Add bad_weak_ptr case

This commit is contained in:
Steven Dee (Jōshin) 2024-08-28 11:31:00 -07:00
parent 38f0504429
commit f6fc17d2e5
No known key found for this signature in database
2 changed files with 46 additions and 1 deletions

View file

@ -4,6 +4,7 @@
#define CTL_SHARED_PTR_H_
#include "conditional.h"
#include "exception.h"
#include "is_convertible.h"
#include "is_void.h"
#include "remove_extent.h"
@ -11,6 +12,15 @@
namespace ctl {
class bad_weak_ptr : public exception
{
public:
const char* what() const noexcept override
{
return "ctl::bad_weak_ptr";
}
};
namespace __ {
static inline __attribute__((always_inline)) void
@ -217,8 +227,12 @@ class shared_ptr
template<typename U>
requires is_convertible_v<U, T>
explicit shared_ptr(const weak_ptr<U>& r) : shared_ptr(r.lock())
explicit shared_ptr(const weak_ptr<U>& r) : p(r.p), rc(r.rc)
{
if (r.expired()) {
throw bad_weak_ptr();
}
rc->keep_shared();
}
// TODO(mrdomino): blocked on ctl::ref
@ -408,6 +422,9 @@ class weak_ptr
}
private:
template<typename U>
friend class shared_ptr;
element_type* p = nullptr;
__::shared_ref* rc = nullptr;
};

View file

@ -36,6 +36,8 @@ make_shared(Args&&... args)
return ctl::make_shared<T, Args...>(ctl::forward<Args>(args)...);
}
using bad_weak_ptr = ctl::bad_weak_ptr;
#undef ctl
static int g = 0;
@ -215,6 +217,32 @@ main()
return 20;
}
{
// Expired weak pointers lock to nullptr, and throw when promoted to
// shared pointer by constructor.
auto x = make_shared<int>();
weak_ptr<int> y(x);
x.reset();
if (y.lock())
return 21;
int caught = 0;
try {
shared_ptr<int> z(y);
} catch (bad_weak_ptr& e) {
caught = 1;
}
if (!caught)
return 22;
}
{
// nullptr is always expired.
shared_ptr<int> x(nullptr);
weak_ptr<int> y(x);
if (!y.expired())
return 23;
}
// TODO(mrdomino): exercise threads / races. The reference count should be
// atomically maintained.