Commit 6e9d4d69 authored by Zhengxu Chen's avatar Zhengxu Chen Committed by Facebook GitHub Bot

Fix darwin and hphp build failures for PrimaryPtr.

Summary:
On darwin with Xcode, deleter for a shared_ptr is passed by copying the whole lambda, causing issues when building PrimaryPtr.

In this diff we try to work around this problem by putting the last promise value on the heap while sharing the control block with the shared_ptr exposed to user.

Reviewed By: yfeldblum

Differential Revision: D27354087

fbshipit-source-id: 9cb23912c9f1058505f3c20384eb998233eba2da
parent 056d288f
...@@ -203,10 +203,7 @@ class PrimaryPtr { ...@@ -203,10 +203,7 @@ class PrimaryPtr {
return std::move(this->unreferenced_); return std::move(this->unreferenced_);
}) })
// start cleanup tasks // start cleanup tasks
.deferValue([this](folly::Unit) { .deferValue([this](folly::Unit) { return getCleanup(innerPtr_.get()); })
auto cleanup = getCleanup(innerPtr_.get());
return std::move(cleanup);
})
.defer([this](folly::Try<folly::Unit> r) { .defer([this](folly::Try<folly::Unit> r) {
if (r.hasException()) { if (r.hasException()) {
LOG(FATAL) << "Cleanup actions must be noexcept."; LOG(FATAL) << "Cleanup actions must be noexcept.";
...@@ -235,10 +232,26 @@ class PrimaryPtr { ...@@ -235,10 +232,26 @@ class PrimaryPtr {
auto referencesContract = folly::makePromiseContract<folly::Unit>(); auto referencesContract = folly::makePromiseContract<folly::Unit>();
unreferenced_ = std::move(std::get<1>(referencesContract)); unreferenced_ = std::move(std::get<1>(referencesContract));
// The deleter object needs to be copyable in std::shared_ptr on some
// platform. To work around this limitation we can slightly tweak the
// semantics of deleter copy constructor and check we always use this
// object at most once.
class LastReference {
public:
LastReference(Promise<Unit>&& p) : p_(std::move(p)) {}
LastReference(LastReference&&) = default;
LastReference(LastReference& other) : LastReference(std::move(other)) {}
void operator()(T*) {
DCHECK(!p_.isFulfilled());
p_.setValue();
}
private:
Promise<Unit> p_;
};
auto innerPtrShared = std::shared_ptr<T>( auto innerPtrShared = std::shared_ptr<T>(
innerPtr_.get(), innerPtr_.get(),
[lastReference = std::move(std::get<0>(referencesContract))]( LastReference{std::move(std::get<0>(referencesContract))});
T*) mutable { lastReference.setValue(folly::Unit{}); });
outerPtrWeak_ = outerPtrShared_ = outerPtrWeak_ = outerPtrShared_ =
std::make_shared<std::shared_ptr<T>>(innerPtrShared); std::make_shared<std::shared_ptr<T>>(innerPtrShared);
......
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