Commit e559539b authored by Kirk Shoop's avatar Kirk Shoop Committed by Facebook GitHub Bot

MasterPtr -> PrimaryPtr

Summary: name change

Reviewed By: LeeHowes

Differential Revision: D22162997

fbshipit-source-id: 8431a25fe46df2b5e4bfb162fc982b1c55bce7ce
parent 42d5bf14
......@@ -28,44 +28,44 @@
namespace folly {
template <typename T>
class EnableMasterFromThis;
class EnablePrimaryFromThis;
template <typename T>
class MasterPtr;
class PrimaryPtr;
template <typename T>
class MasterPtrRef;
class PrimaryPtrRef;
namespace detail {
struct publicallyDerivedFromEnableMasterFromThis_fn {
struct publicallyDerivedFromEnablePrimaryFromThis_fn {
template <class T>
void operator()(const EnableMasterFromThis<T>&) const {}
void operator()(const EnablePrimaryFromThis<T>&) const {}
};
} // namespace detail
template <class T>
constexpr bool is_enable_master_from_this_v = folly::
is_invocable_v<detail::publicallyDerivedFromEnableMasterFromThis_fn, T>;
is_invocable_v<detail::publicallyDerivedFromEnablePrimaryFromThis_fn, T>;
template <typename T>
using is_enable_master_from_this =
std::bool_constant<is_enable_master_from_this_v<T>>;
/**
* EnableMasterFromThis provides an object with appropriate access to the
* functionality of the MasterPtr holding this.
* EnablePrimaryFromThis provides an object with appropriate access to the
* functionality of the PrimaryPtr holding this.
*/
template <typename T>
class EnableMasterFromThis {
// initializes members when the MasterPtr for this is constructed
class EnablePrimaryFromThis {
// initializes members when the PrimaryPtr for this is constructed
//
// used by the MasterPtr for this, to invoke the EnableMasterFromThis base of
// T, if it exists.
// used by the PrimaryPtr for this, to invoke the EnablePrimaryFromThis base
// of T, if it exists.
template <
class O,
class Master,
std::enable_if_t<is_enable_master_from_this_v<O>, int> = 0>
static void set(EnableMasterFromThis<O>* that, Master& m) {
static void set(EnablePrimaryFromThis<O>* that, Master& m) {
that->outerPtrWeak_ = m.outerPtrWeak_;
}
......@@ -76,24 +76,24 @@ class EnableMasterFromThis {
static void set(O*, Master&) {}
public:
// Gets a non-owning reference to the pointer. MasterPtr::join() and the
// MasterPtr::cleanup() work do *NOT* wait for outstanding MasterPtrRef
// Gets a non-owning reference to the pointer. PrimaryPtr::join() and the
// PrimaryPtr::cleanup() work do *NOT* wait for outstanding PrimaryPtrRef
// objects to be released.
MasterPtrRef<T> masterRefFromThis() {
return MasterPtrRef<T>(outerPtrWeak_);
PrimaryPtrRef<T> masterRefFromThis() {
return PrimaryPtrRef<T>(outerPtrWeak_);
}
// Gets a non-owning const reference to the pointer. MasterPtr::join() and the
// MasterPtr::cleanup() work do *NOT* wait for outstanding MasterPtrRef
// Gets a non-owning const reference to the pointer. PrimaryPtr::join() and
// the PrimaryPtr::cleanup() work do *NOT* wait for outstanding PrimaryPtrRef
// objects to be released.
MasterPtrRef<const T> masterRefFromThis() const {
return MasterPtrRef<const T>(outerPtrWeak_);
PrimaryPtrRef<const T> masterRefFromThis() const {
return PrimaryPtrRef<const T>(outerPtrWeak_);
}
// Attempts to lock a pointer. Returns null if pointer is not set or if
// MasterPtr::join() was called or the MasterPtr::cleanup() task was started
// (even if the call to MasterPtr::join() hasn't returned yet and the
// MasterPtr::cleanup() task has not completed yet).
// PrimaryPtr::join() was called or the PrimaryPtr::cleanup() task was started
// (even if the call to PrimaryPtr::join() hasn't returned yet and the
// PrimaryPtr::cleanup() task has not completed yet).
std::shared_ptr<T> masterLockFromThis() {
if (auto outerPtr = outerPtrWeak_.lock()) {
return *outerPtr;
......@@ -102,9 +102,9 @@ class EnableMasterFromThis {
}
// Attempts to lock a pointer. Returns null if pointer is not set or if
// MasterPtr::join() was called or the MasterPtr::cleanup() task was started
// (even if the call to MasterPtr::join() hasn't returned yet and the
// MasterPtr::cleanup() task has not completed yet).
// PrimaryPtr::join() was called or the PrimaryPtr::cleanup() task was started
// (even if the call to PrimaryPtr::join() hasn't returned yet and the
// PrimaryPtr::cleanup() task has not completed yet).
std::shared_ptr<T const> masterLockFromThis() const {
if (!*this) {
return nullptr;
......@@ -117,24 +117,23 @@ class EnableMasterFromThis {
private:
template <class>
friend class MasterPtr;
friend class PrimaryPtr;
std::weak_ptr<std::shared_ptr<T>> outerPtrWeak_;
};
/**
* MasterPtr should be used to achieve deterministic destruction of objects with
* shared ownership.
* Once an object is managed by a MasterPtr, shared_ptrs can be obtained
* pointing to that object. However destroying those shared_ptrs will never call
* the object destructor inline. To destroy the object, join() method must be
* called on MasterPtr or the task returned from cleanup() must be completed,
* which will wait for all shared_ptrs to be released and then call the object
* destructor on the caller supplied execution context.
* PrimaryPtr should be used to achieve deterministic destruction of objects
* with shared ownership. Once an object is managed by a PrimaryPtr, shared_ptrs
* can be obtained pointing to that object. However destroying those shared_ptrs
* will never call the object destructor inline. To destroy the object, join()
* method must be called on PrimaryPtr or the task returned from cleanup() must
* be completed, which will wait for all shared_ptrs to be released and then
* call the object destructor on the caller supplied execution context.
*/
template <typename T>
class MasterPtr {
// retrieves nested cleanup() work from innerPtr_. Called when the MasterPtr
class PrimaryPtr {
// retrieves nested cleanup() work from innerPtr_. Called when the PrimaryPtr
// cleanup() task has finished waiting for outstanding references
//
template <class Cleanup, std::enable_if_t<is_cleanup_v<Cleanup>, int> = 0>
......@@ -148,14 +147,14 @@ class MasterPtr {
}
public:
MasterPtr() = delete;
PrimaryPtr() = delete;
template <class T2, class Deleter>
MasterPtr(std::unique_ptr<T2, Deleter> ptr) {
PrimaryPtr(std::unique_ptr<T2, Deleter> ptr) {
set(std::move(ptr));
}
~MasterPtr() {
~PrimaryPtr() {
if (*this) {
LOG(FATAL) << "MasterPtr has to be joined explicitly.";
LOG(FATAL) << "PrimaryPtr has to be joined explicitly.";
}
}
......@@ -223,7 +222,7 @@ class MasterPtr {
template <class T2, class Deleter>
void set(std::unique_ptr<T2, Deleter> ptr) {
if (*this) {
LOG(FATAL) << "MasterPtr has to be joined before being set.";
LOG(FATAL) << "PrimaryPtr has to be joined before being set.";
}
if (!ptr) {
......@@ -246,21 +245,21 @@ class MasterPtr {
outerPtrWeak_ = outerPtrShared_ =
std::make_shared<std::shared_ptr<T>>(innerPtrShared);
// attaches optional EnableMasterFromThis base of innerPtr_ to this
// MasterPtr
EnableMasterFromThis<T>::set(innerPtr_.get(), *this);
// attaches optional EnablePrimaryFromThis base of innerPtr_ to this
// PrimaryPtr
EnablePrimaryFromThis<T>::set(innerPtr_.get(), *this);
}
// Gets a non-owning reference to the pointer. join() and the cleanup() work
// do *NOT* wait for outstanding MasterPtrRef objects to be released.
MasterPtrRef<T> ref() const {
return MasterPtrRef<T>(outerPtrWeak_);
// do *NOT* wait for outstanding PrimaryPtrRef objects to be released.
PrimaryPtrRef<T> ref() const {
return PrimaryPtrRef<T>(outerPtrWeak_);
}
private:
template <class>
friend class EnableMasterFromThis;
friend class MasterPtrRef<T>;
friend class EnablePrimaryFromThis;
friend class PrimaryPtrRef<T>;
folly::SemiFuture<folly::Unit> unreferenced_;
std::shared_ptr<std::shared_ptr<T>> outerPtrShared_;
......@@ -269,12 +268,12 @@ class MasterPtr {
};
/**
* MasterPtrRef is a non-owning reference to the pointer. MasterPtr::join()
* and the MasterPtr::cleanup() work do *NOT* wait for outstanding MasterPtrRef
* objects to be released.
* PrimaryPtrRef is a non-owning reference to the pointer. PrimaryPtr::join()
* and the PrimaryPtr::cleanup() work do *NOT* wait for outstanding
* PrimaryPtrRef objects to be released.
*/
template <typename T>
class MasterPtrRef {
class PrimaryPtrRef {
public:
// Attempts to lock a pointer. Returns null if pointer is not set or if
// join() was called or cleanup() work was started (even if the call to join()
......@@ -288,10 +287,10 @@ class MasterPtrRef {
private:
template <class>
friend class EnableMasterFromThis;
friend class EnablePrimaryFromThis;
template <class>
friend class MasterPtr;
/* implicit */ MasterPtrRef(std::weak_ptr<std::shared_ptr<T>> outerPtrWeak)
friend class PrimaryPtr;
/* implicit */ PrimaryPtrRef(std::weak_ptr<std::shared_ptr<T>> outerPtrWeak)
: outerPtrWeak_(std::move(outerPtrWeak)) {}
std::weak_ptr<std::shared_ptr<T>> outerPtrWeak_;
......
......@@ -103,7 +103,7 @@ class AsyncScope {
////////
// Implement the async-cleanup pattern.
// Implement the async cleanup 'cleanup()' pattern used by MasterPtr.
// Implement the async cleanup 'cleanup()' pattern used by PrimaryPtr.
//
// If you have previuosly called add() then you must call cleanup()
// and wait for the retuned future to complete before the AsyncScope
......
......@@ -18,39 +18,39 @@
#include <folly/executors/CPUThreadPoolExecutor.h>
#include <folly/executors/ManualExecutor.h>
#include <folly/experimental/MasterPtr.h>
#include <folly/experimental/PrimaryPtr.h>
#include <folly/portability/GTest.h>
#include <folly/synchronization/Baton.h>
using namespace std::literals::chrono_literals;
TEST(MasterPtrTest, Basic) {
EXPECT_TRUE(folly::is_cleanup_v<folly::MasterPtr<int>>);
TEST(PrimaryPtrTest, Basic) {
EXPECT_TRUE(folly::is_cleanup_v<folly::PrimaryPtr<int>>);
auto ptr = std::make_unique<int>(42);
auto rawPtr = ptr.get();
folly::MasterPtr<int> masterPtr(std::move(ptr));
auto masterPtrRef = masterPtr.ref();
EXPECT_TRUE(!!masterPtr);
folly::PrimaryPtr<int> primaryPtr(std::move(ptr));
auto primaryPtrRef = primaryPtr.ref();
EXPECT_TRUE(!!primaryPtr);
auto lockedPtr1 = masterPtr.lock();
auto lockedPtr2 = masterPtrRef.lock();
auto lockedPtr1 = primaryPtr.lock();
auto lockedPtr2 = primaryPtrRef.lock();
EXPECT_EQ(lockedPtr1.get(), rawPtr);
EXPECT_EQ(lockedPtr2.get(), rawPtr);
EXPECT_EQ(lockedPtr1.use_count(), 3);
EXPECT_EQ(lockedPtr2.use_count(), 3);
EXPECT_TRUE(!!masterPtr);
EXPECT_TRUE(!!primaryPtr);
auto joinFuture = std::async(std::launch::async, [&] {
masterPtr.join();
EXPECT_TRUE(!masterPtr);
primaryPtr.join();
EXPECT_TRUE(!primaryPtr);
});
auto lockFailFuture = std::async(std::launch::async, [&] {
while (masterPtr.lock()) {
while (primaryPtr.lock()) {
std::this_thread::yield();
}
});
......@@ -62,8 +62,8 @@ TEST(MasterPtrTest, Basic) {
EXPECT_EQ(lockedPtr1.use_count(), 2);
EXPECT_EQ(lockedPtr2.use_count(), 2);
EXPECT_EQ(masterPtr.lock().get(), nullptr);
EXPECT_EQ(masterPtrRef.lock().get(), nullptr);
EXPECT_EQ(primaryPtr.lock().get(), nullptr);
EXPECT_EQ(primaryPtrRef.lock().get(), nullptr);
EXPECT_EQ(
joinFuture.wait_for(std::chrono::milliseconds{100}),
......@@ -76,47 +76,47 @@ TEST(MasterPtrTest, Basic) {
joinFuture.wait_for(std::chrono::milliseconds{100}),
std::future_status::ready);
EXPECT_TRUE(!masterPtr);
EXPECT_TRUE(!primaryPtr);
ptr = std::make_unique<int>(42);
rawPtr = ptr.get();
masterPtr.set(std::move(ptr));
EXPECT_TRUE(!!masterPtr);
lockedPtr1 = masterPtr.lock();
primaryPtr.set(std::move(ptr));
EXPECT_TRUE(!!primaryPtr);
lockedPtr1 = primaryPtr.lock();
EXPECT_EQ(lockedPtr1.get(), rawPtr);
lockedPtr1.reset();
masterPtr.join();
EXPECT_EQ(masterPtr.lock().get(), nullptr);
EXPECT_TRUE(!masterPtr);
primaryPtr.join();
EXPECT_EQ(primaryPtr.lock().get(), nullptr);
EXPECT_TRUE(!primaryPtr);
}
struct Mastered : folly::Cleanup, folly::EnableMasterFromThis<Mastered> {
folly::MasterPtr<int> nested_;
struct Primed : folly::Cleanup, folly::EnablePrimaryFromThis<Primed> {
folly::PrimaryPtr<int> nested_;
folly::CPUThreadPoolExecutor pool_;
Mastered() : nested_(std::make_unique<int>(42)), pool_(4) {
Primed() : nested_(std::make_unique<int>(42)), pool_(4) {
addCleanup(nested_);
addCleanup(
folly::makeSemiFuture().defer([this](auto&&) { this->pool_.join(); }));
}
using folly::Cleanup::addCleanup;
std::shared_ptr<Mastered> get_shared() {
std::shared_ptr<Primed> get_shared() {
return masterLockFromThis();
}
};
TEST(MasterPtrTest, BasicCleanup) {
auto ptr = std::make_unique<Mastered>();
TEST(PrimaryPtrTest, BasicCleanup) {
auto ptr = std::make_unique<Primed>();
folly::MasterPtr<Mastered> masterPtr(std::move(ptr));
folly::PrimaryPtr<Primed> primaryPtr(std::move(ptr));
int phase = 0;
int index = 0;
masterPtr.lock()->addCleanup(
primaryPtr.lock()->addCleanup(
folly::makeSemiFuture().deferValue([&, expected = index++](folly::Unit) {
EXPECT_EQ(phase, 1);
EXPECT_EQ(--index, expected);
}));
masterPtr.lock()->addCleanup(
primaryPtr.lock()->addCleanup(
folly::makeSemiFuture().deferValue([&, expected = index++](folly::Unit) {
EXPECT_EQ(phase, 1);
EXPECT_EQ(--index, expected);
......@@ -125,7 +125,7 @@ TEST(MasterPtrTest, BasicCleanup) {
folly::ManualExecutor exec;
phase = 1;
masterPtr.cleanup()
primaryPtr.cleanup()
.within(1s)
.via(folly::getKeepAliveToken(exec))
.getVia(&exec);
......@@ -135,25 +135,25 @@ TEST(MasterPtrTest, BasicCleanup) {
#if defined(__has_feature)
#if !__has_feature(address_sanitizer)
TEST(MasterPtrTest, Errors) {
auto ptr = std::make_unique<Mastered>();
TEST(PrimaryPtrTest, Errors) {
auto ptr = std::make_unique<Primed>();
auto masterPtr = std::make_unique<folly::MasterPtr<Mastered>>(std::move(ptr));
auto primaryPtr = std::make_unique<folly::PrimaryPtr<Primed>>(std::move(ptr));
masterPtr->lock()->addCleanup(folly::makeSemiFuture().deferValue(
primaryPtr->lock()->addCleanup(folly::makeSemiFuture().deferValue(
[](folly::Unit) { EXPECT_TRUE(false); }));
masterPtr->lock()->addCleanup(
primaryPtr->lock()->addCleanup(
folly::makeSemiFuture<folly::Unit>(std::runtime_error("failed cleanup")));
EXPECT_EXIT(
masterPtr->set(std::unique_ptr<Mastered>{}),
primaryPtr->set(std::unique_ptr<Primed>{}),
testing::KilledBySignal(SIGABRT),
".*joined before.*");
folly::ManualExecutor exec;
EXPECT_EXIT(
masterPtr->cleanup()
primaryPtr->cleanup()
.within(1s)
.via(folly::getKeepAliveToken(exec))
.getVia(&exec),
......@@ -161,16 +161,16 @@ TEST(MasterPtrTest, Errors) {
".*noexcept.*");
EXPECT_EXIT(
masterPtr.reset(), testing::KilledBySignal(SIGABRT), ".*MasterPtr.*");
primaryPtr.reset(), testing::KilledBySignal(SIGABRT), ".*PrimaryPtr.*");
// must leak the MasterPtr as its destructor will abort.
(void)masterPtr.release();
// must leak the PrimaryPtr as its destructor will abort.
(void)primaryPtr.release();
}
#endif
#endif
TEST(MasterPtrTest, Invariants) {
struct BadDerived : Mastered {
TEST(PrimaryPtrTest, Invariants) {
struct BadDerived : Primed {
~BadDerived() {
EXPECT_EXIT(
addCleanup(folly::makeSemiFuture().deferValue(
......@@ -187,17 +187,17 @@ TEST(MasterPtrTest, Invariants) {
};
auto ptr = std::make_unique<BadDerived>();
folly::MasterPtr<Mastered> masterPtr(std::move(ptr));
folly::PrimaryPtr<Primed> primaryPtr(std::move(ptr));
auto ranCleanup = false;
masterPtr.lock()->addCleanup(folly::makeSemiFuture().deferValue(
primaryPtr.lock()->addCleanup(folly::makeSemiFuture().deferValue(
[&](folly::Unit) { ranCleanup = true; }));
EXPECT_FALSE(ranCleanup);
{
folly::ManualExecutor exec;
masterPtr.cleanup()
primaryPtr.cleanup()
.within(1s)
.via(folly::getKeepAliveToken(exec))
.getVia(&exec);
......@@ -208,23 +208,23 @@ TEST(MasterPtrTest, Invariants) {
{
folly::ManualExecutor exec;
EXPECT_EXIT(
masterPtr.cleanup().via(folly::getKeepAliveToken(exec)).getVia(&exec),
primaryPtr.cleanup().via(folly::getKeepAliveToken(exec)).getVia(&exec),
testing::KilledBySignal(SIGABRT),
".*already.*");
}
}
struct Derived : Mastered {};
struct Derived : Primed {};
TEST(MasterPtrTest, EnableMasterFromThis) {
TEST(PrimaryPtrTest, EnablePrimaryFromThis) {
auto ptr = std::make_unique<Derived>();
auto rawPtr = ptr.get();
auto masterPtr = folly::MasterPtr<Mastered>{std::move(ptr)};
auto masterPtrRef = masterPtr.ref();
auto primaryPtr = folly::PrimaryPtr<Primed>{std::move(ptr)};
auto primaryPtrRef = primaryPtr.ref();
auto lockedPtr1 = masterPtr.lock();
auto lockedPtr2 = masterPtrRef.lock();
auto lockedPtr1 = primaryPtr.lock();
auto lockedPtr2 = primaryPtrRef.lock();
EXPECT_EQ(lockedPtr1.get(), rawPtr);
EXPECT_EQ(lockedPtr2.get(), rawPtr);
......@@ -237,11 +237,11 @@ TEST(MasterPtrTest, EnableMasterFromThis) {
auto cleanupFuture = std::async(std::launch::async, [&] {
folly::ManualExecutor exec;
masterPtr.cleanup()
primaryPtr.cleanup()
.within(1s)
.via(folly::getKeepAliveToken(exec))
.getVia(&exec);
EXPECT_TRUE(!masterPtr);
EXPECT_TRUE(!primaryPtr);
});
EXPECT_EQ(
......@@ -252,8 +252,8 @@ TEST(MasterPtrTest, EnableMasterFromThis) {
EXPECT_EQ(lockedPtr2.use_count(), 3);
EXPECT_EQ(lockedPtr3.use_count(), 3);
EXPECT_EQ(masterPtr.lock().get(), nullptr);
EXPECT_EQ(masterPtrRef.lock().get(), nullptr);
EXPECT_EQ(primaryPtr.lock().get(), nullptr);
EXPECT_EQ(primaryPtrRef.lock().get(), nullptr);
EXPECT_EQ(
cleanupFuture.wait_for(std::chrono::milliseconds{100}),
......@@ -267,5 +267,5 @@ TEST(MasterPtrTest, EnableMasterFromThis) {
cleanupFuture.wait_for(std::chrono::milliseconds{100}),
std::future_status::ready);
EXPECT_TRUE(!masterPtr);
EXPECT_TRUE(!primaryPtr);
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment