mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-02-25 07:19:02 +00:00
Enable STL-style enable_shared_from_this (#1295)
This commit is contained in:
parent
6397999fca
commit
ef62730ae4
2 changed files with 96 additions and 4 deletions
|
@ -4,6 +4,7 @@
|
||||||
#define CTL_SHARED_PTR_H_
|
#define CTL_SHARED_PTR_H_
|
||||||
|
|
||||||
#include "exception.h"
|
#include "exception.h"
|
||||||
|
#include "is_base_of.h"
|
||||||
#include "is_convertible.h"
|
#include "is_convertible.h"
|
||||||
#include "remove_extent.h"
|
#include "remove_extent.h"
|
||||||
#include "unique_ptr.h"
|
#include "unique_ptr.h"
|
||||||
|
@ -201,10 +202,7 @@ class shared_ptr
|
||||||
|
|
||||||
template<typename U, typename D>
|
template<typename U, typename D>
|
||||||
requires __::shared_ptr_compatible<T, U>
|
requires __::shared_ptr_compatible<T, U>
|
||||||
shared_ptr(U* const p, D d)
|
shared_ptr(U*, D);
|
||||||
: p(p), rc(__::shared_pointer<U, D>::make(p, move(d)))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename U>
|
template<typename U>
|
||||||
shared_ptr(const shared_ptr<U>& r, element_type* p) noexcept
|
shared_ptr(const shared_ptr<U>& r, element_type* p) noexcept
|
||||||
|
@ -443,6 +441,62 @@ class weak_ptr
|
||||||
__::shared_ref* rc = nullptr;
|
__::shared_ref* rc = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
class enable_shared_from_this
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
shared_ptr<T> shared_from_this()
|
||||||
|
{
|
||||||
|
return shared_ptr<T>(weak_this);
|
||||||
|
}
|
||||||
|
shared_ptr<T const> shared_from_this() const
|
||||||
|
{
|
||||||
|
return shared_ptr<T>(weak_this);
|
||||||
|
}
|
||||||
|
|
||||||
|
weak_ptr<T> weak_from_this()
|
||||||
|
{
|
||||||
|
return weak_this;
|
||||||
|
}
|
||||||
|
weak_ptr<T const> weak_from_this() const
|
||||||
|
{
|
||||||
|
return weak_this;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
constexpr enable_shared_from_this() noexcept = default;
|
||||||
|
enable_shared_from_this(const enable_shared_from_this& r) noexcept
|
||||||
|
{
|
||||||
|
}
|
||||||
|
~enable_shared_from_this() = default;
|
||||||
|
|
||||||
|
enable_shared_from_this& operator=(
|
||||||
|
const enable_shared_from_this& r) noexcept
|
||||||
|
{
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
template<typename U, typename... Args>
|
||||||
|
friend shared_ptr<U> make_shared(Args&&...);
|
||||||
|
|
||||||
|
template<typename U>
|
||||||
|
friend class shared_ptr;
|
||||||
|
|
||||||
|
weak_ptr<T> weak_this;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
template<typename U, typename D>
|
||||||
|
requires __::shared_ptr_compatible<T, U>
|
||||||
|
shared_ptr<T>::shared_ptr(U* const p, D d)
|
||||||
|
: p(p), rc(__::shared_pointer<U, D>::make(p, move(d)))
|
||||||
|
{
|
||||||
|
if constexpr (is_base_of_v<enable_shared_from_this<U>, U>) {
|
||||||
|
p->weak_this = *this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T, typename... Args>
|
template<typename T, typename... Args>
|
||||||
shared_ptr<T>
|
shared_ptr<T>
|
||||||
make_shared(Args&&... args)
|
make_shared(Args&&... args)
|
||||||
|
@ -452,6 +506,9 @@ make_shared(Args&&... args)
|
||||||
shared_ptr<T> r;
|
shared_ptr<T> r;
|
||||||
r.p = &rc->t;
|
r.p = &rc->t;
|
||||||
r.rc = rc.release();
|
r.rc = rc.release();
|
||||||
|
if constexpr (is_base_of_v<enable_shared_from_this<T>, T>) {
|
||||||
|
r->weak_this = r;
|
||||||
|
}
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
// #define ctl std
|
// #define ctl std
|
||||||
|
|
||||||
using ctl::bad_weak_ptr;
|
using ctl::bad_weak_ptr;
|
||||||
|
using ctl::enable_shared_from_this;
|
||||||
using ctl::make_shared;
|
using ctl::make_shared;
|
||||||
using ctl::move;
|
using ctl::move;
|
||||||
using ctl::shared_ptr;
|
using ctl::shared_ptr;
|
||||||
|
@ -66,6 +67,27 @@ struct Base
|
||||||
struct Derived : Base
|
struct Derived : Base
|
||||||
{};
|
{};
|
||||||
|
|
||||||
|
class SharedThis : public enable_shared_from_this<SharedThis>
|
||||||
|
{
|
||||||
|
struct Private
|
||||||
|
{
|
||||||
|
explicit Private() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
SharedThis(Private)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static shared_ptr<SharedThis> create()
|
||||||
|
{
|
||||||
|
return make_shared<SharedThis>(Private());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class CanShareThis : public enable_shared_from_this<CanShareThis>
|
||||||
|
{};
|
||||||
|
|
||||||
int
|
int
|
||||||
main()
|
main()
|
||||||
{
|
{
|
||||||
|
@ -241,6 +263,19 @@ main()
|
||||||
return 23;
|
return 23;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// enable_shared_from_this allows shared pointers to self.
|
||||||
|
auto x = SharedThis::create();
|
||||||
|
auto y = x->shared_from_this();
|
||||||
|
if (x.use_count() != 2 || x.get() != y.get())
|
||||||
|
return 24;
|
||||||
|
auto z = new CanShareThis();
|
||||||
|
auto w = shared_ptr<CanShareThis>(z);
|
||||||
|
auto v = w->shared_from_this();
|
||||||
|
if (w.use_count() != 2 || w.get() != v.get())
|
||||||
|
return 25;
|
||||||
|
}
|
||||||
|
|
||||||
// TODO(mrdomino): exercise threads / races. The reference count should be
|
// TODO(mrdomino): exercise threads / races. The reference count should be
|
||||||
// atomically maintained.
|
// atomically maintained.
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue