2 * Copyright (C) 2005-2011 Team XBMC
5 * This Program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
10 * This Program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with XBMC; see the file COPYING. If not, write to
17 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
18 * http://www.gnu.org/copyleft/gpl.html
26 #include "threads/Condition.h"
27 #include "threads/SingleLock.h"
29 // forward declare the CEventGroup
37 * This is an Event class built from a ConditionVariable. The Event adds the state
38 * that the condition is gating as well as the mutex/lock.
40 * This Event can be 'interruptible' (even though there is only a single place
41 * in the code that uses this behavior).
43 * This class manages 'spurious returns' from the condition variable.
45 class CEvent : public XbmcThreads::NonCopyable
48 volatile bool signaled;
49 unsigned int numWaits;
51 CCriticalSection groupListMutex; // lock for the groups list
52 std::vector<XbmcThreads::CEventGroup*> * groups;
55 * To satisfy the TightConditionVariable requirements and allow the
56 * predicate being monitored to include both the signaled and interrupted
59 XbmcThreads::ConditionVariable actualCv;
60 XbmcThreads::TightConditionVariable<volatile bool&> condVar;
61 CCriticalSection mutex;
63 friend class XbmcThreads::CEventGroup;
65 void addGroup(XbmcThreads::CEventGroup* group);
66 void removeGroup(XbmcThreads::CEventGroup* group);
68 // helper for the two wait methods
69 inline bool prepReturn() { bool ret = signaled; if (!manualReset && numWaits == 0) signaled = false; return ret; }
72 inline CEvent(bool manual = false, bool signaled_ = false) :
73 manualReset(manual), signaled(signaled_), numWaits(0), groups(NULL), condVar(actualCv,signaled) {}
75 inline void Reset() { CSingleLock lock(mutex); signaled = false; }
79 * This will wait up to 'milliSeconds' milliseconds for the Event
80 * to be triggered. The method will return 'true' if the Event
81 * was triggered. Otherwise it will return false.
83 inline bool WaitMSec(unsigned int milliSeconds)
84 { CSingleLock lock(mutex); numWaits++; condVar.wait(mutex,milliSeconds); numWaits--; return prepReturn(); }
87 * This will wait for the Event to be triggered. The method will return
88 * 'true' if the Event was triggered. If it was either interrupted
89 * it will return false. Otherwise it will return false.
92 { CSingleLock lock(mutex); numWaits++; condVar.wait(mutex); numWaits--; return prepReturn(); }
95 * This is mostly for testing. It allows a thread to make sure there are
96 * the right amount of other threads waiting.
98 inline int getNumWaits() { CSingleLock lock(mutex); return numWaits; }
102 namespace XbmcThreads
105 * CEventGroup is a means of grouping CEvents to wait on them together.
106 * It is equivalent to WaitOnMultipleObject that returns when "any" Event
107 * in the group signaled.
109 class CEventGroup : public NonCopyable
111 std::vector<CEvent*> events;
113 XbmcThreads::ConditionVariable actualCv;
114 XbmcThreads::TightConditionVariable<CEvent*&> condVar;
115 CCriticalSection mutex;
117 unsigned int numWaits;
119 // This is ONLY called from CEvent::Set.
120 inline void Set(CEvent* child) { CSingleLock l(mutex); signaled = child; condVar.notifyAll(); }
122 friend class ::CEvent;
127 * Create a CEventGroup from a number of CEvents. num is the number
128 * of Events that follow. E.g.:
130 * CEventGroup g(3, event1, event2, event3);
132 CEventGroup(int num, CEvent* v1, ...);
135 * Create a CEventGroup from a number of CEvents. The parameters
136 * should form a NULL terminated list of CEvent*'s
138 * CEventGroup g(event1, event2, event3, NULL);
140 CEventGroup(CEvent* v1, ...);
144 * This will block until any one of the CEvents in the group are
145 * signaled at which point a pointer to that CEvents will be
151 * This will block until any one of the CEvents in the group are
152 * signaled or the timeout is reachec. If an event is signaled then
153 * it will return a pointer to that CEvent, otherwise it will return
156 CEvent* wait(unsigned int milliseconds);
159 * This is mostly for testing. It allows a thread to make sure there are
160 * the right amount of other threads waiting.
162 inline int getNumWaits() { CSingleLock lock(mutex); return numWaits; }