soui 5.0.0.1
Soui5 Doc
 
Loading...
Searching...
No Matches
SNotifyCenter.cpp
1#include "souistd.h"
2#include <event/SNotifyCenter.h>
3#include <helper/SFunctor.hpp>
4#include <core/SNativeWnd.h>
5
6SNSBEGIN
7
8template <>
10
11//////////////////////////////////////////////////////////////////////////
12class SNotifyReceiver : public SNativeWnd {
13 public:
14 enum
15 {
16 UM_RUNONUISYNC = (WM_USER + 1000),
17 TIMERID_ASYNC = 100,
18 };
19
20 SNotifyReceiver(INotifyCallback *pCallback)
21 : m_pCallback(pCallback)
22 {
23 SASSERT(m_pCallback);
24 }
25
26 ~SNotifyReceiver()
27 {
28 }
29
30 LRESULT OnRunOnUISync(UINT uMsg, WPARAM wParam, LPARAM lParam);
31
32 void OnTimer(UINT_PTR uID);
33
34 BEGIN_MSG_MAP_EX(SNotifyReceiver)
35 MSG_WM_TIMER(OnTimer)
36 MESSAGE_HANDLER_EX(UM_RUNONUISYNC, OnRunOnUISync)
37 END_MSG_MAP()
38
39 protected:
40 INotifyCallback *m_pCallback;
41};
42
43LRESULT SNotifyReceiver::OnRunOnUISync(UINT uMsg, WPARAM wParam, LPARAM lParam)
44{
45 IRunnable *pRunnable = (IRunnable *)lParam;
46 pRunnable->run();
47 return 0;
48}
49
50void SNotifyReceiver::OnTimer(UINT_PTR uID)
51{
52 if (uID == TIMERID_ASYNC)
53 {
54 KillTimer(uID);
55 m_pCallback->OnFireEvts();
56 }
57}
58
59//////////////////////////////////////////////////////////////////////////
60SNotifyCenter::SNotifyCenter(int nInterval)
61 : m_pReceiver(NULL)
62 , m_bRunning(FALSE)
63 , m_nInterval(nInterval)
64{
65 m_dwMainTrdID = GetCurrentThreadId();
66 m_pReceiver = new SNotifyReceiver(this);
67 m_pReceiver->CreateNative(_T("NotifyReceiver"), WS_POPUP, 0, 0, 0, 0, 0, HWND_MESSAGE, 0, NULL);
68 SASSERT(m_pReceiver->IsWindow());
69}
70
71SNotifyCenter::~SNotifyCenter(void)
72{
73 m_pReceiver->DestroyWindow();
74 delete m_pReceiver;
75 m_pReceiver = NULL;
76
77 SPOSITION pos = m_ayncEvent.GetTailPosition();
78 while (pos)
79 {
80 IEvtArgs *e = m_ayncEvent.GetNext(pos);
81 e->Release();
82 }
83}
84
86{
87 SASSERT(m_dwMainTrdID == GetCurrentThreadId());
88 OnFireEvent(e);
89}
90
91//把事件抛到事件队列,不检查事件是否注册,执行事件时再检查。
93{
94 SAutoLock lock(m_cs);
95 e->AddRef();
96 if (!m_bRunning)
97 {
98 m_pReceiver->SetTimer(SNotifyReceiver::TIMERID_ASYNC, m_nInterval, NULL);
99 m_bRunning = TRUE;
100 }
101 m_ayncEvent.AddTail(e);
102}
103
105{
106 if (!GetEventObject(e->GetID()))
107 return; //确保事件是已经注册过的已经事件。
108
109 FireEvent(e);
110 if (!e->IsBubbleUp())
111 return;
112
113 SPOSITION pos = m_evtHandlerMap.GetTailPosition();
114 while (pos)
115 {
116 IEvtSlot *pSlot = m_evtHandlerMap.GetPrev(pos);
117 pSlot->Run(e);
118 if (!e->IsBubbleUp())
119 break;
120 }
121}
122
124{
125 SList<IEvtArgs *> evts;
126 SList<SAutoRefPtr<IRunnable>> cbs;
127 {
128 SAutoLock lock(m_cs);
129 evts = m_ayncEvent;
130 m_ayncEvent.RemoveAll();
131 cbs.Swap(m_asyncRunnable);
132 m_bRunning = FALSE;
133 }
134 {
135 SPOSITION pos = evts.GetHeadPosition();
136 while (pos)
137 {
138 IEvtArgs *e = evts.GetNext(pos);
139 OnFireEvent(e);
140 e->Release();
141 }
142 }
143 {
144 SPOSITION pos = cbs.GetHeadPosition();
145 while (pos)
146 {
147 SAutoRefPtr<IRunnable> runnable = cbs.GetNext(pos);
148 runnable->run();
149 }
150 }
151}
152
153BOOL SNotifyCenter::RegisterEventMap(const IEvtSlot *slot)
154{
155 for (SPOSITION pos = m_evtHandlerMap.GetHeadPosition(); pos;)
156 {
157 IEvtSlot *pSlot = m_evtHandlerMap.GetNext(pos);
158 if (pSlot->Equal(slot))
159 return FALSE;
160 }
161 m_evtHandlerMap.AddTail(slot->Clone());
162 return TRUE;
163}
164
165BOOL SNotifyCenter::UnregisterEventMap(const IEvtSlot *slot)
166{
167 for (SPOSITION pos = m_evtHandlerMap.GetHeadPosition(); pos;)
168 {
169 SPOSITION posPrev = pos;
170 IEvtSlot *pSlot = m_evtHandlerMap.GetNext(pos);
171 if (pSlot->Equal(slot))
172 {
173 m_evtHandlerMap.RemoveAt(posPrev);
174 pSlot->Release();
175 return TRUE;
176 }
177 }
178 return FALSE;
179}
180
181void SNotifyCenter::RunOnUI(IRunnable *pRunnable, BOOL bSync)
182{
183 if (bSync)
184 {
185 m_pReceiver->SendMessage(SNotifyReceiver::UM_RUNONUISYNC, 0, (LPARAM)pRunnable);
186 }
187 else
188 {
189 SAutoLock lock(m_cs);
190 if (!m_bRunning)
191 {
192 m_pReceiver->SetTimer(SNotifyReceiver::TIMERID_ASYNC, m_nInterval, NULL);
193 m_bRunning = TRUE;
194 }
195 m_asyncRunnable.AddTail(pRunnable);
196 }
197}
198
199void SNotifyCenter::RunOnUI2(THIS_ FunRunOnUI fun, WPARAM wp, LPARAM lp, BOOL bSync)
200{
201 IRunnable *pRunable = new StaticSFunctor2<FunRunOnUI, WPARAM, LPARAM>(fun, wp, lp);
202 RunOnUI(pRunable, bSync);
203 pRunable->Release();
204}
205
206#ifdef ENABLE_RUNONUI
207void SNotifyCenter::RunOnUISync(std::function<void(void)> fn)
208{
209 IRunnable *pRunable = new StdRunnable(fn);
210 RunOnUI(pRunable, TRUE);
211 pRunable->Release();
212}
213
214void SNotifyCenter::RunOnUIAsync(std::function<void(void)> fn)
215{
216 IRunnable *pRunable = new StdRunnable(fn);
217 RunOnUI(pRunable, FALSE);
218 pRunable->Release();
219}
220
221#endif
222
223SNSEND
Interface and Implementation for Native Window Handling.
Auto-lock class for managing critical sections.
Smart pointer class for managing COM-style reference-counted objects.
SEvent * GetEventObject(const DWORD dwEventID)
获取事件对象
void FireEvent(IEvtArgs *args)
触发事件
Class for managing native window operations.
Definition SNativeWnd.h:126
BOOL KillTimer(UINT_PTR nIDEvent) OVERRIDE
Kills a timer for the window.
通知中心类,管理事件的注册、注销和触发
void FireEventAsync(IEvtArgs *e) OVERRIDE
触发一个异步通知事件
void RunOnUI2(FunRunOnUI fun, WPARAM wp, LPARAM lp, BOOL bSync) OVERRIDE
在UI线程中运行一个函数
BOOL RegisterEventMap(const IEvtSlot *slot) OVERRIDE
注册一个处理通知的对象
void FireEventSync(IEvtArgs *e) OVERRIDE
触发一个同步通知事件
void RunOnUIAsync(std::function< void(void)> fn)
在UI线程中异步运行一个闭包
virtual void OnFireEvts()
触发多个事件
void RunOnUI(IRunnable *pRunnable, BOOL bSync) OVERRIDE
在UI线程中运行一个可运行对象
void RunOnUISync(std::function< void(void)> fn)
在UI线程中同步运行一个闭包
virtual void OnFireEvent(IEvtArgs *e)
触发事件
BOOL UnregisterEventMap(const IEvtSlot *slot) OVERRIDE
注销一个处理通知的对象
static T * ms_Singleton
Static pointer to the singleton instance.
Definition SSingleton.h:35