convert line ends
[canaan.git] / prj / tech / libsrc / cpptools / fixedstk.h
blobc31faacf4f199e2a6592a01a17e77ad6e01b331e
1 ///////////////////////////////////////////////////////////////////////////////
2 // $Source: x:/prj/tech/libsrc/cpptools/RCS/fixedstk.h $
3 // $Author: TOML $
4 // $Date: 1997/09/22 22:29:29 $
5 // $Revision: 1.1 $
6 //
7 // Fixed size stacks of fixed size things...
8 //
9 // Very simple overflowing circular stack structures, with thread-safe and
10 // normal versions. Designed with systems-level stuff in mind -- Not meant for
11 // use with high copy overhead -- or any complex use really. Input devices,
12 // network protocols, multithreaded communication...
14 // Not a lot of error checking!
16 // Tries to remain consistent if in interrupt situation, but not verified! Make
17 // sure to declare instance volatile if using under interrupt
19 // Size MUST be a power of 2, because we implement the wrap-around logic
20 // (index = (index + 1) % kMaxElems) with only powers of 2 in mind
21 // (index = (index + 1) & (kMaxElems - 1)) for performance
23 // We use temporaries so that values are never totally invalid (i.e., we can never
24 // be interrrupted or preempted with either insert or remove index pointing
25 // off the end of the array)
28 #ifndef __FIXEDSTK_H
29 #define __FIXEDSTK_H
31 ///////////////////////////////////////////////////////////////////////////////
33 // TEMPLATE: cFixedStack
35 // A simple stack for things like device managers, network handling, etc.
38 template <class T, unsigned kMaxElems>
39 class cFixedStack
41 // A macro is used for index advancement to _ensure_ this
42 // is inlined -- Watcom sometimes decides not to inline
43 // this tiny code fragment!
45 #define cFixedStack_Advance(index) \
46 { \
47 register unsigned temp = index; \
48 temp++; \
49 temp &= unsigned(kMaxElems - 1); \
50 index = temp; \
53 #define cFixedStack_Retreat(index) \
54 { \
55 register unsigned temp = index; \
56 temp--; \
57 temp &= unsigned(kMaxElems - 1); \
58 index = temp; \
61 public:
62 cFixedStack()
64 #ifdef DEBUG
65 unsigned test = ((kMaxElems) & (kMaxElems - 1));
66 AssertMsg(test == 0, "Must be power of 2");
67 #endif
68 m_iNext = m_iBottom = 0;
72 // Queries for stack state
74 BOOL IsEmpty()
76 return (m_iNext == m_iBottom);
79 BOOL IsFull()
81 return (((m_iNext + 1) & unsigned(kMaxElems - 1)) == m_iBottom);
84 unsigned GetSize()
86 return kMaxElems;
90 // Empty the stack
92 void Flush()
94 m_iNext = 0;
95 m_iBottom = 0;
99 // Push to the stack, discarding oldest if overflown. TRUE is no overflow
101 BOOL Push(const T * pPush)
103 const BOOL fOverflow = IsFull();
105 // If overflowing, discard oldest stack item...
106 if (fOverflow)
108 cFixedStack_Advance(m_iBottom);
111 m_Entries[m_iNext] = *pPush;
113 cFixedStack_Advance(m_iNext);
115 return fOverflow;
119 // Push to the stack, getting pointer to added item.
120 // TRUE is no overflow
122 BOOL Push(const T * pPush, const T ** ppPushed)
124 const BOOL fOverflow = IsFull();
126 if (fOverflow)
128 cFixedStack_Advance(m_iBottom);
131 *ppPushed = &m_Entries[m_iNext];
132 m_Entries[m_iNext] = *pPush;
134 cFixedStack_Advance(m_iNext);
136 return fOverflow;
140 // Push to the stack, discarding if overflown. TRUE is no overflow
142 BOOL PushUnlessFull(const T * pPush)
144 if (!IsFull())
146 m_Entries[m_iNext] = *pPush;
147 cFixedStack_Advance(m_iNext);
148 return TRUE;
150 return FALSE;
154 // Push to the stack, getting pointer to added item.
155 // TRUE is no overflow
157 BOOL PushUnlessFull(const T * pPush, const T ** ppPushed)
159 if (!IsFull())
161 *ppPushed = &m_Entries[m_iNext];
162 m_Entries[m_iNext] = *pPush;
163 cFixedStack_Advance(m_iNext);
164 return TRUE;
166 *ppPushed = NULL;
167 return FALSE;
171 // Get the next available item from the stack. TRUE if
172 // there is any.
174 BOOL Pop(T * pReturn)
176 if (!IsEmpty())
178 cFixedStack_Retreat(m_iNext);
179 *pReturn = m_Entries[m_iNext];
180 return TRUE;
182 return FALSE;
186 // Check for the next available item from the stack. TRUE if
187 // there is any.
189 BOOL Peek(T * pReturn)
191 if (!IsEmpty())
193 *pReturn = m_Entries[((m_iNext - 1) & unsigned(kMaxElems - 1))];
194 return TRUE;
196 return FALSE;
200 // Check for the next available item from the stack.
201 // Results are undefined if stack is actually empty
203 const T & Peek()
205 return m_Entries[((m_iNext - 1) & unsigned(kMaxElems - 1))];
209 // Threading support
211 BOOL WaitForData(ulong msecTimeout = 0)
213 return !IsEmpty();
215 HANDLE GetAvailabilitySignalHandle() { return NULL; }
216 void Lock() {}
217 void Unlock() {}
220 private:
221 unsigned m_iNext;
222 unsigned m_iBottom;
224 T m_Entries[kMaxElems];
226 #undef cFixedStack_Advance
227 #undef cFixedStack_Retreat
230 ///////////////////////////////////////////////////////////////////////////////
232 // TEMPLATE: cFixedMTStack
234 // A thread-safe version of cFixedStack
237 #ifdef __THRDTOOL_H
239 template <class T, unsigned kMaxElems>
240 class cFixedMTStack : private cFixedStack<T, kMaxElems>
242 public:
243 BOOL IsEmpty()
245 cAutoLock lock(m_Lock);
246 return cFixedStack<T, kMaxElems>::IsEmpty();
249 BOOL IsFull()
251 cAutoLock lock(m_Lock);
252 return cFixedStack<T, kMaxElems>::IsFull();
255 unsigned GetSize()
257 return cFixedStack<T, kMaxElems>::GetSize();
260 void Flush()
262 cAutoLock lock(m_Lock);
263 cFixedStack<T, kMaxElems>::Flush();
266 BOOL Push(const T * pPush)
268 cAutoLock lock(m_Lock);
269 if (IsEmpty())
270 m_AvailabilitySignal.Set();
271 return cFixedStack<T, kMaxElems>::Push(pPush);
274 BOOL Push(const T * pPush, const T ** ppPushed)
276 cAutoLock lock(m_Lock);
277 if (IsEmpty())
278 m_AvailabilitySignal.Set();
279 return cFixedStack<T, kMaxElems>::Push(pPush, ppPushed);
282 BOOL PushUnlessFull(const T * pPush)
284 cAutoLock lock(m_Lock);
285 if (IsEmpty())
286 m_AvailabilitySignal.Set();
287 return cFixedStack<T, kMaxElems>::PushUnlessFull(pPush);
290 BOOL PushUnlessFull(const T * pPush, const T ** ppPushed)
292 cAutoLock lock(m_Lock);
293 if (IsEmpty())
294 m_AvailabilitySignal.Set();
295 return cFixedStack<T, kMaxElems>::PushUnlessFull(pPush, ppPushed);
298 BOOL Pop(T * pReturn)
300 cAutoLock lock(m_Lock);
301 BOOL result = cFixedStack<T, kMaxElems>::Pop(pReturn);
302 if (IsEmpty())
303 m_AvailabilitySignal.Reset();
304 return result;
307 BOOL Peek(T * pReturn)
309 cAutoLock lock(m_Lock);
310 return cFixedStack<T, kMaxElems>::Peek(pReturn);
313 BOOL WaitForData(ulong msecTimeout = INFINITE)
315 return m_AvailabilitySignal.Wait(msecTimeout);
318 HANDLE GetAvailabilitySignalHandle()
320 return m_AvailabilitySignal;
323 void Lock()
325 m_Lock.Lock();
328 void Unlock()
330 m_Lock.Unlock();
333 private:
334 cThreadLock m_Lock;
335 cThreadEvent m_AvailabilitySignal;
338 #endif
340 ///////////////////////////////////////////////////////////////////////////////
342 #endif /* !__FIXEDSTK_H */