From da5817816d4fd433ced56576d2cad98df5b238d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steven=20Dee=20=28J=C5=8Dshin=29?= Date: Wed, 19 Jun 2024 22:53:37 -0700 Subject: [PATCH] Basics of make_shared with anonymous union --- ctl/shared_ptr.h | 52 +++++++++++++++++++++++++++++++++++++ test/ctl/shared_ptr_test.cc | 11 ++++++++ 2 files changed, 63 insertions(+) diff --git a/ctl/shared_ptr.h b/ctl/shared_ptr.h index f902b7c65..7702a99b0 100644 --- a/ctl/shared_ptr.h +++ b/ctl/shared_ptr.h @@ -2,6 +2,7 @@ // vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi #ifndef COSMOPOLITAN_CTL_SHARED_PTR_H_ #define COSMOPOLITAN_CTL_SHARED_PTR_H_ +#include "new.h" #include "unique_ptr.h" namespace ctl { @@ -72,6 +73,39 @@ struct shared_pointer : shared_control } }; +template +struct shared_emplace : shared_control +{ + union { + T t; + }; + + template + void construct(Args&&... args) { + ::new (&t) T(ctl::forward(args)...); + } + + static unique_ptr make_unique() + { + return new shared_emplace(); + } + +private: + explicit constexpr shared_emplace() noexcept + { + } + + void on_zero_shared() noexcept override + { + t.~T(); + } + + void on_zero_weak() noexcept override + { + delete this; + } +}; + } // namespace __ struct bad_weak_ptr : ctl::exception @@ -203,10 +237,28 @@ class shared_ptr // TODO(mrdomino): owner_before(weak_ptr const&) private: + constexpr shared_ptr(T* const p, __::shared_control* rc) noexcept + : p(p), rc(rc) + { + } + + template + friend shared_ptr make_shared(Args&&... args); + T* p; __::shared_control* rc; }; +template +shared_ptr make_shared(Args&&... args) +{ + auto rc = __::shared_emplace::make_unique(); + rc->construct(ctl::forward(args)...); + auto r = shared_ptr(&rc->t, rc.get()); + rc.release(); + return r; +} + // TODO(mrdomino): non-member functions (make_shared et al) // TODO(mrdomino): weak_ptr diff --git a/test/ctl/shared_ptr_test.cc b/test/ctl/shared_ptr_test.cc index 41cf41ffa..8fee9361f 100644 --- a/test/ctl/shared_ptr_test.cc +++ b/test/ctl/shared_ptr_test.cc @@ -24,6 +24,11 @@ template using Ptr = ctl::shared_ptr; +template +Ptr Mk(Args&&... args) { + return ctl::make_shared(ctl::forward(args)...); +} + #undef ctl int @@ -62,6 +67,12 @@ main() } #endif + { + auto x = Mk(5); + if (x.use_count() != 1) + return 8; + } + // TODO(mrdomino): exercise more of API // TODO(mrdomino): threading stress-test