1010#include  < mutex> 
1111#include  < functional> 
1212
13+ //  async function callback support for single threaded environments.
14+ //  can be use only if async calls has sharing same thread with caller instance
15+ struct  single_thread_usage  {};
16+ 
17+ //  in case if async call executing from another thread,
18+ //  the destruction of caller and async callback function execution can run
19+ //  at the same time, this policy must be using for thread safety
20+ struct  multi_thread_usage  {};
21+ 
22+ //  trait struct for the usage of threading policy
23+ template  <typename  thread_support_t >
24+ struct  thread_support_traits  { 
25+ //  should have type definitions described below
26+ //  typedef mutex_type
27+ //  typedef lock_guard_t
28+ //  typedef unique_lock_t
29+ };
30+ 
1331struct  asyn_call_token 
1432{
1533virtual  ~asyn_call_token () = default ;
@@ -26,18 +44,14 @@ struct asyn_call_token
2644virtual  void * get_caller () = 0;
2745};
2846
29- template  <typename  Caller, typename  ...IFaces>
30- class  async_call_helper  
31- : public IFaces...
47+ template  <typename  Caller, typename  thread_support_t  = single_thread_usage>
48+ class  async_call_helper 
3249{
3350public: 
34- using  ThisType = async_call_helper<Caller, IFaces...>;
35- //  using IFaces::IFaces...;
51+ using  ThisType = async_call_helper<Caller, thread_support_t >;
3652~async_call_helper () = default ;
3753protected: 
38- async_call_helper () 
39- : IFaces()... 
40- {
54+ async_call_helper () {
4155lifetime_ref = std::make_shared<auto_ref_holder>(parent ());
4256}
4357
@@ -46,7 +60,7 @@ class async_call_helper
4660struct  special_token  final 
4761: public asyn_call_token
4862{
49- special_token (std::weak_ptr<auto_ref_holder> ref_, std::mutex & guard_) 
63+ special_token (std::weak_ptr<auto_ref_holder> ref_, thread_support_traits< thread_support_t >::mutex_type & guard_) 
5064: ref(ref_) 
5165, guard(guard_, std::defer_lock) {}
5266
@@ -66,7 +80,7 @@ class async_call_helper
6680}
6781private: 
6882std::weak_ptr<auto_ref_holder> ref;
69- std::unique_lock<std::mutex>  guard;
83+ typename  thread_support_traits< thread_support_t >:: unique_lock_t  guard;
7084};
7185return  new  special_token (weak_ref (), guard);
7286}
@@ -87,7 +101,7 @@ class async_call_helper
87101: public asyn_call_token
88102{
89103trampoline_t (std::weak_ptr<auto_ref_holder> ref_, 
90-  std::mutex & guard_,
104+  thread_support_traits< thread_support_t >::mutex_type & guard_,
91105 std::function<void (Args...)> callback_) 
92106: ref(ref_) 
93107, guard(guard_, std::defer_lock)
@@ -116,7 +130,7 @@ class async_call_helper
116130}
117131private: 
118132std::weak_ptr<auto_ref_holder> ref;
119- std::unique_lock<std::mutex>  guard;
133+ typename  thread_support_traits< thread_support_t >:: unique_lock_t  guard;
120134std::function<void (Args...)> callback;
121135};
122136std::function<void (Args...)> callback = cb;
@@ -137,7 +151,7 @@ class async_call_helper
137151}
138152
139153void  set_deleted () noexcept  {
140- std::lock_guard<std::mutex>  lock (guard);
154+ thread_support_traits< thread_support_t >:: lock_guard_t  lock (guard);
141155lifetime_ref.reset ();
142156}
143157
@@ -160,7 +174,29 @@ class async_call_helper
160174}
161175
162176std::shared_ptr<auto_ref_holder> lifetime_ref;
163- mutable  std::mutex  guard;
177+ mutable  typename  thread_support_traits< thread_support_t >::mutex_type  guard;
164178};
165179
180+ template  <>
181+ struct  thread_support_traits <single_thread_usage> {
182+ struct  dummy_mutex  {};
183+ using  mutex_type = dummy_mutex;
184+ struct  dummy_locker  {
185+ explicit  dummy_locker (mutex_type&) {}
186+ dummy_locker (mutex_type&, std::adopt_lock_t ) {}
187+ dummy_locker (mutex_type&, std::defer_lock_t ) {}
188+ dummy_locker (mutex_type&, std::try_to_lock_t ) {}
189+ explicit  operator  bool () const  noexcept  { return  false ; }
190+ void  lock () {}
191+ void  unlock () {}
192+ };
193+ using  lock_guard_t  = dummy_locker;
194+ using  unique_lock_t  = dummy_locker;
195+ };
166196
197+ template  <>
198+ struct  thread_support_traits <multi_thread_usage> {
199+ using  mutex_type = std::mutex;
200+ using  lock_guard_t  = std::lock_guard<mutex_type>;
201+ using  unique_lock_t  = std::unique_lock<mutex_type>;
202+ };
0 commit comments