Skip to content

Commit 2335bea

Browse files
committed
run all ble operations which involve peripheral in its own thread
Signed-off-by: Andrey Parfenov <a1994ndrey@gmail.com>
1 parent 99fa8ba commit 2335bea

1 file changed

Lines changed: 208 additions & 24 deletions

File tree

src/board_controller/ble_lib_board.cpp

Lines changed: 208 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,166 @@
1+
#include <condition_variable>
2+
#include <deque>
3+
#include <functional>
4+
#include <future>
5+
#include <memory>
16
#include <string.h>
27
#include <string>
8+
#include <thread>
9+
#include <type_traits>
10+
#include <utility>
11+
12+
#ifdef _WIN32
13+
#include <objbase.h>
14+
#ifdef _MSC_VER
15+
#pragma comment(lib, "ole32.lib")
16+
#endif
17+
#endif
318

419
#include "ble_lib_board.h"
520

621
#include "bluetooth_types.h"
722
#include "get_dll_dir.h"
823

24+
namespace
25+
{
26+
#ifdef _WIN32
27+
class BLEThreadDispatcher
28+
{
29+
public:
30+
BLEThreadDispatcher ()
31+
: stop (false), started (false), worker (&BLEThreadDispatcher::worker_loop, this)
32+
{
33+
std::unique_lock<std::mutex> lock (mutex);
34+
cv.wait (lock, [this] { return started; });
35+
}
36+
37+
~BLEThreadDispatcher ()
38+
{
39+
{
40+
std::lock_guard<std::mutex> lock (mutex);
41+
stop = true;
42+
}
43+
cv.notify_one ();
44+
if (worker.joinable ())
45+
{
46+
worker.join ();
47+
}
48+
}
49+
50+
template <typename Func>
51+
typename std::enable_if<!std::is_void<typename std::result_of<Func ()>::type>::value,
52+
typename std::result_of<Func ()>::type>::type
53+
run (Func func)
54+
{
55+
typedef typename std::result_of<Func ()>::type result_type;
56+
if (is_worker_thread ())
57+
{
58+
return func ();
59+
}
60+
61+
std::shared_ptr<std::packaged_task<result_type ()>> task (
62+
new std::packaged_task<result_type ()> (std::move (func)));
63+
std::future<result_type> future = task->get_future ();
64+
{
65+
std::lock_guard<std::mutex> lock (mutex);
66+
queue.push_back ([task] () { (*task) (); });
67+
}
68+
cv.notify_one ();
69+
return future.get ();
70+
}
71+
72+
template <typename Func>
73+
typename std::enable_if<std::is_void<typename std::result_of<Func ()>::type>::value,
74+
void>::type
75+
run (Func func)
76+
{
77+
if (is_worker_thread ())
78+
{
79+
func ();
80+
return;
81+
}
82+
83+
std::shared_ptr<std::packaged_task<void ()>> task (
84+
new std::packaged_task<void ()> (std::move (func)));
85+
std::future<void> future = task->get_future ();
86+
{
87+
std::lock_guard<std::mutex> lock (mutex);
88+
queue.push_back ([task] () { (*task) (); });
89+
}
90+
cv.notify_one ();
91+
future.get ();
92+
}
93+
94+
private:
95+
void worker_loop ()
96+
{
97+
HRESULT coinit_result = CoInitializeEx (NULL, COINIT_MULTITHREADED);
98+
bool co_initialized = SUCCEEDED (coinit_result);
99+
100+
{
101+
std::lock_guard<std::mutex> lock (mutex);
102+
worker_id = std::this_thread::get_id ();
103+
started = true;
104+
}
105+
cv.notify_one ();
106+
107+
for (;;)
108+
{
109+
std::function<void ()> task;
110+
{
111+
std::unique_lock<std::mutex> lock (mutex);
112+
cv.wait (lock, [this] { return stop || !queue.empty (); });
113+
if (stop && queue.empty ())
114+
{
115+
break;
116+
}
117+
task = queue.front ();
118+
queue.pop_front ();
119+
}
120+
task ();
121+
}
122+
123+
if (co_initialized)
124+
{
125+
CoUninitialize ();
126+
}
127+
}
128+
129+
bool is_worker_thread ()
130+
{
131+
std::lock_guard<std::mutex> lock (mutex);
132+
return std::this_thread::get_id () == worker_id;
133+
}
134+
135+
std::mutex mutex;
136+
std::condition_variable cv;
137+
std::deque<std::function<void ()>> queue;
138+
bool stop;
139+
bool started;
140+
std::thread worker;
141+
std::thread::id worker_id;
142+
};
143+
144+
BLEThreadDispatcher &get_ble_thread_dispatcher ()
145+
{
146+
static BLEThreadDispatcher dispatcher;
147+
return dispatcher;
148+
}
149+
150+
template <typename Func>
151+
typename std::result_of<Func ()>::type run_on_simpleble_thread (Func func)
152+
{
153+
return get_ble_thread_dispatcher ().run (std::move (func));
154+
}
155+
#else
156+
template <typename Func>
157+
typename std::result_of<Func ()>::type run_on_simpleble_thread (Func func)
158+
{
159+
return func ();
160+
}
161+
#endif
162+
} // namespace
163+
9164
#ifndef STATIC_SIMPLEBLE
10165
DLLLoader *BLELibBoard::dll_loader = NULL;
11166
std::mutex BLELibBoard::mutex;
@@ -449,9 +604,10 @@ simpleble_err_t BLELibBoard::simpleble_peripheral_connect (simpleble_peripheral_
449604
return SIMPLEBLE_FAILURE;
450605
}
451606

452-
return func (handle);
607+
return run_on_simpleble_thread ([func, handle] () { return func (handle); });
453608
#else
454-
return ::simpleble_peripheral_connect (handle);
609+
return run_on_simpleble_thread (
610+
[handle] () { return ::simpleble_peripheral_connect (handle); });
455611
#endif
456612
}
457613

@@ -474,9 +630,10 @@ simpleble_err_t BLELibBoard::simpleble_peripheral_disconnect (simpleble_peripher
474630
return SIMPLEBLE_FAILURE;
475631
}
476632

477-
return func (handle);
633+
return run_on_simpleble_thread ([func, handle] () { return func (handle); });
478634
#else
479-
return ::simpleble_peripheral_disconnect (handle);
635+
return run_on_simpleble_thread (
636+
[handle] () { return ::simpleble_peripheral_disconnect (handle); });
480637
#endif
481638
}
482639

@@ -499,9 +656,10 @@ void BLELibBoard::simpleble_peripheral_release_handle (simpleble_peripheral_t ha
499656
return;
500657
}
501658

502-
func (handle);
659+
run_on_simpleble_thread ([func, handle] () { func (handle); });
503660
#else
504-
return ::simpleble_peripheral_release_handle (handle);
661+
return run_on_simpleble_thread (
662+
[handle] () { return ::simpleble_peripheral_release_handle (handle); });
505663
#endif
506664
}
507665

@@ -524,9 +682,10 @@ size_t BLELibBoard::simpleble_peripheral_services_count (simpleble_peripheral_t
524682
return 0;
525683
}
526684

527-
return func (handle);
685+
return run_on_simpleble_thread ([func, handle] () { return func (handle); });
528686
#else
529-
return ::simpleble_peripheral_services_count (handle);
687+
return run_on_simpleble_thread (
688+
[handle] () { return ::simpleble_peripheral_services_count (handle); });
530689
#endif
531690
}
532691

@@ -550,9 +709,11 @@ simpleble_err_t BLELibBoard::simpleble_peripheral_services_get (
550709
return SIMPLEBLE_FAILURE;
551710
}
552711

553-
return func (handle, index, services);
712+
return run_on_simpleble_thread (
713+
[func, handle, index, services] () { return func (handle, index, services); });
554714
#else
555-
return ::simpleble_peripheral_services_get (handle, index, services);
715+
return run_on_simpleble_thread ([handle, index, services] ()
716+
{ return ::simpleble_peripheral_services_get (handle, index, services); });
556717
#endif
557718
}
558719

@@ -578,10 +739,15 @@ simpleble_err_t BLELibBoard::simpleble_peripheral_write_request (simpleble_perip
578739
return SIMPLEBLE_FAILURE;
579740
}
580741

581-
return func (handle, service, characteristic, data, data_length);
742+
return run_on_simpleble_thread ([func, handle, service, characteristic, data, data_length] ()
743+
{ return func (handle, service, characteristic, data, data_length); });
582744
#else
583-
return ::simpleble_peripheral_write_request (
584-
handle, service, characteristic, data, data_length);
745+
return run_on_simpleble_thread (
746+
[handle, service, characteristic, data, data_length] ()
747+
{
748+
return ::simpleble_peripheral_write_request (
749+
handle, service, characteristic, data, data_length);
750+
});
585751
#endif
586752
}
587753

@@ -606,10 +772,15 @@ simpleble_err_t BLELibBoard::simpleble_peripheral_write_command (simpleble_perip
606772
return SIMPLEBLE_FAILURE;
607773
}
608774

609-
return func (handle, service, characteristic, data, data_length);
775+
return run_on_simpleble_thread ([func, handle, service, characteristic, data, data_length] ()
776+
{ return func (handle, service, characteristic, data, data_length); });
610777
#else
611-
return ::simpleble_peripheral_write_command (
612-
handle, service, characteristic, data, data_length);
778+
return run_on_simpleble_thread (
779+
[handle, service, characteristic, data, data_length] ()
780+
{
781+
return ::simpleble_peripheral_write_command (
782+
handle, service, characteristic, data, data_length);
783+
});
613784
#endif
614785
}
615786

@@ -640,9 +811,14 @@ simpleble_err_t BLELibBoard::simpleble_peripheral_notify (simpleble_peripheral_t
640811
return SIMPLEBLE_FAILURE;
641812
}
642813

643-
return func (handle, service, characteristic, callback, userdata);
814+
return run_on_simpleble_thread ([func, handle, service, characteristic, callback, userdata] ()
815+
{ return func (handle, service, characteristic, callback, userdata); });
644816
#else
645-
return ::simpleble_peripheral_notify (handle, service, characteristic, callback, userdata);
817+
return run_on_simpleble_thread (
818+
[handle, service, characteristic, callback, userdata] () {
819+
return ::simpleble_peripheral_notify (
820+
handle, service, characteristic, callback, userdata);
821+
});
646822
#endif
647823
}
648824

@@ -666,9 +842,11 @@ simpleble_err_t BLELibBoard::simpleble_peripheral_unsubscribe (
666842
return SIMPLEBLE_FAILURE;
667843
}
668844

669-
return func (handle, service, characteristic);
845+
return run_on_simpleble_thread ([func, handle, service, characteristic] ()
846+
{ return func (handle, service, characteristic); });
670847
#else
671-
return ::simpleble_peripheral_unsubscribe (handle, service, characteristic);
848+
return run_on_simpleble_thread ([handle, service, characteristic] ()
849+
{ return ::simpleble_peripheral_unsubscribe (handle, service, characteristic); });
672850
#endif
673851
}
674852

@@ -744,9 +922,13 @@ simpleble_err_t BLELibBoard::simpleble_peripheral_read (simpleble_peripheral_t h
744922
return SIMPLEBLE_FAILURE;
745923
}
746924

747-
return func (handle, service, characteristic, data, data_length);
925+
return run_on_simpleble_thread ([func, handle, service, characteristic, data, data_length] ()
926+
{ return func (handle, service, characteristic, data, data_length); });
748927
#else
749-
return ::simpleble_peripheral_read (handle, service, characteristic, data, data_length);
928+
return run_on_simpleble_thread (
929+
[handle, service, characteristic, data, data_length] () {
930+
return ::simpleble_peripheral_read (handle, service, characteristic, data, data_length);
931+
});
750932
#endif
751933
}
752934

@@ -770,8 +952,10 @@ simpleble_err_t BLELibBoard::simpleble_peripheral_is_connected (
770952
return SIMPLEBLE_FAILURE;
771953
}
772954

773-
return func (handle, connected);
955+
return run_on_simpleble_thread (
956+
[func, handle, connected] () { return func (handle, connected); });
774957
#else
775-
return ::simpleble_peripheral_is_connected (handle, connected);
958+
return run_on_simpleble_thread (
959+
[handle, connected] () { return ::simpleble_peripheral_is_connected (handle, connected); });
776960
#endif
777961
}

0 commit comments

Comments
 (0)