Summary:
ThreadLocalPtr manages the lifecycle of the object that is
stored with it. We have a use case where we sometimes want to transfer ownership
of the stored object to another thread by wrapping them with
unique_ptrs. Adding a release function, similar to to the
unique_ptr::release is the cleanest way for us to transfer ownership.
Test Plan:
I can do some on off testing using a command line tool, but I
was wondering about how to add some unit tests. Not sure when the folly
unit tests were.
Reviewed By: njormrod@fb.com
FB internal diff:
D1321588
return *get();
}
+ T* release() {
+ threadlocal_detail::ElementWrapper& w =
+ threadlocal_detail::StaticMeta<Tag>::get(id_);
+
+ return static_cast<T*>(w.release());
+ }
+
void reset(T* newPtr = nullptr) {
threadlocal_detail::ElementWrapper& w =
threadlocal_detail::StaticMeta<Tag>::get(id_);
if (ptr != nullptr) {
DCHECK(deleter != nullptr);
deleter->dispose(ptr, mode);
- if (ownsDeleter) {
- delete deleter;
- }
- ptr = nullptr;
- deleter = nullptr;
- ownsDeleter = false;
+
+ cleanup();
+ }
+ }
+
+ void* release() {
+ auto retPtr = ptr;
+
+ if (ptr != nullptr) {
+ cleanup();
}
+
+ return retPtr;
}
template <class Ptr>
}
}
+ void cleanup() {
+ if (ownsDeleter) {
+ delete deleter;
+ }
+ ptr = nullptr;
+ deleter = nullptr;
+ ownsDeleter = false;
+ }
+
void* ptr;
DeleterBase* deleter;
bool ownsDeleter;
EXPECT_FALSE(tl);
}
+TEST(ThreadLocalPtr, TestRelease) {
+ Widget::totalVal_ = 0;
+ ThreadLocalPtr<Widget> w;
+ std::unique_ptr<Widget> wPtr;
+ std::thread([&w, &wPtr]() {
+ w.reset(new Widget());
+ w.get()->val_ += 10;
+
+ wPtr.reset(w.release());
+ }).join();
+ EXPECT_EQ(0, Widget::totalVal_);
+ wPtr.reset();
+ EXPECT_EQ(10, Widget::totalVal_);
+}
+
// Test deleting the ThreadLocalPtr object
TEST(ThreadLocalPtr, CustomDeleter2) {
Widget::totalVal_ = 0;