2#include "core/SMsgLoop.h"
5#define WM_SYSTIMER 0x0118
11BOOL RemoveElementFromArray(SArray<T> &arr, T ele)
13 int idx = arr.Find(ele);
20class SMessageLoopPriv {
22 SMessageLoopPriv(IMessageLoop *pParentLoop = NULL)
23 : m_parentLoop(pParentLoop)
26 SArray<IMsgFilter *> m_aMsgFilter;
27 SArray<IIdleHandler *> m_aIdleHandler;
28 SList<IRunnable *> m_runnables;
29 SList<IRunnable *> m_runningQueue;
30 SAutoRefPtr<IMessageLoop> m_parentLoop;
40 m_priv =
new SMessageLoopPriv(pParentLoop);
52 ::TranslateMessage(pMsg);
53 ::DispatchMessage(pMsg);
61 PostThreadMessage(m_tid, WM_QUIT, (WPARAM)exitCode, 0);
69 m_tid = GetCurrentThreadId();
79 SSLOGD() <<
"WaitMsg returned FALSE (error)";
87 SPOSITION pos = m_priv->m_runnables.GetHeadPosition();
90 IRunnable *pRunnable = m_priv->m_runnables.GetNext(pos);
93 m_priv->m_runnables.RemoveAll();
101 BOOL bContinue = !m_priv->m_aIdleHandler.IsEmpty();
103 for (
size_t i = 0; i < m_priv->m_aIdleHandler.GetCount(); i++)
106 if (!pIdleHandler->
OnIdle())
109 if (m_priv->m_parentLoop)
111 if (!m_priv->m_parentLoop->OnIdle(nIdleCount))
120 for (
int i = (
int)m_priv->m_aMsgFilter.GetCount() - 1; i >= 0; i--)
122 IMsgFilter *pMessageFilter = m_priv->m_aMsgFilter[i];
126 if (m_priv->m_parentLoop)
128 m_priv->m_parentLoop->PreTranslateMessage(pMsg);
136 switch (pMsg->message)
152 return RemoveElementFromArray(m_priv->m_aIdleHandler, pIdleHandler);
159 m_priv->m_aIdleHandler.Add(pIdleHandler);
165 return RemoveElementFromArray(m_priv->m_aMsgFilter, pMessageFilter);
170 m_priv->m_aMsgFilter.Add(pMessageFilter);
179 SSLOGW() <<
"msg loop not running now! pending task size:" << m_priv->m_runnables.GetCount();
181 m_priv->m_runnables.AddTail(runable->clone());
182 if (m_priv->m_runnables.GetCount() > 5)
184 PostThreadMessage(m_tid, WM_NULL, 0, 0);
193 SPOSITION pos = m_priv->m_runnables.GetHeadPosition();
196 SPOSITION pos2 = pos;
197 IRunnable *p = m_priv->m_runnables.GetNext(pos);
198 if (p->getObject() == pObj)
201 m_priv->m_runnables.RemoveAt(pos2);
206 pos = m_priv->m_runningQueue.GetHeadPosition();
209 SPOSITION pos2 = pos;
210 IRunnable *p = m_priv->m_runningQueue.GetNext(pos);
211 if (p->getObject() == pObj)
214 m_priv->m_runningQueue.RemoveAt(pos2);
229 m_priv->m_runningQueue.Swap(m_priv->m_runnables);
234 if (m_priv->m_runningQueue.IsEmpty())
236 IRunnable *pRunnable = m_priv->m_runningQueue.GetHead();
237 m_priv->m_runningQueue.RemoveHead();
239 pRunnable->Release();
241 if (m_priv->m_parentLoop)
243 m_priv->m_parentLoop->ExecutePendingTask();
249 return ::PeekMessage(pMsg, 0, wMsgFilterMin, wMsgFilterMax, bRemove ? PM_REMOVE : PM_NOREMOVE);
255 while (!m_bQuit && m_bDoIdle && !
PeekMsg(&msg, 0, 0, FALSE))
257 m_bDoIdle =
OnIdle(m_nIdleCount++);
266 return ::WaitMessage();
272 while (
PeekMsg(&msg, 0, 0, TRUE) && !m_bQuit)
274 if (msg.message == WM_QUIT)
287 return (
int)msg.wParam;
Auto-lock class for managing critical sections.
BOOL PostTask(IRunnable *runable) OVERRIDE
Posts a task to the message loop.
int HandleMsg() OVERRIDE
Handles a message from the message queue.
static BOOL IsIdleMessage(MSG *pMsg)
Checks if a message is an idle message.
BOOL PeekMsg(LPMSG pMsg, UINT wMsgFilterMin, UINT wMsgFilterMax, BOOL bRemove) OVERRIDE
Peeks at a message in the message queue without removing it.
void ExecutePendingTask() OVERRIDE
Executes all pending tasks.
void OnMsg(LPMSG pMsg) OVERRIDE
Processes a single message.
BOOL RemoveMessageFilter(IMsgFilter *pMessageFilter) OVERRIDE
Removes a message filter from the message loop.
virtual ~SMessageLoop()
Destructor for SMessageLoop.
BOOL PreTranslateMessage(MSG *pMsg) OVERRIDE
Pre-translates a message before it is dispatched.
BOOL RemoveIdleHandler(IIdleHandler *pIdleHandler) OVERRIDE
Removes an idle handler from the message loop.
BOOL OnIdle(int nIdleCount) OVERRIDE
Handles idle processing.
void RunIdle()
Runs idle processing.
int Run() OVERRIDE
Runs the message loop.
BOOL AddIdleHandler(IIdleHandler *pIdleHandler) OVERRIDE
Adds an idle handler to the message loop.
BOOL IsRunning() const OVERRIDE
Checks if the message loop is running.
BOOL AddMessageFilter(IMsgFilter *pMessageFilter) OVERRIDE
Adds a message filter to the message loop.
BOOL WaitMsg() OVERRIDE
Waits for a message in the message queue.
int RemoveTasksForObject(void *pObj) OVERRIDE
Removes all tasks associated with a specific object.
void Quit(int exitCode) OVERRIDE
Quits the message loop.
SMessageLoop(IMessageLoop *pParentLoop)
Constructor for SMessageLoop.
Interface for handling idle time.
BOOL OnIdle() PURE
Handles idle time.
Interface for message loops.
Interface for message filtering.
BOOL PreTranslateMessage(MSG *pMsg) PURE
Preprocesses a message.