X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=folly%2FThreadLocal.h;h=b47742072a65a9c837872edf602b8fe4989b9137;hb=61a96501d8da914c23c4d6d0b9ca49a18f58bea0;hp=30b8042bb337d29aebd111ea4945159b973d8e36;hpb=946d061defe9702e4e449bd6e828ed0a016b5364;p=folly.git diff --git a/folly/ThreadLocal.h b/folly/ThreadLocal.h index 30b8042b..b4774207 100644 --- a/folly/ThreadLocal.h +++ b/folly/ThreadLocal.h @@ -34,14 +34,14 @@ * @author Spencer Ahrens (sahrens) */ -#ifndef FOLLY_THREADLOCAL_H_ -#define FOLLY_THREADLOCAL_H_ +#pragma once +#include #include +#include #include -#include #include - +#include namespace folly { enum class TLPDestructionMode { @@ -181,32 +181,65 @@ class ThreadLocalPtr { } void reset(T* newPtr = nullptr) { + auto guard = makeGuard([&] { delete newPtr; }); threadlocal_detail::ElementWrapper& w = StaticMeta::instance().get(&id_); - if (w.ptr != newPtr) { - w.dispose(TLPDestructionMode::THIS_THREAD); - w.set(newPtr); - } + w.dispose(TLPDestructionMode::THIS_THREAD); + guard.dismiss(); + w.set(newPtr); } explicit operator bool() const { return get() != nullptr; } + /** + * reset() that transfers ownership from a smart pointer + */ + template < + typename SourceT, + typename Deleter, + typename = typename std::enable_if< + std::is_convertible::value>::type> + void reset(std::unique_ptr source) { + auto deleter = [delegate = source.get_deleter()]( + T * ptr, TLPDestructionMode) { + delegate(ptr); + }; + reset(source.release(), deleter); + } + + /** + * reset() that transfers ownership from a smart pointer with the default + * deleter + */ + template < + typename SourceT, + typename = typename std::enable_if< + std::is_convertible::value>::type> + void reset(std::unique_ptr source) { + reset(source.release()); + } + /** * reset() with a custom deleter: * deleter(T* ptr, TLPDestructionMode mode) * "mode" is ALL_THREADS if we're destructing this ThreadLocalPtr (and thus * deleting pointers for all threads), and THIS_THREAD if we're only deleting - * the member for one thread (because of thread exit or reset()) + * the member for one thread (because of thread exit or reset()). + * Invoking the deleter must not throw. */ template - void reset(T* newPtr, Deleter deleter) { + void reset(T* newPtr, const Deleter& deleter) { + auto guard = makeGuard([&] { + if (newPtr) { + deleter(newPtr, TLPDestructionMode::THIS_THREAD); + } + }); threadlocal_detail::ElementWrapper& w = StaticMeta::instance().get(&id_); - if (w.ptr != newPtr) { - w.dispose(TLPDestructionMode::THIS_THREAD); - w.set(newPtr, deleter); - } + w.dispose(TLPDestructionMode::THIS_THREAD); + guard.dismiss(); + w.set(newPtr, deleter); } // Holds a global lock for iteration through all thread local child objects. @@ -353,5 +386,3 @@ class ThreadLocalPtr { }; } // namespace folly - -#endif /* FOLLY_THREADLOCAL_H_ */