mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-08-03 08:20:28 +00:00
wip Implement ctl::shared_ptr
This code does not segfault and it compiles cleanly, and it took a while to get here.
This commit is contained in:
parent
a795017416
commit
b16cf2ee97
3 changed files with 239 additions and 0 deletions
97
ctl/shared_ptr.cc
Normal file
97
ctl/shared_ptr.cc
Normal file
|
@ -0,0 +1,97 @@
|
|||
// -*- mode:c++; indent-tabs-mode:nil; c-basic-offset:4; coding:utf-8 -*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
//
|
||||
// Copyright 2024 Justine Alexandra Roberts Tunney
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for
|
||||
// any purpose with or without fee is hereby granted, provided that the
|
||||
// above copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||
// WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||
// WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
||||
// AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
// DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||
// PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
// TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
// PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
#include "shared_ptr.h"
|
||||
|
||||
#include "libc/intrin/atomic.h"
|
||||
|
||||
namespace {
|
||||
|
||||
inline void
|
||||
incref(_Atomic(size_t)* r)
|
||||
{
|
||||
size_t r2 = atomic_fetch_add_explicit(r, 1, memory_order_relaxed);
|
||||
if (r2 > ((size_t)-1) >> 1)
|
||||
__builtin_trap();
|
||||
}
|
||||
|
||||
inline int
|
||||
decref(_Atomic(size_t)* r)
|
||||
{
|
||||
if (!atomic_fetch_sub_explicit(r, 1, memory_order_release)) {
|
||||
atomic_thread_fence(memory_order_acquire);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline size_t
|
||||
getref(const _Atomic(size_t)* r)
|
||||
{
|
||||
return atomic_load_explicit(r, memory_order_relaxed);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace ctl {
|
||||
|
||||
namespace __ {
|
||||
|
||||
void
|
||||
shared_control::add_shared() noexcept
|
||||
{
|
||||
incref(&shared);
|
||||
}
|
||||
|
||||
void
|
||||
shared_control::release_shared() noexcept
|
||||
{
|
||||
if (decref(&shared)) {
|
||||
on_zero_shared();
|
||||
release_weak();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
shared_control::add_weak() noexcept
|
||||
{
|
||||
incref(&weak);
|
||||
}
|
||||
|
||||
void
|
||||
shared_control::release_weak() noexcept
|
||||
{
|
||||
if (decref(&weak))
|
||||
on_zero_weak();
|
||||
}
|
||||
|
||||
size_t
|
||||
shared_control::use_count() const noexcept
|
||||
{
|
||||
return 1 + getref(&shared);
|
||||
}
|
||||
|
||||
size_t
|
||||
shared_control::weak_count() const noexcept
|
||||
{
|
||||
return getref(&weak);
|
||||
}
|
||||
|
||||
} // namespace __
|
||||
|
||||
} // namespace ctl
|
107
ctl/shared_ptr.h
Normal file
107
ctl/shared_ptr.h
Normal file
|
@ -0,0 +1,107 @@
|
|||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// 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 "unique_ptr.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
// TODO(mrdomino): move
|
||||
struct exception
|
||||
{
|
||||
virtual const char* what() const noexcept
|
||||
{
|
||||
return "exception";
|
||||
}
|
||||
};
|
||||
|
||||
namespace __ {
|
||||
|
||||
struct shared_control
|
||||
{
|
||||
_Atomic(size_t) shared;
|
||||
_Atomic(size_t) weak;
|
||||
|
||||
constexpr shared_control() noexcept : shared(0), weak(0)
|
||||
{
|
||||
}
|
||||
virtual ~shared_control()
|
||||
{
|
||||
}
|
||||
void add_shared() noexcept;
|
||||
void release_shared() noexcept;
|
||||
void add_weak() noexcept;
|
||||
void release_weak() noexcept;
|
||||
size_t use_count() const noexcept;
|
||||
size_t weak_count() const noexcept;
|
||||
|
||||
private:
|
||||
virtual void on_zero_shared() noexcept = 0;
|
||||
virtual void on_zero_weak() noexcept = 0;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct shared_pointer : shared_control
|
||||
{
|
||||
T* p;
|
||||
|
||||
static shared_pointer* make(T* p)
|
||||
{
|
||||
return new shared_pointer(p);
|
||||
}
|
||||
|
||||
private:
|
||||
shared_pointer(T* p) noexcept : p(p)
|
||||
{
|
||||
}
|
||||
|
||||
void on_zero_shared() noexcept override
|
||||
{
|
||||
delete p;
|
||||
}
|
||||
|
||||
void on_zero_weak() noexcept override
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace __
|
||||
|
||||
struct bad_weak_ptr : ctl::exception
|
||||
{
|
||||
const char* what() const noexcept override
|
||||
{
|
||||
return "bad_weak_ptr";
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class shared_ptr
|
||||
{
|
||||
public:
|
||||
constexpr shared_ptr(nullptr_t = nullptr) noexcept
|
||||
: p(nullptr), ctl(nullptr)
|
||||
{
|
||||
}
|
||||
shared_ptr(T* const p2)
|
||||
{
|
||||
auto hold = ctl::unique_ptr(p2);
|
||||
ctl = __::shared_pointer<T>::make(p2);
|
||||
p = hold.release();
|
||||
}
|
||||
|
||||
~shared_ptr()
|
||||
{
|
||||
if (ctl)
|
||||
ctl->release_shared();
|
||||
}
|
||||
|
||||
private:
|
||||
T* p;
|
||||
__::shared_control* ctl;
|
||||
};
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // COSMOPOLITAN_CTL_SHARED_PTR_H_
|
35
test/ctl/shared_ptr_test.cc
Normal file
35
test/ctl/shared_ptr_test.cc
Normal file
|
@ -0,0 +1,35 @@
|
|||
// -*- mode:c++; indent-tabs-mode:nil; c-basic-offset:4; coding:utf-8 -*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
//
|
||||
// Copyright 2024 Justine Alexandra Roberts Tunney
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for
|
||||
// any purpose with or without fee is hereby granted, provided that the
|
||||
// above copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||
// WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||
// WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
||||
// AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
// DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||
// PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
// TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
// PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
#include "ctl/shared_ptr.h"
|
||||
|
||||
template<typename T>
|
||||
using Ptr = ctl::shared_ptr<T>;
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
{
|
||||
Ptr<int> x;
|
||||
}
|
||||
|
||||
{
|
||||
Ptr<int> x(new int());
|
||||
}
|
||||
return 0;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue