1 #ifndef TGCALLS_THREAD_LOCAL_OBJECT_H 2 #define TGCALLS_THREAD_LOCAL_OBJECT_H 3 4 #include "rtc_base/thread.h" 5 #include "rtc_base/location.h" 6 7 #include <functional> 8 #include <memory> 9 10 namespace tgcalls { 11 12 template <typename T> 13 class ThreadLocalObject { 14 public: 15 template < 16 typename Generator, 17 typename = std::enable_if_t<std::is_same<T*, decltype(std::declval<Generator>()())>::value>> ThreadLocalObject(rtc::Thread * thread,Generator && generator)18 ThreadLocalObject(rtc::Thread *thread, Generator &&generator) : 19 _thread(thread), 20 _valueHolder(std::make_unique<ValueHolder>()) { 21 assert(_thread != nullptr); 22 _thread->PostTask(RTC_FROM_HERE, [valueHolder = _valueHolder.get(), generator = std::forward<Generator>(generator)]() mutable { 23 valueHolder->_value.reset(generator()); 24 }); 25 } 26 ~ThreadLocalObject()27 ~ThreadLocalObject() { 28 _thread->PostTask(RTC_FROM_HERE, [valueHolder = std::move(_valueHolder)](){ 29 valueHolder->_value.reset(); 30 }); 31 } 32 33 template <typename FunctorT> perform(const rtc::Location & posted_from,FunctorT && functor)34 void perform(const rtc::Location& posted_from, FunctorT &&functor) { 35 _thread->PostTask(posted_from, [valueHolder = _valueHolder.get(), f = std::forward<FunctorT>(functor)]() mutable { 36 assert(valueHolder->_value != nullptr); 37 f(valueHolder->_value.get()); 38 }); 39 } 40 getSyncAssumingSameThread()41 T *getSyncAssumingSameThread() { 42 assert(_thread->IsCurrent()); 43 assert(_valueHolder->_value != nullptr); 44 return _valueHolder->_value.get(); 45 } 46 47 private: 48 struct ValueHolder { 49 std::shared_ptr<T> _value; 50 }; 51 52 rtc::Thread *_thread = nullptr; 53 std::unique_ptr<ValueHolder> _valueHolder; 54 55 }; 56 57 } // namespace tgcalls 58 59 #endif 60