TNB Library
TnbThreadDispatch.h
[詳解]
1#pragma once
13#include "TnbThread.h"
14
15
16
17//TNB Library
18namespace TNB
19{
20
21
22
47{
49public:
50
64 struct IListener
65 {
67 virtual ~IListener(void) {}
68
78 virtual bool OnThreadDispatchReceive(UINT nMsg, WPARAM wParam, LPARAM lParam) = 0;
79
85 virtual void OnThreadDispatchSetup(void) {}
86 };
87
88
89 //-------------------------
90
91
93 CThreadDispatch(void) : m_isDispatching(false)
94 {
95 m_lisDef.pDisp = this;
96 m_piListener = &m_lisDef;
97 m_thread.SetRunner(this);
98 }
99
101 virtual ~CThreadDispatch(void)
102 {
103 Stop();
104 }
105
112 void SetListener(IListener* piListener)
113 {
114 m_piListener = (piListener != NULL) ? piListener : &m_lisDef;
115 }
116
124 bool SetPriority(int priority)
125 {
126 return m_thread.SetPriority(priority);
127 }
128
133 DWORD GetThreadId(void) const
134 {
135 return m_thread.GetId();
136 }
137
144 bool Start(LPCTSTR lpszName = NULL)
145 {
146 m_isDispatching = false;
147 if ( m_thread.IsAlive() )
148 {
149 return false;
150 }
151 #ifdef _DEBUG
152 if ( lpszName == NULL) { lpszName = _T("ThreadDispatch:MessagePump"); }
153 #endif
154 if ( m_thread.Start(lpszName) )
155 {
156 DWORD dwTick = ::GetTickCount();
157 while ( (::GetTickCount() - dwTick) < 5000 )
158 {
159 if ( this->PostMessage(WM_NULL) )
160 {
161 return true;
162 }
163 ::Sleep(100);
164 }
165 m_thread.Stop();
166 }
167 return false;
168 }
169
175 bool Stop(void)
176 {
177 m_isDispatching = false;
178 if ( m_thread.IsAlive() )
179 {
180 m_thread.PostMessage(WM_QUIT);
181 return m_thread.Stop();
182 }
183 return true;
184 }
185
191 bool IsAlive(void) const
192 {
193 return m_thread.IsAlive();
194 }
195
204 bool PostMessage(UINT nMsg, WPARAM wParam = 0, LPARAM lParam = 0) const
205 {
206 if ( m_thread.IsAlive() )
207 {
208 return m_thread.PostMessage(nMsg, wParam, lParam);
209 }
210 return false;
211 }
212
218 bool IsDispatching(void) const
219 {
220 return m_isDispatching;
221 }
222
235 virtual bool OnThreadDispatchReceive(UINT nMsg, WPARAM wParam, LPARAM lParam)
236 {
237 ASSERT0(false, "CThreadDispatch", "継承もリスナ登録も行われずに使用されています。");
238 return false;
239 }
240
248 virtual void OnThreadDispatchSetup(void)
249 {
250 ASSERT0(false, "CThreadDispatch", "継承もリスナ登録も行われずに使用されています。");
251 }
252
258 {
259 return m_thread;
260 }
261
262private:
263 TNB::CThread m_thread;
264 IListener* m_piListener;
265 bool m_isDispatching;
266
271 virtual void OnSetupThread(void)
272 {
273 if ( m_piListener != NULL )
274 {
275 m_piListener->OnThreadDispatchSetup();
276 }
277 }
278
283 virtual DWORD Run(void)
284 {
285 MSG msg;
286 while ( ::GetMessage(&msg, NULL, 0, 0) > 0 )
287 {
288 if ( msg.message != WM_NULL && m_piListener != NULL )
289 {
290 m_isDispatching = true;
291 bool r = m_piListener->OnThreadDispatchReceive(msg.message, msg.wParam, msg.lParam);
292 m_isDispatching = false;
293 if ( ! r )
294 {
295 this->PostMessage(WM_QUIT);
296 }
297 else
298 {
299 ::TranslateMessage(&msg);
300 ::DispatchMessage(&msg);
301 }
302 }
303 }
304 ASSERTLIB(msg.message == WM_QUIT);
305 if ( m_piListener != NULL )
306 {
307 m_isDispatching = true;
308 m_piListener->OnThreadDispatchReceive(msg.message, msg.wParam, msg.lParam);
309 m_isDispatching = false;
310 }
311 return 0;
312 }
313
314 #ifndef _TnbDOXYGEN //Document作成用シンボル
315
317 struct TDefaultListener : IListener
318 {
319 CThreadDispatch* pDisp;
320 virtual bool OnThreadDispatchReceive(UINT nMsg, WPARAM wParam, LPARAM lParam)
321 {
322 return pDisp->OnThreadDispatchReceive(nMsg, wParam, lParam);
323 }
324 virtual void OnThreadDispatchSetup(void)
325 {
326 pDisp->OnThreadDispatchSetup();
327 }
328 } m_lisDef;
329
330 #endif //_TnbDOXYGEN
331};
332
333
334
349template<size_t COUNT>
351{
352public:
353
367 {
369 virtual ~IListener(void) {}
370
379 virtual bool OnMultiDispatchReceive(UINT nMsg, WPARAM wParam) = 0;
380 };
381
382
383 //-----
384
385
388 {
389 m_in.pListener = NULL;
390 loop ( i, COUNT )
391 {
392 m_in.tasks[i].SetListener(&m_in);
393 m_in.isTaskWorking[i] = false;
394 }
395 m_in.taskIndex = 0;
396 }
397
403 {
404 m_in.pListener = l;
405 }
406
414 void PostMessage(UINT msg, WPARAM wParam = 0)
415 {
416 INDEX tn = 0;
417 loop ( i, COUNT )
418 {
419 tn = (i + m_in.taskIndex) % COUNT;
420 if ( ! m_in.isTaskWorking[tn] )
421 {
422 break;
423 }
424 }
425 m_in.isTaskWorking[tn] = true;
426 m_in.tasks[tn].PostMessage(msg, wParam, tn);
427 }
428
437 void PostMessageToOne(INDEX index, UINT msg, WPARAM wParam = 0)
438 {
439 if ( index < COUNT )
440 {
441 m_in.isTaskWorking[index] = true;
442 m_in.tasks[index].PostMessage(msg, wParam, index);
443 }
444 }
445
451 bool Start(void)
452 {
453 bool r = true;
454 m_in.taskIndex = 0;
455 loop ( i, COUNT )
456 {
457 m_in.isTaskWorking[i] = false;
458 #ifdef _DEBUG
459 r &= m_in.tasks[i].Start(CStr::Fmt(_T("CMultiDispatch-%d"), i + 1));
460 #else
461 r &= m_in.tasks[i].Start();
462 #endif
463 }
464 if ( ! r )
465 {
466 Stop();
467 }
468 return r;
469 }
470
472 void Stop(void)
473 {
474 loop ( i, COUNT )
475 {
476 m_in.tasks[i].Stop();
477 m_in.isTaskWorking[i] = false;
478 }
479 }
480
481private:
483 struct TInner : CThreadDispatch::IListener
484 {
485 DEFPARENTLISTENER(typename CMultiThreadDispatchT<COUNT>, IParentListener);
486 IParentListener* pListener;
487 CThreadDispatch tasks[COUNT];
488 bool isTaskWorking[COUNT];
489 INDEX taskIndex;
492 virtual bool OnThreadDispatchReceive(UINT nMsg, WPARAM wParam, LPARAM lParam)
493 {
494 TRACE1("OnMultiDispatch-%d\n", lParam + 1);
495 if ( pListener != NULL )
496 {
497 pListener->OnMultiDispatchReceive(nMsg, wParam);
498 }
499 isTaskWorking[lParam] = false;
500 return true;
501 }
502 };
503 TInner m_in;
504};
505
506
507
508}; // TNB
509
#define loop(VAR, CNT)
loop構文.
Definition: TnbDef.h:343
スレッド管理関係のヘッダ
[ETC] コピー不可能スーパークラス.
Definition: TnbDef.h:599
マルチスレッド処理制御クラス
void Stop(void)
[設定] スレッド停止
bool Start(void)
[設定] スレッド開始
CMultiThreadDispatchT(void)
コンストラクタ
void PostMessage(UINT msg, WPARAM wParam=0)
[送信] メッセージ送信.
void SetListener(IListener *l)
[設定] リスナー登録.
void PostMessageToOne(INDEX index, UINT msg, WPARAM wParam=0)
[送信] メッセージ送信.
static CStrT Fmt(const TCHAR *lpszFormat,...)
[作成] 書式付き文字列作成
Definition: TnbStr.h:1206
スレッド処理制御クラス
CThreadStatus & ReferThreadStatus(void)
[参照] 処理スレッド状態参照.
bool PostMessage(UINT nMsg, WPARAM wParam=0, LPARAM lParam=0) const
[設定] スレッドへPostMessage
bool IsDispatching(void) const
[確認] 処理中?
bool SetPriority(int priority)
[設定] 優先度設定.
void SetListener(IListener *piListener)
[登録] リスナー登録
virtual void OnThreadDispatchSetup(void)
[通知] 開始通知.
virtual ~CThreadDispatch(void)
デストラクタ
bool IsAlive(void) const
[確認] スレッドが生きているか
bool Start(LPCTSTR lpszName=NULL)
[設定] スレッド開始
virtual bool OnThreadDispatchReceive(UINT nMsg, WPARAM wParam, LPARAM lParam)
[通知] メッセージ受信.
DWORD GetThreadId(void) const
[取得] スレッドのID取得
bool Stop(void)
[設定] スレッド停止
CThreadDispatch(void)
コンストラクタ
スレッド状態管理クラス
Definition: TnbThread.h:128
bool PostMessage(UINT message, WPARAM wParam=0, LPARAM lParam=0) const
[実行] PostThreadメッセージ
Definition: TnbThread.h:238
bool IsAlive(void) const
[確認] スレッドが生きているか
Definition: TnbThread.h:177
DWORD GetId(void) const
[取得] スレッドのID取得
Definition: TnbThread.h:163
bool SetPriority(int priority=THREAD_PRIORITY_NORMAL)
[設定] 優先度設定
Definition: TnbThread.h:217
スレッド管理クラス
Definition: TnbThread.h:316
bool SetRunner(IRunner *pRunner)
[設定] ランナー、設定
Definition: TnbThread.h:420
bool Stop(DWORD dwWait=15000)
[設定] スレッド停止 スレッドに対して停止要求します。
Definition: TnbThread.h:505
bool Start(LPCTSTR lpszName=NULL)
[設定] スレッド開始
Definition: TnbThread.h:618
TNB Library
Definition: TnbDoxyTitle.txt:2
マルチスレッド処理制御のリスナーインターフェース
virtual ~IListener(void)
デストラクタ
virtual bool OnMultiDispatchReceive(UINT nMsg, WPARAM wParam)=0
[通知] メッセージ受信.
スレッド処理制御のリスナーインターフェース
virtual ~IListener(void)
デストラクタ
virtual void OnThreadDispatchSetup(void)
[通知] 開始通知.
virtual bool OnThreadDispatchReceive(UINT nMsg, WPARAM wParam, LPARAM lParam)=0
[通知] メッセージ受信.
スレッド実行管理ランナーインターフェース
Definition: TnbThread.h:341