comparison deps/Platinum/ThirdParty/Neptune/Source/System/Win32/NptWin32Queue.cpp @ 0:3425707ddbf6

Initial import (hopefully this mercurial stuff works...)
author fraserofthenight
date Mon, 06 Jul 2009 08:06:28 -0700
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:3425707ddbf6
1 /*****************************************************************
2 |
3 | Neptune - Queue :: Win32 Implementation
4 |
5 | (c) 2001-2002 Gilles Boccon-Gibod
6 | Author: Gilles Boccon-Gibod (bok@bok.net)
7 |
8 ****************************************************************/
9
10 /*----------------------------------------------------------------------
11 | includes
12 +---------------------------------------------------------------------*/
13 #if defined(_XBOX)
14 #include <xtl.h>
15 #else
16 #include <windows.h>
17 #endif
18
19 #include "NptConfig.h"
20 #include "NptTypes.h"
21 #include "NptQueue.h"
22 #include "NptThreads.h"
23 #include "NptList.h"
24 #include "NptDebug.h"
25 #include "NptWin32Threads.h"
26 #include "NptLogging.h"
27
28 /*----------------------------------------------------------------------
29 | logging
30 +---------------------------------------------------------------------*/
31 //NPT_SET_LOCAL_LOGGER("neptune.queue.win32")
32
33 /*----------------------------------------------------------------------
34 | NPT_Win32Queue
35 +---------------------------------------------------------------------*/
36 class NPT_Win32Queue : public NPT_GenericQueue
37 {
38 public:
39 // methods
40 NPT_Win32Queue(NPT_Cardinal max_items);
41 ~NPT_Win32Queue();
42 NPT_Result Push(NPT_QueueItem* item, NPT_Timeout timeout);
43 NPT_Result Pop(NPT_QueueItem*& item, NPT_Timeout timeout);
44 NPT_Result Peek(NPT_QueueItem*& item, NPT_Timeout timeout);
45
46
47 private:
48 // members
49 NPT_Cardinal m_MaxItems;
50 NPT_Win32CriticalSection m_Mutex;
51 NPT_Win32Event* m_CanPushCondition;
52 NPT_Win32Event* m_CanPopCondition;
53 NPT_List<NPT_QueueItem*> m_Items; // should be volatile ?
54 };
55
56 /*----------------------------------------------------------------------
57 | NPT_Win32Queue::NPT_Win32Queue
58 +---------------------------------------------------------------------*/
59 NPT_Win32Queue::NPT_Win32Queue(NPT_Cardinal max_items) :
60 m_MaxItems(max_items)
61 {
62 m_CanPushCondition = new NPT_Win32Event(true, true);
63 m_CanPopCondition = new NPT_Win32Event(true, false);
64 }
65
66 /*----------------------------------------------------------------------
67 | NPT_Win32Queue::~NPT_Win32Queue()
68 +---------------------------------------------------------------------*/
69 NPT_Win32Queue::~NPT_Win32Queue()
70 {
71 // destroy resources
72 delete m_CanPushCondition;
73 delete m_CanPopCondition;
74 }
75
76 /*----------------------------------------------------------------------
77 | NPT_Win32Queue::Push
78 +---------------------------------------------------------------------*/
79 NPT_Result
80 NPT_Win32Queue::Push(NPT_QueueItem* item, NPT_Timeout timeout)
81 {
82 // lock the mutex that protects the list
83 NPT_CHECK(m_Mutex.Lock());
84
85 // check that we have not exceeded the max
86 if (m_MaxItems) {
87 while (m_Items.GetItemCount() >= m_MaxItems) {
88 // we must wait until some items have been removed
89
90 // reset the condition to indicate that the queue is full
91 m_CanPushCondition->Reset();
92
93 // unlock the mutex so that another thread can pop
94 m_Mutex.Unlock();
95
96 // wait for the condition to signal that we can push
97 NPT_CHECK(m_CanPushCondition->Wait(timeout));
98
99 // relock the mutex so that we can check the list again
100 NPT_CHECK(m_Mutex.Lock());
101 }
102 }
103
104 // add the item to the list
105 m_Items.Add(item);
106
107 // wake up the threads waiting to pop
108 m_CanPopCondition->Signal();
109
110 // unlock the mutex
111 m_Mutex.Unlock();
112
113 return NPT_SUCCESS;
114 }
115
116 /*----------------------------------------------------------------------
117 | NPT_Win32Queue::Pop
118 +---------------------------------------------------------------------*/
119 NPT_Result
120 NPT_Win32Queue::Pop(NPT_QueueItem*& item, NPT_Timeout timeout)
121 {
122 // default value
123 item = NULL;
124
125 // lock the mutex that protects the list
126 NPT_CHECK(m_Mutex.Lock());
127
128 NPT_Result result;
129 if (timeout) {
130 while ((result = m_Items.PopHead(item)) == NPT_ERROR_LIST_EMPTY) {
131 // no item in the list, wait for one
132
133 // reset the condition to indicate that the queue is empty
134 m_CanPopCondition->Reset();
135
136 // unlock the mutex so that another thread can push
137 m_Mutex.Unlock();
138
139 // wait for the condition to signal that we can pop
140 NPT_CHECK(m_CanPopCondition->Wait(timeout));
141
142 // relock the mutex so that we can check the list again
143 NPT_CHECK(m_Mutex.Lock());
144 }
145 } else {
146 result = m_Items.PopHead(item);
147 }
148
149 if (m_MaxItems && (result == NPT_SUCCESS)) {
150 // wake up the threads waiting to push
151 m_CanPushCondition->Signal();
152 }
153
154 // unlock the mutex
155 m_Mutex.Unlock();
156
157 return result;
158 }
159
160 /*----------------------------------------------------------------------
161 | NPT_Win32Queue::Peek
162 +---------------------------------------------------------------------*/
163 NPT_Result
164 NPT_Win32Queue::Peek(NPT_QueueItem*& item, NPT_Timeout timeout)
165 {
166 // default value
167 item = NULL;
168
169 // lock the mutex that protects the list
170 NPT_CHECK(m_Mutex.Lock());
171
172 NPT_Result result = NPT_SUCCESS;
173 NPT_List<NPT_QueueItem*>::Iterator head = m_Items.GetFirstItem();
174 if (timeout) {
175 while (!head) {
176 // no item in the list, wait for one
177
178 // reset the condition to indicate that the queue is empty
179 m_CanPopCondition->Reset();
180
181 // unlock the mutex so that another thread can push
182 m_Mutex.Unlock();
183
184 // wait for the condition to signal that we can pop
185 NPT_CHECK(m_CanPopCondition->Wait(timeout));
186
187 // relock the mutex so that we can check the list again
188 NPT_CHECK(m_Mutex.Lock());
189
190 // try again
191 head = m_Items.GetFirstItem();
192 }
193 } else {
194 if (!head) result = NPT_ERROR_LIST_EMPTY;
195 }
196
197 if (head) item = *head;
198
199 // unlock the mutex
200 m_Mutex.Unlock();
201
202 return result;
203 }
204
205 /*----------------------------------------------------------------------
206 | NPT_GenericQueue::CreateInstance
207 +---------------------------------------------------------------------*/
208 NPT_GenericQueue*
209 NPT_GenericQueue::CreateInstance(NPT_Cardinal max_items)
210 {
211 return new NPT_Win32Queue(max_items);
212 }
213