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