mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-08-03 08:20:28 +00:00
further wip
This commit is contained in:
parent
3b01802ee3
commit
c719dedb0e
2 changed files with 147 additions and 3 deletions
116
ctl/shared_ptr.h
116
ctl/shared_ptr.h
|
@ -25,10 +25,13 @@ struct shared_control
|
|||
constexpr shared_control() noexcept : shared(0), weak(0)
|
||||
{
|
||||
}
|
||||
|
||||
shared_control(const shared_control&) = delete;
|
||||
|
||||
virtual ~shared_control()
|
||||
{
|
||||
}
|
||||
|
||||
void add_shared() noexcept;
|
||||
void release_shared() noexcept;
|
||||
void add_weak() noexcept;
|
||||
|
@ -46,7 +49,7 @@ struct shared_pointer : shared_control
|
|||
{
|
||||
T* p;
|
||||
|
||||
static shared_pointer* make(T* p)
|
||||
static shared_pointer* make(T* const p)
|
||||
{
|
||||
auto p2 = unique_ptr(p);
|
||||
auto r = new shared_pointer(p2.release());
|
||||
|
@ -54,7 +57,7 @@ struct shared_pointer : shared_control
|
|||
}
|
||||
|
||||
private:
|
||||
shared_pointer(T* p) noexcept : p(p)
|
||||
explicit constexpr shared_pointer(T* const p) noexcept : p(p)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -79,29 +82,136 @@ struct bad_weak_ptr : ctl::exception
|
|||
}
|
||||
};
|
||||
|
||||
// TODO(mrdomino): typename D = default_delete<T>
|
||||
template<typename T>
|
||||
class shared_ptr
|
||||
{
|
||||
public:
|
||||
using element_type = T; // TODO(mrdomino): remove extent?
|
||||
|
||||
constexpr shared_ptr(nullptr_t = nullptr) noexcept
|
||||
: p(nullptr), ctl(nullptr)
|
||||
{
|
||||
}
|
||||
shared_ptr(T* const p) : p(p), ctl(__::shared_pointer<T>::make(p))
|
||||
|
||||
explicit shared_ptr(auto* const p) : p(p), ctl(__::shared_pointer<T>::make(p))
|
||||
{
|
||||
}
|
||||
|
||||
shared_ptr(const shared_ptr& r) noexcept : p(r.p), ctl(r.ctl)
|
||||
{
|
||||
if (ctl)
|
||||
ctl->add_shared();
|
||||
}
|
||||
|
||||
shared_ptr(shared_ptr&& r) noexcept : p(r.p), ctl(r.ctl)
|
||||
{
|
||||
r.p = nullptr;
|
||||
r.ctl = nullptr;
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
shared_ptr(const shared_ptr<U>& r, T* const p) noexcept : p(p), ctl(r.ctl)
|
||||
{
|
||||
if (ctl)
|
||||
ctl->add_shared();
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
shared_ptr(shared_ptr<U>&& r, T* const p) noexcept : p(p), ctl(r.ctl)
|
||||
{
|
||||
r.p = nullptr;
|
||||
r.ctl = nullptr;
|
||||
}
|
||||
|
||||
// TODO(mrdomino): moar ctors
|
||||
|
||||
~shared_ptr()
|
||||
{
|
||||
if (ctl)
|
||||
ctl->release_shared();
|
||||
}
|
||||
|
||||
shared_ptr& operator=(shared_ptr r) noexcept
|
||||
{
|
||||
swap(r);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void reset() noexcept
|
||||
{
|
||||
if (ctl)
|
||||
ctl->release_shared();
|
||||
p = nullptr;
|
||||
ctl = nullptr;
|
||||
}
|
||||
|
||||
void reset(auto* const p2)
|
||||
{
|
||||
shared_ptr<T>(p2).swap(*this);
|
||||
}
|
||||
|
||||
void swap(shared_ptr& r) noexcept
|
||||
{
|
||||
using std::swap;
|
||||
swap(p, r.p);
|
||||
swap(ctl, r.ctl);
|
||||
}
|
||||
|
||||
element_type* get() const noexcept
|
||||
{
|
||||
return p;
|
||||
}
|
||||
|
||||
// TODO(mrdomino): fix for shared_ptr<void>
|
||||
T& operator*() const noexcept
|
||||
{
|
||||
if (!p)
|
||||
__builtin_trap();
|
||||
return *p;
|
||||
}
|
||||
|
||||
// TODO(mrdomino): fix for shared_ptr<T[]>
|
||||
T* operator->() const noexcept
|
||||
{
|
||||
if (!p)
|
||||
__builtin_trap();
|
||||
return *p;
|
||||
}
|
||||
|
||||
element_type& operator[](ptrdiff_t i) const
|
||||
{
|
||||
return *(p + i);
|
||||
}
|
||||
|
||||
size_t use_count() const noexcept
|
||||
{
|
||||
return ctl ? ctl->use_count() : 0;
|
||||
}
|
||||
|
||||
explicit operator bool() const noexcept
|
||||
{
|
||||
return p;
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
bool owner_before(const shared_ptr<U>& r) const noexcept
|
||||
{
|
||||
return p < r.p;
|
||||
}
|
||||
|
||||
// TODO(mrdomino): owner_before(weak_ptr const&)
|
||||
|
||||
private:
|
||||
T* p;
|
||||
__::shared_control* ctl;
|
||||
};
|
||||
|
||||
// TODO(mrdomino): non-member functions (make_shared et al)
|
||||
// TODO(mrdomino): weak_ptr
|
||||
|
||||
// TODO(someday): std::atomic<std::shared_ptr>
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // COSMOPOLITAN_CTL_SHARED_PTR_H_
|
||||
|
|
|
@ -18,9 +18,14 @@
|
|||
|
||||
#include "ctl/shared_ptr.h"
|
||||
|
||||
// #include <memory>
|
||||
// #define ctl std
|
||||
|
||||
template<typename T>
|
||||
using Ptr = ctl::shared_ptr<T>;
|
||||
|
||||
#undef ctl
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
|
@ -30,6 +35,35 @@ main()
|
|||
|
||||
{
|
||||
Ptr<int> x(new int());
|
||||
if (x.use_count() != 1)
|
||||
return 1;
|
||||
Ptr<int> y(x);
|
||||
if (x.use_count() != 2 || y.use_count() != 2)
|
||||
return 2;
|
||||
x.reset();
|
||||
if (x.use_count() || y.use_count() != 1)
|
||||
return 3;
|
||||
}
|
||||
|
||||
{
|
||||
Ptr<int> x(new int());
|
||||
x.reset(new int(2));
|
||||
if (x.use_count() != 1)
|
||||
return 5;
|
||||
}
|
||||
|
||||
// TODO(mrdomino):
|
||||
#if 0
|
||||
{
|
||||
Ptr<int> x(new int);
|
||||
Ptr<void> y(x, nullptr);
|
||||
if (x.use_count() != 2)
|
||||
return 7;
|
||||
}
|
||||
#endif
|
||||
|
||||
// TODO(mrdomino): exercise more of API
|
||||
// TODO(mrdomino): threading stress-test
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue