qwaitcondition_win32.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: Nokia Corporation (qt-info@nokia.com)
5 **
6 ** This file is part of the QtCore module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** No Commercial Usage
10 ** This file contains pre-release code and may not be distributed.
11 ** You may use this file in accordance with the terms and conditions
12 ** contained in the either Technology Preview License Agreement or the
13 ** Beta Release License Agreement.
14 **
15 ** GNU Lesser General Public License Usage
16 ** Alternatively, this file may be used under the terms of the GNU Lesser
17 ** General Public License version 2.1 as published by the Free Software
18 ** Foundation and appearing in the file LICENSE.LGPL included in the
19 ** packaging of this file. Please review the following information to
20 ** ensure the GNU Lesser General Public License version 2.1 requirements
21 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22 **
23 ** In addition, as a special exception, Nokia gives you certain
24 ** additional rights. These rights are described in the Nokia Qt LGPL
25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26 ** package.
27 **
28 ** GNU General Public License Usage
29 ** Alternatively, this file may be used under the terms of the GNU
30 ** General Public License version 3.0 as published by the Free Software
31 ** Foundation and appearing in the file LICENSE.GPL included in the
32 ** packaging of this file. Please review the following information to
33 ** ensure the GNU General Public License version 3.0 requirements will be
34 ** met: http://www.gnu.org/copyleft/gpl.html.
35 **
36 ** If you are unsure which license is appropriate for your use, please
37 ** contact the sales department at http://www.qtsoftware.com/contact.
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include <windows.h>
43 #include "qwaitcondition.h"
44 #include "qmutex.h"
45 #include "qinternallist.h"
46 
47 //***********************************************************************
48 // QWaitConditionPrivate
49 // **********************************************************************
50 
52 {
53 public:
55  {
56  event = CreateEvent(NULL, TRUE, FALSE, NULL);
57  }
58  ~QWaitConditionEvent() { CloseHandle(event); }
59  int priority;
60  bool wokenUp;
61  HANDLE event;
62 };
63 
64 class EventQueue : public QInternalList<QWaitConditionEvent>
65 {
66  public:
67  EventQueue() { setAutoDelete(TRUE); }
69 };
70 
72 {
73 public:
77 
78  QWaitConditionEvent *pre();
79  void wait(QWaitConditionEvent *wce);
80  void post(QWaitConditionEvent *wce);
81 };
82 
84 {
85  mtx.lock();
86  QWaitConditionEvent *wce =
87  freeQueue.isEmpty() ? new QWaitConditionEvent : freeQueue.take(0);
88  wce->priority = GetThreadPriority(GetCurrentThread());
89  wce->wokenUp = FALSE;
90 
91  // insert 'wce' into the queue (sorted by priority)
92  uint index = 0;
93  for (; index < queue.count(); ++index)
94  {
95  QWaitConditionEvent *current = queue.at(index);
96  if (current->priority < wce->priority)
97  break;
98  }
99  queue.insert(index, wce);
100  mtx.unlock();
101 
102  return wce;
103 }
104 
106 {
107  WaitForSingleObject(wce->event, INFINITE);
108 }
109 
111 {
112  mtx.lock();
113 
114  // remove 'wce' from the queue
115  int idx = queue.find(wce);
116  ASSERT(idx!=-1);
117  queue.take(idx);
118  ResetEvent(wce->event);
119  freeQueue.append(wce);
120 
121  // wakeups delivered after the timeout should be forwarded to the next waiter
122  if (wce->wokenUp && !queue.isEmpty())
123  {
124  QWaitConditionEvent *other = queue.getFirst();
125  SetEvent(other->event);
126  other->wokenUp = TRUE;
127  }
128 
129  mtx.unlock();
130 }
131 
132 //***********************************************************************
133 // QWaitCondition implementation
134 //***********************************************************************
135 
137 {
138  d = new QWaitConditionPrivate;
139 }
140 
142 {
143  if (!d->queue.isEmpty())
144  {
145  qWarning("QWaitCondition: Destroyed while threads are still waiting");
146  }
147  delete d;
148 }
149 
151 {
152  if (!mutex) return;
153 
154  QWaitConditionEvent *wce = d->pre();
155  mutex->unlock();
156  d->wait(wce);
157  mutex->lock();
158  d->post(wce);
159 }
160 
162 {
163  // wake up the first waiting thread in the queue
164  QMutexLocker locker(&d->mtx);
165  for (uint i = 0; i < d->queue.count(); ++i)
166  {
167  QWaitConditionEvent *current = d->queue.at(i);
168  if (current->wokenUp) continue;
169  SetEvent(current->event);
170  current->wokenUp = TRUE;
171  break;
172  }
173 }
174 
176 {
177  // wake up the all threads in the queue
178  QMutexLocker locker(&d->mtx);
179  for (uint i = 0; i < d->queue.count(); ++i)
180  {
181  QWaitConditionEvent *current = d->queue.at(i);
182  SetEvent(current->event);
183  current->wokenUp = TRUE;
184  }
185 }
186 
void lock()
Definition: qmutex.cpp:58
Definition: qmutex.h:49
void wait(std::chrono::milliseconds dur)
void post(QWaitConditionEvent *wce)
const bool FALSE
Definition: qglobal.h:370
void qWarning(const char *msg,...)
Definition: qglobal.cpp:409
QWaitConditionEvent * pre()
static Entry * current
void unlock()
Definition: qmutex.cpp:85
void wait(QMutex *mutex)
unsigned uint
Definition: qglobal.h:351
const bool TRUE
Definition: qglobal.h:371
Event finding and building.
#define ASSERT(x)
Definition: qglobal.h:590