#ifndef TGCALLS_THREAD_LOCAL_OBJECT_H #define TGCALLS_THREAD_LOCAL_OBJECT_H #include "rtc_base/thread.h" #include "rtc_base/location.h" #include #include namespace tgcalls { template class ThreadLocalObject { public: template < typename Generator, typename = std::enable_if_t()())>::value>> ThreadLocalObject(rtc::Thread *thread, Generator &&generator) : _thread(thread), _valueHolder(std::make_unique()) { assert(_thread != nullptr); _thread->PostTask(RTC_FROM_HERE, [valueHolder = _valueHolder.get(), generator = std::forward(generator)]() mutable { valueHolder->_value.reset(generator()); }); } ~ThreadLocalObject() { _thread->PostTask(RTC_FROM_HERE, [valueHolder = std::move(_valueHolder)](){ valueHolder->_value.reset(); }); } template void perform(const rtc::Location& posted_from, FunctorT &&functor) { _thread->PostTask(posted_from, [valueHolder = _valueHolder.get(), f = std::forward(functor)]() mutable { assert(valueHolder->_value != nullptr); f(valueHolder->_value.get()); }); } T *getSyncAssumingSameThread() { assert(_thread->IsCurrent()); assert(_valueHolder->_value != nullptr); return _valueHolder->_value.get(); } private: struct ValueHolder { std::shared_ptr _value; }; rtc::Thread *_thread = nullptr; std::unique_ptr _valueHolder; }; } // namespace tgcalls #endif