1 ///////////////////////////////////////////////////////////////////////////////
2 // $Source: x:/prj/tech/libsrc/cpptools/RCS/fixedstk.h $
4 // $Date: 1997/09/22 22:29:29 $
7 // Fixed size stacks of fixed size things...
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)
31 ///////////////////////////////////////////////////////////////////////////////
33 // TEMPLATE: cFixedStack
35 // A simple stack for things like device managers, network handling, etc.
38 template <class T
, unsigned kMaxElems
>
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) \
47 register unsigned temp = index; \
49 temp &= unsigned(kMaxElems - 1); \
53 #define cFixedStack_Retreat(index) \
55 register unsigned temp = index; \
57 temp &= unsigned(kMaxElems - 1); \
65 unsigned test
= ((kMaxElems
) & (kMaxElems
- 1));
66 AssertMsg(test
== 0, "Must be power of 2");
68 m_iNext
= m_iBottom
= 0;
72 // Queries for stack state
76 return (m_iNext
== m_iBottom
);
81 return (((m_iNext
+ 1) & unsigned(kMaxElems
- 1)) == m_iBottom
);
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...
108 cFixedStack_Advance(m_iBottom
);
111 m_Entries
[m_iNext
] = *pPush
;
113 cFixedStack_Advance(m_iNext
);
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();
128 cFixedStack_Advance(m_iBottom
);
131 *ppPushed
= &m_Entries
[m_iNext
];
132 m_Entries
[m_iNext
] = *pPush
;
134 cFixedStack_Advance(m_iNext
);
140 // Push to the stack, discarding if overflown. TRUE is no overflow
142 BOOL
PushUnlessFull(const T
* pPush
)
146 m_Entries
[m_iNext
] = *pPush
;
147 cFixedStack_Advance(m_iNext
);
154 // Push to the stack, getting pointer to added item.
155 // TRUE is no overflow
157 BOOL
PushUnlessFull(const T
* pPush
, const T
** ppPushed
)
161 *ppPushed
= &m_Entries
[m_iNext
];
162 m_Entries
[m_iNext
] = *pPush
;
163 cFixedStack_Advance(m_iNext
);
171 // Get the next available item from the stack. TRUE if
174 BOOL
Pop(T
* pReturn
)
178 cFixedStack_Retreat(m_iNext
);
179 *pReturn
= m_Entries
[m_iNext
];
186 // Check for the next available item from the stack. TRUE if
189 BOOL
Peek(T
* pReturn
)
193 *pReturn
= m_Entries
[((m_iNext
- 1) & unsigned(kMaxElems
- 1))];
200 // Check for the next available item from the stack.
201 // Results are undefined if stack is actually empty
205 return m_Entries
[((m_iNext
- 1) & unsigned(kMaxElems
- 1))];
211 BOOL
WaitForData(ulong msecTimeout
= 0)
215 HANDLE
GetAvailabilitySignalHandle() { return NULL
; }
224 T m_Entries
[kMaxElems
];
226 #undef cFixedStack_Advance
227 #undef cFixedStack_Retreat
230 ///////////////////////////////////////////////////////////////////////////////
232 // TEMPLATE: cFixedMTStack
234 // A thread-safe version of cFixedStack
239 template <class T
, unsigned kMaxElems
>
240 class cFixedMTStack
: private cFixedStack
<T
, kMaxElems
>
245 cAutoLock
lock(m_Lock
);
246 return cFixedStack
<T
, kMaxElems
>::IsEmpty();
251 cAutoLock
lock(m_Lock
);
252 return cFixedStack
<T
, kMaxElems
>::IsFull();
257 return cFixedStack
<T
, kMaxElems
>::GetSize();
262 cAutoLock
lock(m_Lock
);
263 cFixedStack
<T
, kMaxElems
>::Flush();
266 BOOL
Push(const T
* pPush
)
268 cAutoLock
lock(m_Lock
);
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
);
278 m_AvailabilitySignal
.Set();
279 return cFixedStack
<T
, kMaxElems
>::Push(pPush
, ppPushed
);
282 BOOL
PushUnlessFull(const T
* pPush
)
284 cAutoLock
lock(m_Lock
);
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
);
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
);
303 m_AvailabilitySignal
.Reset();
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
;
335 cThreadEvent m_AvailabilitySignal
;
340 ///////////////////////////////////////////////////////////////////////////////
342 #endif /* !__FIXEDSTK_H */