Mercurial > projects > hoofbaby
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 |