uLib  User mode C/C++ extended API library for Win32 programmers.
ListClsEx.cpp
Go to the documentation of this file.
1 //==---------------------------------------------------------------------------
2 // DLinkListEx uses a Windows locking mechanism, so, unlike DLinkList,
3 // it can't be built on another platform (and hence may use the rest of uLib).
4 //==---------------------------------------------------------------------------
5 
6 // NOTA BENE: THIS IS AN EXPERIMENTAL MODULE AND MIGHT NOT WORK AS EXPECTED...
7 
8 #include <uLib/ListEx.h>
9 #include <uLib/Debug.h>
10 
11 //==---------------------------------------------------------------------------
12 // DLinkListEx - Mutually exclusive access
13 //==---------------------------------------------------------------------------
14 
15 
16 DLinkListEx::DLinkListEx( DWORD SpinCount )
17 : DLinkList()
18 {
19  SetLastError( 0 ); // Allow caller to examine success of c'tor, since...
20  InitializeCriticalSectionAndSpinCount( &_csect, SpinCount ); //... SetLastError
21 }
22 
23 DLinkListEx::DLinkListEx( PLIST_ENTRY ListHead, DWORD SpinCount ) // Pick up a plain DDK list.
24 : DLinkList()
25 {
26  SafeRemove = true;
27  SetLastError( 0 ); // Dito...
28  InitializeCriticalSectionAndSpinCount( &_csect, SpinCount ); //...
29  if (Lock( true ))
30  {
31  _grabList( ListHead );
32  Unlock();
33  }
34 }
35 
36 DLinkListEx::~DLinkListEx()
37 {
38  TRACE_IF( Count > 0, DP_WARNING, _F("Deleting non-empty list. Count=%lu\n"), Count );
39  DeleteCriticalSection( &_csect );
40 }
41 
42 bool DLinkListEx::Lock( bool Wait )
43 {
44  bool ok;
45  if (!Wait)
46  {
47  ok = bool_cast( TryEnterCriticalSection( &_csect ));
48  if (!ok) SetLastError( ERROR_LOCK_FAILED );
49  }
50  else
51  {
52  // MSDN: "EnterCriticalSection can raise EXCEPTION_POSSIBLE_DEADLOCK
53  // if a wait operation on the critical section times out. Do not handle
54  // a possible deadlock exception; instead, debug the application."
55 
56  EnterCriticalSection( &_csect ); // May except...
57  ok = true;
58  }
59  return ok;
60 }
61 
62 void DLinkListEx::Unlock()
63 {
64  LeaveCriticalSection( &_csect );
65 }
66 
67 DWORD DLinkListEx::SetLockSpinCount( DWORD SpinCount )
68 {
69  return SetCriticalSectionSpinCount( &_csect, SpinCount );
70 }
71 
72 //==---------------------------------------------------------------------------
73 // Content transfer: Wait for lock
74 //==---------------------------------------------------------------------------
75 
76 UINT DLinkListEx::ExportToListHead( PLIST_ENTRY ListHead )
77 {
78  UINT count = 0;
79  if (Lock( true ))
80  {
81  count = DLinkList::ExportToListHead( ListHead );
82  Unlock();
83  }
84  return count;
85 }
86 
87 UINT DLinkListEx::ImportFromListHead( PLIST_ENTRY ListHead, PLIST_ENTRY* ppFirst )
88 {
89  UINT count = 0;
90  if (Lock( true ))
91  {
92  count = DLinkList::ImportFromListHead( ListHead, ppFirst );
93  Unlock();
94  }
95  return count;
96 }
97 
98 UINT DLinkListEx::ExportToHeadlessList( PLIST_ENTRY* Target )
99 {
100  UINT count = 0;
101  if (Lock( true ))
102  {
103  count = DLinkList::ExportToHeadlessList( Target );
104  Unlock();
105  }
106  return count;
107 }
108 
109 UINT DLinkListEx::ImportHeadlessList( PLIST_ENTRY Circular, PLIST_ENTRY* ppFirst )
110 {
111  UINT count = 0;
112  if (Lock( true ))
113  {
114  count = DLinkList::ImportHeadlessList( Circular, ppFirst );
115  Unlock();
116  }
117  return count;
118 }
119 
120 //==---------------------------------------------------------------------------
121 // Content change: Wait for lock
122 //==---------------------------------------------------------------------------
123 
124 PLIST_ENTRY DLinkListEx::Append( PLIST_ENTRY Entry )
125 {
126  if (!Lock( true )) Entry = NULL;
127  else
128  {
129  Entry = DLinkList::Append( Entry );
130  Unlock();
131  }
132  return Entry;
133 }
134 
135 PLIST_ENTRY DLinkListEx::Prepend( PLIST_ENTRY Entry )
136 {
137  if (!Lock( true )) Entry = NULL;
138  else
139  {
140  Entry = DLinkList::Prepend( Entry );
141  Unlock();
142  }
143  return Entry;
144 }
145 
146 UINT DLinkListEx::AppendList( PLIST_ENTRY ListToAppend, PLIST_ENTRY* ppFirst )
147 {
148  // ListToAppend is the /head/ of the list to append.
149 
150  UINT nrAdded = 0;
151  if (Lock( true ))
152  {
153  nrAdded = DLinkList::AppendList( ListToAppend, ppFirst );
154  Unlock();
155  }
156  return nrAdded;
157 }
158 
159 UINT DLinkListEx::AppendList( PDLinkList ListToAppend, PLIST_ENTRY* ppFirst ) // preliminary
160 {
161  UINT nrAdded = DLinkListEx::AppendList( (PLIST_ENTRY)ListToAppend, ppFirst );
162  if (nrAdded) ListToAppend->Count = 0; // If success, ListToAppend is cleared.
163  return nrAdded;
164 }
165 
166 PLIST_ENTRY DLinkListEx::RemoveEntry( PLIST_ENTRY Entry ) // Return Entry if removed, else NULL
167 {
168  if (!Lock( true )) Entry = NULL;
169  else
170  {
171  Entry = DLinkList::RemoveEntry( Entry );
172  Unlock();
173  }
174  return Entry;
175 }
176 
177 void DLinkListEx::RemoveAll( PDListFunc ItemAction, void* UserData )
178 {
179  if (Lock( true ))
180  {
181  // Note: Because RemoveEntry is not virtual, the inherited RemoveAll will
182  // call it's own RemoveEntry, not our Ex version, so we don't have to be
183  // concerned about inefficient reaquiring of an already owned lock.
184 
185  DLinkList::RemoveAll( ItemAction, UserData );
186  Unlock();
187  }
188 }
189 
190 //==---------------------------------------------------------------------------
191 // Sort: Wait for lock
192 //==---------------------------------------------------------------------------
193 
194 void DLinkListEx::QuickSort( PDListComp Compare, void* Context )
195 {
196  if (Lock( true ))
197  {
198  DLinkList::QuickSort( Compare, Context );
199  Unlock();
200  }
201 }
202 
203 //==---------------------------------------------------------------------------
204 // Enumeration: Lock if able, else abort
205 //==---------------------------------------------------------------------------
206 
207 PLIST_ENTRY DLinkListEx::FirstThat( PDListFunc Match, void* UserData )
208 {
209  PLIST_ENTRY item = NULL;
210  bool locked = Lock();
211  TRACE( DP_VERBOSE, _F("Locked = %u\n"), locked );
212  if (locked)
213  {
214  item = DLinkList::FirstThat( Match, UserData );
215  Unlock();
216  }
217  return item;
218 }
219 
220 PLIST_ENTRY DLinkListEx::LastThat( PDListFunc Match, void* UserData )
221 {
222  PLIST_ENTRY item = NULL;
223  bool locked = Lock();
224  TRACE( DP_VERBOSE, _F("Locked = %u\n"), locked );
225  if (locked)
226  {
227  item = DLinkList::LastThat( Match, UserData );
228  Unlock();
229  }
230  return item;
231 }
232 
233 bool DLinkListEx::ForEach( PDListFunc Action, void* UserData )
234 {
235  bool complete = false;
236  bool locked = Lock();
237  TRACE( DP_VERBOSE, _F("Locked = %u\n"), locked );
238  if (locked)
239  {
240  complete = DLinkList::ForEach( Action, UserData );
241  Unlock();
242  }
243  return complete;
244 }
245 
246 // EOF
PLIST_ENTRY FirstThat(PDListFunc Match, void *UserData=NULL)
Definition: ListCls.cpp:287
unsigned long DWORD
Definition: Common.h:414
UINT ExportToListHead(PLIST_ENTRY ListHead)
Definition: ListCls.cpp:431
UINT ImportFromListHead(IN PLIST_ENTRY ListHead, OPTOUT PLIST_ENTRY *ppFirst)
Definition: ListCls.cpp:446
PLIST_ENTRY LastThat(PDListFunc Match, void *UserData=NULL)
Definition: ListCls.cpp:302
UINT ImportHeadlessList(IN PLIST_ENTRY Circular, OPTOUT PLIST_ENTRY *ppFirst)
Definition: ListCls.cpp:472
bool ForEach(PDListFunc Action, void *UserData=NULL)
Definition: ListCls.cpp:317
UINT AppendList(IN PLIST_ENTRY ListToAppend, OPTOUT PLIST_ENTRY *ppFirst)
Definition: ListCls.cpp:116
#define TRACE(_lvl,...)
Definition: Debug.h:216
struct _LIST_ENTRY * PLIST_ENTRY
bool(__stdcall * PDListFunc)(PLIST_ENTRY Entry, void *UserData)
Definition: ListFunc.h:152
PLIST_ENTRY Prepend(PLIST_ENTRY Entry)
Definition: ListCls.cpp:103
#define TRACE_IF(cond,...)
Definition: Debug.h:227
PLIST_ENTRY Append(PLIST_ENTRY Entry)
Definition: ListCls.cpp:90
int(__stdcall * PDListComp)(PLIST_ENTRY X, PLIST_ENTRY Y, void *UserData)
Definition: ListFunc.h:159
void QuickSort(PDListComp Compare, void *UserData=NULL)
Definition: ListCls.cpp:335
bool __forceinline bool_cast(BOOL B52)
Definition: Common.h:767
void RemoveAll(PDListFunc ItemAction, void *UserData=NULL)
Definition: ListCls.cpp:241
Debug and error handling support.
class DLinkList * PDLinkList
Definition: ListFunc.h:143
UINT ExportToHeadlessList(PLIST_ENTRY *Circular)
Definition: ListCls.cpp:462
#define _F(s)
Definition: Debug.h:49
#define DP_VERBOSE
Definition: Debug.h:86
PLIST_ENTRY RemoveEntry(PLIST_ENTRY Entry)
Definition: ListCls.cpp:213
#define DP_WARNING
Definition: Debug.h:83