|
1
|
1 #pragma once
|
|
|
2
|
|
|
3 #include "ThreadUtils.h"
|
|
|
4 #include "rethrow.h"
|
|
|
5
|
|
|
6 namespace ThreadUtils {
|
|
|
7
|
|
|
8 // OLD single thread wrapper class used only by old WMA input
|
|
|
9 // Modern code should use cmdThread which is all kinds of prettier
|
|
|
10 template<typename TBase, bool processMsgs = false>
|
|
|
11 class CSingleThreadWrapper : protected CVerySimpleThread {
|
|
|
12 private:
|
|
|
13 protected:
|
|
|
14 class command {
|
|
|
15 protected:
|
|
|
16 command() : m_abort(), m_completionEvent() {}
|
|
|
17 virtual void executeImpl(TBase &) {}
|
|
|
18 virtual ~command() {}
|
|
|
19 public:
|
|
|
20 void execute(TBase & obj) {
|
|
|
21 m_rethrow.exec( [this, &obj] {executeImpl(obj); } );
|
|
|
22 SetEvent(m_completionEvent);
|
|
|
23 }
|
|
|
24 void rethrow() const {
|
|
|
25 m_rethrow.rethrow();
|
|
|
26 }
|
|
|
27 CRethrow m_rethrow;
|
|
|
28 HANDLE m_completionEvent;
|
|
|
29 abort_callback * m_abort;
|
|
|
30 };
|
|
|
31
|
|
|
32 typedef std::function<void (TBase&) > func_t;
|
|
|
33
|
|
|
34 class command2 : public command {
|
|
|
35 public:
|
|
|
36 command2( func_t f ) : m_func(f) {}
|
|
|
37 void executeImpl(TBase & obj) {
|
|
|
38 m_func(obj);
|
|
|
39 }
|
|
|
40 private:
|
|
|
41
|
|
|
42 func_t m_func;
|
|
|
43 };
|
|
|
44
|
|
|
45 typedef pfc::rcptr_t<command> command_ptr;
|
|
|
46
|
|
|
47 CSingleThreadWrapper() {
|
|
|
48 m_completionEvent.create(true,false);
|
|
|
49 this->StartThread();
|
|
|
50 //start();
|
|
|
51 }
|
|
|
52
|
|
|
53 ~CSingleThreadWrapper() {
|
|
|
54 m_threadAbort.abort();
|
|
|
55 this->WaitTillThreadDone();
|
|
|
56 }
|
|
|
57
|
|
|
58 void invokeCommand2( func_t f, abort_callback & abort) {
|
|
|
59 auto c = pfc::rcnew_t<command2>(f);
|
|
|
60 invokeCommand( c, abort );
|
|
|
61 }
|
|
|
62 void invokeCommand(command_ptr cmd, abort_callback & abort) {
|
|
|
63 abort.check();
|
|
|
64 m_completionEvent.set_state(false);
|
|
|
65 pfc::vartoggle_t<abort_callback*> abortToggle(cmd->m_abort, &abort);
|
|
|
66 pfc::vartoggle_t<HANDLE> eventToggle(cmd->m_completionEvent, m_completionEvent.get() );
|
|
|
67 m_commands.Add(cmd);
|
|
|
68 m_completionEvent.wait_for(-1);
|
|
|
69 //WaitAbortable(m_completionEvent.get(), abort);
|
|
|
70 cmd->rethrow();
|
|
|
71 }
|
|
|
72
|
|
|
73 private:
|
|
|
74 void ThreadProc() {
|
|
|
75 TRACK_CALL_TEXT("CSingleThreadWrapper entry");
|
|
|
76 try {
|
|
|
77 TBase instance;
|
|
|
78 for(;;) {
|
|
|
79 command_ptr cmd;
|
|
|
80 if (processMsgs) m_commands.Get_MsgLoop(cmd, m_threadAbort);
|
|
|
81 else m_commands.Get(cmd, m_threadAbort);
|
|
|
82 cmd->execute(instance);
|
|
|
83 }
|
|
|
84 } catch(...) {}
|
|
|
85 if (processMsgs) ProcessPendingMessages();
|
|
|
86 }
|
|
|
87 win32_event m_completionEvent;
|
|
|
88 CObjectQueue<command_ptr> m_commands;
|
|
|
89 abort_callback_impl m_threadAbort;
|
|
|
90 };
|
|
|
91 } |