Skip to content

Commit 3a9912a

Browse files
committed
implement threading policy for supporting both single and multi threading
1 parent 26b13a3 commit 3a9912a

File tree

2 files changed

+51
-15
lines changed

2 files changed

+51
-15
lines changed

async-call-helper/async-call-helper.hpp

Lines changed: 50 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,24 @@
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+
1331
struct asyn_call_token
1432
{
1533
virtual ~asyn_call_token() = default;
@@ -26,18 +44,14 @@ struct asyn_call_token
2644
virtual 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
{
3350
public:
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;
3753
protected:
38-
async_call_helper()
39-
: IFaces()...
40-
{
54+
async_call_helper() {
4155
lifetime_ref = std::make_shared<auto_ref_holder>(parent());
4256
}
4357

@@ -46,7 +60,7 @@ class async_call_helper
4660
struct 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
}
6781
private:
6882
std::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
};
7185
return new special_token(weak_ref(), guard);
7286
}
@@ -87,7 +101,7 @@ class async_call_helper
87101
: public asyn_call_token
88102
{
89103
trampoline_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
}
117131
private:
118132
std::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;
120134
std::function<void(Args...)> callback;
121135
};
122136
std::function<void(Args...)> callback = cb;
@@ -137,7 +151,7 @@ class async_call_helper
137151
}
138152

139153
void set_deleted() noexcept {
140-
std::lock_guard<std::mutex> lock(guard);
154+
thread_support_traits<thread_support_t>::lock_guard_t lock(guard);
141155
lifetime_ref.reset();
142156
}
143157

@@ -160,7 +174,29 @@ class async_call_helper
160174
}
161175

162176
std::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+
};

async-call-helper/safe-service.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
#include "async-call-helper.hpp"
44

55
class safe_service
6-
: public async_call_helper<safe_service>
6+
: public async_call_helper<safe_service, multi_thread_usage>
77
{
88
public:
99
explicit safe_service(int in_param);

0 commit comments

Comments
 (0)