2 * Copyright (c) 1999-2002 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Portions Copyright (c) 1999-2002 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.1 (the "License"). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
14 * The Original Code and all software distributed under the License are
15 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
22 * @APPLE_LICENSE_HEADER_END@
24 * Modified: $Date: 2002/04/27 20:52:48 $
25 * Revision: $Id: LinkedList.h,v 1.3 2002/04/27 20:52:48 lane Exp $
36 #ifndef __LINKEDLIST__
37 #define __LINKEDLIST__
40 //we cant just use "macintosh_build" - the mac macho_build is designated as "posix_build" but may
41 //include open transport in some cases
42 #ifndef __OPENTRANSPORT__
43 //#if (!macintosh_build)
45 #include <stddef.h> //for OTGetLinkObject replacement
47 #include "OPUtils.h" //for true/false
51 // ECF 010928 win32 syncronization routines for safe critical sections. We can't simply use TryEnterCriticalSection()
52 // to return a true/false value because it's not available in win95 and 98
53 class OSCriticalSection
57 OSCriticalSection() {locked = false; InitializeCriticalSection(&theCriticalSection);}
58 ~OSCriticalSection() {DeleteCriticalSection(&theCriticalSection);}
59 NMBoolean acquire() { if (locked == true) return false; //dont have to wait in this case
60 EnterCriticalSection(&theCriticalSection);
61 if (locked) {LeaveCriticalSection(&theCriticalSection); return false;}
62 else {locked = true; LeaveCriticalSection(&theCriticalSection); return true;}}
63 void release() { EnterCriticalSection(&theCriticalSection);
64 locked = false; LeaveCriticalSection(&theCriticalSection);}
66 CRITICAL_SECTION theCriticalSection;
68 #endif //windows_build
72 class OSCriticalSection
75 OSCriticalSection() {pthread_mutex_init(&theMutex,NULL);}
76 ~OSCriticalSection() {pthread_mutex_destroy(&theMutex);}
77 NMBoolean acquire() { int error = pthread_mutex_trylock(&theMutex);
78 if (error) return false; else return true;}
79 void release() { pthread_mutex_unlock(&theMutex);}
81 pthread_mutex_t theMutex;
84 #endif //(posix_build)
86 /* -------------------------------------------------------------------------
89 ** These are functions to implement a LIFO list that is interrupt-safe.
90 ** The only function which is not is OTReverseList. Normally, you create
91 ** a LIFO list, populate it at interrupt time, and then use OTLIFOStealList
92 ** to atomically remove the list, and OTReverseList to flip the list so that
93 ** it is a FIFO list, which tends to be more useful.
94 ------------------------------------------------------------------------- */
110 OSCriticalSection theLock;
116 void Enqueue(OTLink* link)
118 while (true) {if (theLock.acquire()) break;}
127 while (true) {if (theLock.acquire()) break;}
128 OTLink *origHead = fHead;
129 fHead = fHead->fNext;
137 while (true) {if (theLock.acquire()) break;}
138 OTLink *origHead = fHead;
147 return fHead == NULL;
151 /* -------------------------------------------------------------------------
154 ** An OTList is a non-interrupt-safe list, but has more features than the
155 ** OTLIFO list. It is a standard singly-linked list.
156 ------------------------------------------------------------------------- */
158 typedef struct OTList OTList;
160 typedef NMBoolean (*OTListSearchProcPtr)(const void* ref, OTLink* linkToCheck);
162 // Remove the last link from the list
164 extern OTLink* OTRemoveLast(OTList* pList);
166 // Return the first link from the list
168 extern OTLink* OTGetFirst(OTList* pList);
170 // Return the last link from the list
172 extern OTLink* OTGetLast(OTList* pList);
174 // Return true if the link is present in the list
176 extern NMBoolean OTIsInList(OTList* pList, OTLink* link);
178 // Find a link in the list which matches the search criteria
179 // established by the search proc and the refPtr. This is done
180 // by calling the search proc, passing it the refPtr and each
181 // link in the list, until the search proc returns true.
182 // NULL is returned if the search proc never returned true.
184 extern OTLink* OTFindLink(OTList* pList, OTListSearchProcPtr proc, const void* refPtr);
186 // Remove the specified link from the list, returning true if it was found
188 extern NMBoolean OTRemoveLink(OTList*, OTLink*);
190 // Similar to OTFindLink, but it also removes it from the list.
192 extern OTLink* OTFindAndRemoveLink(OTList* pList, OTListSearchProcPtr proc, const void* refPtr);
194 // Return the "index"th link in the list
196 extern OTLink* OTGetIndexedLink(OTList* pList, size_t index);
206 { return fHead == NULL; }
208 void AddFirst(OTLink* link)
214 void AddLast(OTLink* link)
220 OTLink *current = fHead;
222 while (current->fNext != NULL)
223 current = current->fNext;
225 current->fNext = link;
235 { return OTGetFirst(this); }
238 { return OTGetLast(this); }
240 OTLink* RemoveFirst()
242 OTLink *origHead = fHead;
243 fHead = fHead->fNext;
248 { return OTRemoveLast(this); }
250 NMBoolean IsInList(OTLink* link)
251 { return OTIsInList(this, link); }
253 OTLink* FindLink(OTListSearchProcPtr proc, const void* ref)
254 { return OTFindLink(this, proc, ref); }
256 NMBoolean RemoveLink(OTLink* link)
257 { return OTRemoveLink(this, link); }
259 OTLink* RemoveLink(OTListSearchProcPtr proc, const void* ref)
260 { return OTFindAndRemoveLink(this, proc, ref); }
262 OTLink* GetIndexedLink(size_t index)
263 { return OTGetIndexedLink(this, index); }
267 //FIXME!! this is a recursive function and will crash and burn on large lists
268 static OTLink* OTReverseList(OTLink *headRef)
273 if (headRef == NULL) return NULL;
276 rest = (OTLink *) first->fNext;
278 if (rest == NULL) return headRef;
280 rest = OTReverseList(rest);
282 first->fNext->fNext = first;
289 #define OTGetLinkObject(link, struc, field) \
290 ((struc*)((char*)(link) - offsetof(struc, field)))
292 #endif //!macintosh_build
293 #endif /* __LINKEDLIST__ */