further wip

This commit is contained in:
Steven Dee (Jōshin) 2024-06-17 22:59:57 -07:00
parent 3b01802ee3
commit c719dedb0e
No known key found for this signature in database
2 changed files with 147 additions and 3 deletions

View file

@ -25,10 +25,13 @@ struct shared_control
constexpr shared_control() noexcept : shared(0), weak(0) constexpr shared_control() noexcept : shared(0), weak(0)
{ {
} }
shared_control(const shared_control&) = delete; shared_control(const shared_control&) = delete;
virtual ~shared_control() virtual ~shared_control()
{ {
} }
void add_shared() noexcept; void add_shared() noexcept;
void release_shared() noexcept; void release_shared() noexcept;
void add_weak() noexcept; void add_weak() noexcept;
@ -46,7 +49,7 @@ struct shared_pointer : shared_control
{ {
T* p; T* p;
static shared_pointer* make(T* p) static shared_pointer* make(T* const p)
{ {
auto p2 = unique_ptr(p); auto p2 = unique_ptr(p);
auto r = new shared_pointer(p2.release()); auto r = new shared_pointer(p2.release());
@ -54,7 +57,7 @@ struct shared_pointer : shared_control
} }
private: 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> template<typename T>
class shared_ptr class shared_ptr
{ {
public: public:
using element_type = T; // TODO(mrdomino): remove extent?
constexpr shared_ptr(nullptr_t = nullptr) noexcept constexpr shared_ptr(nullptr_t = nullptr) noexcept
: p(nullptr), ctl(nullptr) : 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() ~shared_ptr()
{ {
if (ctl) if (ctl)
ctl->release_shared(); 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: private:
T* p; T* p;
__::shared_control* ctl; __::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 } // namespace ctl
#endif // COSMOPOLITAN_CTL_SHARED_PTR_H_ #endif // COSMOPOLITAN_CTL_SHARED_PTR_H_

View file

@ -18,9 +18,14 @@
#include "ctl/shared_ptr.h" #include "ctl/shared_ptr.h"
// #include <memory>
// #define ctl std
template<typename T> template<typename T>
using Ptr = ctl::shared_ptr<T>; using Ptr = ctl::shared_ptr<T>;
#undef ctl
int int
main() main()
{ {
@ -30,6 +35,35 @@ main()
{ {
Ptr<int> x(new int()); 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; return 0;
} }