OpenClonk
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros
StdSchedulerWin32.cpp
Go to the documentation of this file.
1 /*
2  * OpenClonk, http://www.openclonk.org
3  *
4  * Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de/
5  * Copyright (c) 2009-2016, The OpenClonk Team and contributors
6  *
7  * Distributed under the terms of the ISC license; see accompanying file
8  * "COPYING" for details.
9  *
10  * "Clonk" is a registered trademark of Matthes Bender, used with permission.
11  * See accompanying file "TRADEMARK" for details.
12  *
13  * To redistribute this file separately, substitute the full license texts
14  * for the above references.
15  */
16 
17 // Events are Windows-specific
18 #include "C4Include.h"
19 #include "platform/StdScheduler.h"
20 #ifdef STDSCHEDULER_USE_EVENTS
21 
22 #include <mmsystem.h>
23 #include <process.h>
24 
26 {
27  return GetEvent() && WaitForSingleObject(GetEvent(), 0) == WAIT_OBJECT_0;
28 }
29 
30 CStdNotifyProc::CStdNotifyProc() : Event(true) {}
31 void CStdNotifyProc::Notify() { Event.Set(); }
33 {
34  if (!Event.WaitFor(0)) return false;
35  Event.Reset();
36  return true;
37 }
38 
39 bool StdScheduler::DoScheduleProcs(int iTimeout)
40 {
41  size_t i;
42  // Collect event handles
43  int iEventCnt = 0; HANDLE hEvent;
44  StdSchedulerProc *pMessageProc = nullptr;
45  for (i = 0u; i < procs.size(); i++)
46  {
47  auto proc = procs[i];
48  if ( (hEvent = proc->GetEvent()) )
49  {
50  if (hEvent == STDSCHEDULER_EVENT_MESSAGE)
51  pMessageProc = proc;
52  else
53  {
54  eventHandles[iEventCnt] = hEvent;
55  eventProcs[iEventCnt] = proc;
56  iEventCnt++;
57  }
58  }
59  }
60 
61  // Wait for something to happen
62  DWORD ret; DWORD dwMsec = iTimeout < 0 ? INFINITE : iTimeout;
63  if (pMessageProc)
64  ret = MsgWaitForMultipleObjects(iEventCnt, eventHandles.data(), false, dwMsec, QS_ALLINPUT);
65  else
66  ret = WaitForMultipleObjects(iEventCnt, eventHandles.data(), false, dwMsec);
67 
68  bool fSuccess = true;
69 
70  // Event?
71  if (ret != WAIT_TIMEOUT)
72  {
73  // Which event?
74  int iEventNr = ret - WAIT_OBJECT_0;
75 
76  // Execute the signaled process
77  StdSchedulerProc *pProc = iEventNr < iEventCnt ? eventProcs[iEventNr] : pMessageProc;
78  if (!pProc->Execute(0))
79  {
80  OnError(pProc);
81  fSuccess = false;
82  }
83 
84  }
85 
86  // Execute all processes with timeout
87  auto tNow = C4TimeMilliseconds::Now();
88  for (auto proc = procs.begin(); proc != procs.end(); ++proc)
89  {
90  auto tProcTick = (*proc)->GetNextTick(tNow);
91  if (tProcTick <= tNow)
92  if (!(*proc)->Execute(0))
93  {
94  OnError(*proc);
95  fSuccess = false;
96  }
97  }
98  return fSuccess;
99 }
100 
101 /* CStdMultimediaTimerProc */
102 
103 int CStdMultimediaTimerProc::iTimePeriod = 0;
104 
106  uCriticalTimerDelay(28),
107  idCriticalTimer(0),
108  uCriticalTimerResolution(5),
109  Event(true)
110 {
111 
112  if (!iTimePeriod)
113  {
114  // Get resolution caps
115  TIMECAPS tc;
116  timeGetDevCaps(&tc, sizeof(tc));
117  // Establish minimum resolution
118  uCriticalTimerResolution = Clamp(uCriticalTimerResolution, tc.wPeriodMin, tc.wPeriodMax);
119  timeBeginPeriod(uCriticalTimerResolution);
120  }
121  iTimePeriod++;
122 
123  SetDelay(iDelay);
124 
125 }
126 
127 CStdMultimediaTimerProc::~CStdMultimediaTimerProc()
128 {
129  if (idCriticalTimer)
130  {
131  timeKillEvent(idCriticalTimer);
132  idCriticalTimer = 0;
133 
134  iTimePeriod--;
135  if (!iTimePeriod)
136  timeEndPeriod(uCriticalTimerResolution);
137  }
138 }
139 
140 void CStdMultimediaTimerProc::SetDelay(uint32_t iDelay)
141 {
142 
143  // Kill old timer (of any)
144  if (idCriticalTimer)
145  timeKillEvent(idCriticalTimer);
146 
147  // Set new delay
148  uCriticalTimerDelay = iDelay;
149 
150  // Set critical timer
151  idCriticalTimer=timeSetEvent(
152  uCriticalTimerDelay,uCriticalTimerResolution,
153  (LPTIMECALLBACK) Event.GetEvent(),0,TIME_PERIODIC | TIME_CALLBACK_EVENT_SET);
154 
155  if(idCriticalTimer == 0)
156  DebugLogF("Creating Critical Timer failed: %d", GetLastError());
157 }
158 
160 {
161  if (procs.size() > eventProcs.size())
162  {
163  eventProcs.resize(procs.size());
164  eventHandles.resize(procs.size()+1);
165  }
166 }
167 
169 {
170 }
171 
173 {
174 }
175 
177 {
178 }
179 
180 bool CStdMultimediaTimerProc::CheckAndReset()
181 {
182  if (!Check()) return false;
183  Event.Reset();
184  return true;
185 }
186 #endif
void Removing(StdSchedulerProc *pProc)
virtual void OnError(StdSchedulerProc *)
Definition: StdScheduler.h:272
T Clamp(T bval, T lbound, T rbound)
Definition: Standard.h:46
bool DebugLogF(const char *strMessage...)
Definition: C4Log.cpp:281
#define CStdMultimediaTimerProc
Definition: StdScheduler.h:220
virtual bool Execute(int iTimeout=-1, pollfd *readyfds=0)=0
bool CheckAndReset()
void StartOnCurrentThread()
void Changed(StdSchedulerProc *pProc)
#define INFINITE
Definition: StdSync.h:58
virtual bool DoScheduleProcs(int iTimeout)
void Added(StdSchedulerProc *pProc)
uint32_t DWORD
static C4TimeMilliseconds Now()