Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1012 lines
20 KiB

  1. /****************************************************************************
  2. *
  3. *
  4. * INTEL Corporation Prorietary Information
  5. *
  6. * This listing is supplied under the terms of a license agreement
  7. * with INTEL Corporation and may not be copied nor disclosed except
  8. * in accordance with the terms of that agreement.
  9. *
  10. * Copyright (c) 1996 Intel Corporation.
  11. *
  12. *
  13. * Abstract:
  14. *
  15. * Notes:
  16. *
  17. ***************************************************************************/
  18. #ifndef __TSTABLE_H
  19. #define __TSTABLE_H
  20. #include <windows.h>
  21. typedef struct _LOCK_ENTRY
  22. {
  23. HANDLE hLock;
  24. int iLockCount;
  25. BOOL bCleanup,
  26. bDeleted;
  27. WORD wNextFree,
  28. wUniqueID;
  29. } LOCK_ENTRY, *PLOCK_ENTRY;
  30. // definition of an invalid ID
  31. #define TSTABLE_INVALID_ID (DWORD) 0xFFFFFFFF
  32. // return codes that the callback function used in conjunction with EnumerateEntries can return
  33. const DWORD CALLBACK_CONTINUE = 1;
  34. const DWORD CALLBACK_ABORT = 2;
  35. const DWORD CALLBACK_DELETE_ENTRY = 3;
  36. const DWORD CALLBACK_DELETE_ENTRY_AND_OBJECT = 4;
  37. // used in call to Lock
  38. #define TSTABLE_INVALID_UNIQUE_ID (WORD) 0xFFFF
  39. #define TSTABLE_INVALID_INDEX (WORD) 0xFFFF
  40. // This is a compare function that we aren't using right now. It
  41. // will be useful in the future if there is a reason to search
  42. // the table
  43. typedef INT (*ENTRY_COMPARE) (LPVOID ptr1, LPVOID ptr2);
  44. template <class EntryData> class TSTable
  45. {
  46. typedef DWORD (*TABLE_CALLBACK) (EntryData* ptr, LPVOID context);
  47. public:
  48. TSTable (WORD _size);
  49. ~TSTable ();
  50. BOOL Resize (WORD wNewSize);
  51. BOOL CreateAndLock (EntryData* pEntryData,
  52. LPDWORD lpdwID);
  53. BOOL Validate (DWORD dwID);
  54. EntryData *Lock (DWORD dwID,
  55. DWORD timeout = INFINITE);
  56. BOOL Unlock (DWORD dwID);
  57. BOOL Delete (DWORD dwID,
  58. BOOL bCleanup = FALSE);
  59. EntryData *EnumerateEntries(TABLE_CALLBACK callBackFunc,
  60. void* context,
  61. BOOL bUnlockTable = FALSE);
  62. BOOL IsInitialized () {return bInitialized;}
  63. WORD GetSize () {return wNumUsed;}
  64. private:
  65. // data
  66. EntryData** pDataTable;
  67. PLOCK_ENTRY pLockTable;
  68. CRITICAL_SECTION csTableLock;
  69. WORD wSize,
  70. wNumUsed,
  71. wFirstFree,
  72. wLastFree,
  73. wUniqueID;
  74. BOOL bInitialized;
  75. // private methods
  76. BOOL LockEntry (WORD wIndex,
  77. DWORD timeout = INFINITE);
  78. BOOL UnLockEntry(WORD wIndex);
  79. void LockTable () { EnterCriticalSection(&csTableLock); };
  80. void UnLockTable() { LeaveCriticalSection(&csTableLock); };
  81. WORD GenerateUniqueID();
  82. DWORD MakeID(WORD wIndex, WORD wUniqueID)
  83. {
  84. DWORD theID = wUniqueID;
  85. theID = (theID << 16) & 0xFFFF0000;
  86. theID |= wIndex;
  87. return(theID);
  88. };
  89. void BreakID(DWORD theID, WORD* pwIndex, WORD* pwUID)
  90. {
  91. *pwIndex = (WORD) (theID & 0x0000FFFF);
  92. *pwUID = (WORD) ((theID >> 16) & 0x0000FFFF);
  93. };
  94. };
  95. /*
  96. ** TSTable::TSTable
  97. *
  98. * FILENAME: c:\msdev\projects\firewalls\inc\tstable.h
  99. *
  100. * PARAMETERS:
  101. *
  102. * DESCRIPTION:
  103. *
  104. * RETURNS:
  105. *
  106. */
  107. template <class EntryData>
  108. TSTable<EntryData>::TSTable(WORD _size) :
  109. wSize(_size),
  110. wNumUsed((WORD) 0),
  111. wFirstFree((WORD) 0),
  112. wLastFree((WORD) (_size - 1)),
  113. wUniqueID((WORD) 0),
  114. bInitialized(TRUE),
  115. pDataTable(NULL),
  116. pLockTable(NULL)
  117. {
  118. WORD wIndex;
  119. // Create the table lock
  120. InitializeCriticalSection(&csTableLock);
  121. // Lock the table
  122. LockTable();
  123. // Create the data table
  124. pDataTable = new EntryData*[wSize];
  125. if(pDataTable == NULL)
  126. {
  127. bInitialized = FALSE;
  128. return;
  129. }
  130. // Init the pointers
  131. for (wIndex = 0; wIndex < wSize; wIndex++)
  132. {
  133. pDataTable[wIndex] = NULL;
  134. }
  135. // Create the lock table
  136. pLockTable = new LOCK_ENTRY[wSize];
  137. if (pLockTable == NULL)
  138. {
  139. bInitialized = FALSE;
  140. return;
  141. }
  142. // Initialize the lock table entries...each entry begins with
  143. // a NULL mutex handle, a zero lock count and it's next free is
  144. // the next successive entry.
  145. for (wIndex = 0; wIndex < wSize; wIndex++ )
  146. {
  147. pLockTable[wIndex].hLock = NULL;
  148. pLockTable[wIndex].iLockCount = 0;
  149. pLockTable[wIndex].wNextFree = (WORD) (wIndex + 1);
  150. }
  151. // note: the wNextFree in the last table entry points to an invalid index, however,
  152. // this is OK since if the table ever fills, it is automatically resized making what
  153. // was an invalid index, the index into the first entry of newly added part of the
  154. // enlargened table. Trust me...
  155. // Unlock the table
  156. UnLockTable();
  157. }
  158. /*
  159. ** TSTable::~TSTable
  160. *
  161. * FILENAME: c:\msdev\projects\firewalls\inc\table.h
  162. *
  163. * PARAMETERS:
  164. *
  165. * DESCRIPTION:
  166. *
  167. * RETURNS:
  168. *
  169. */
  170. template <class EntryData>
  171. TSTable<EntryData>::~TSTable()
  172. {
  173. DWORD wIndex;
  174. // Lock the table
  175. LockTable();
  176. // Delete the data table
  177. if (pDataTable != NULL)
  178. {
  179. delete pDataTable;
  180. }
  181. // Delete the lock table
  182. if (pLockTable != NULL)
  183. {
  184. // Destroy the mutexes
  185. for (wIndex = 0; wIndex < wSize; wIndex++)
  186. {
  187. if (pLockTable[wIndex].hLock != NULL)
  188. {
  189. CloseHandle(pLockTable[wIndex].hLock);
  190. }
  191. }
  192. delete pLockTable;
  193. }
  194. // Unlock the table
  195. UnLockTable();
  196. // Destroy the table lock
  197. DeleteCriticalSection(&csTableLock);
  198. bInitialized = FALSE;
  199. }
  200. /*
  201. ** TSTable::Resize
  202. *
  203. * FILENAME: c:\msdev\projects\firewalls\inc\table.h
  204. *
  205. * PARAMETERS:
  206. *
  207. * DESCRIPTION:
  208. *
  209. * RETURNS:
  210. *
  211. */
  212. template <class EntryData>
  213. BOOL TSTable<EntryData>::Resize(WORD wNewSize)
  214. {
  215. BOOL bRetCode = TRUE;
  216. EntryData** pNewDataTable;
  217. PLOCK_ENTRY pNewLockTable;
  218. WORD wIndex;
  219. // Lock the table
  220. LockTable();
  221. // If the table is shrinking, pretend we did it
  222. if (wNewSize <= wSize)
  223. {
  224. goto EXIT;
  225. }
  226. // Allocate new data and lock tables and make sure that succeeds.
  227. pNewDataTable = new EntryData*[wNewSize];
  228. if(pNewDataTable == NULL)
  229. {
  230. bRetCode = FALSE;
  231. goto EXIT;
  232. }
  233. pNewLockTable = new LOCK_ENTRY[wNewSize];
  234. if(pNewLockTable == NULL)
  235. {
  236. bRetCode = FALSE;
  237. goto CLEANUP1;
  238. }
  239. // Initialize the new section of the lock and data tables
  240. for (wIndex = wSize; wIndex < wNewSize; wIndex++)
  241. {
  242. pNewDataTable[wIndex] = NULL;
  243. pNewLockTable[wIndex].hLock = NULL;
  244. pNewLockTable[wIndex].iLockCount = 0;
  245. pNewLockTable[wIndex].wNextFree = (WORD) (wIndex + 1);
  246. }
  247. // Copy the old data table pointers to the new data table
  248. memcpy((PCHAR) pNewDataTable,
  249. (PCHAR) pDataTable,
  250. sizeof(EntryData*) * wSize);
  251. // Delete the old data table and fix the pointer
  252. delete pDataTable;
  253. pDataTable = pNewDataTable;
  254. // Copy the old lock table to the new lock table
  255. memcpy((PCHAR) pNewLockTable,
  256. (PCHAR) pLockTable,
  257. sizeof(LOCK_ENTRY) * wSize);
  258. // Delete the old lock table and fix the pointer
  259. delete pLockTable;
  260. pLockTable = pNewLockTable;
  261. // Fix the size variable
  262. wSize = wNewSize;
  263. goto EXIT;
  264. CLEANUP1:
  265. // Delete the new data table
  266. delete pNewDataTable;
  267. EXIT:
  268. // Unlock the table
  269. UnLockTable();
  270. return bRetCode;
  271. }
  272. /*
  273. ** TSTable::CreateAndLock
  274. *
  275. * FILENAME: c:\msdev\projects\firewalls\inc\table.h
  276. *
  277. * PARAMETERS:
  278. *
  279. * DESCRIPTION:
  280. *
  281. * RETURNS:
  282. *
  283. */
  284. template <class EntryData>
  285. BOOL TSTable<EntryData>::CreateAndLock(EntryData* pEntryData,
  286. LPDWORD lpdwID)
  287. {
  288. BOOL bRetCode = FALSE;
  289. WORD wIndex;
  290. // If the pointer passed in is bad, then don't even try to do anything for them
  291. if (pEntryData == NULL || lpdwID == NULL)
  292. {
  293. goto EXIT;
  294. }
  295. // Lock the table
  296. LockTable();
  297. // If the table is full, then resize it.
  298. if (wNumUsed == wSize)
  299. {
  300. if (Resize((WORD) (wSize + 20)) == FALSE)
  301. {
  302. goto EXIT;
  303. }
  304. }
  305. // Get the first free entry
  306. wIndex = wFirstFree;
  307. // Create the mutex for the object
  308. if ((pLockTable[wIndex].hLock = CreateMutexA(NULL, FALSE, NULL)) == NULL)
  309. {
  310. goto EXIT;
  311. }
  312. // Lock the entry (no need checking the return code as the entire
  313. // table is locked) - since this is a new entry, that means that nobody
  314. // could have locked the entry already.
  315. LockEntry(wIndex, 0);
  316. // Copy pointer to the data table
  317. pDataTable[wIndex] = pEntryData;
  318. // Init the corresponding lock table entry
  319. pLockTable[wIndex].bDeleted = FALSE;
  320. pLockTable[wIndex].iLockCount = 1;
  321. pLockTable[wIndex].wUniqueID = GenerateUniqueID();
  322. // Set the id for the caller
  323. *lpdwID = MakeID(wIndex, pLockTable[wIndex].wUniqueID);
  324. // Bump up the count of number used
  325. wNumUsed++;
  326. // Fix the next free index
  327. wFirstFree = pLockTable[wIndex].wNextFree;
  328. // Signal success
  329. bRetCode = TRUE;
  330. EXIT:
  331. // Unlock the table
  332. UnLockTable();
  333. return bRetCode;
  334. }
  335. /*
  336. ** TSTable::Lock
  337. *
  338. * FILENAME: c:\msdev\projects\firewalls\inc\table.h
  339. *
  340. * PARAMETERS:
  341. *
  342. * DESCRIPTION:
  343. *
  344. * RETURNS:
  345. *
  346. */
  347. template <class EntryData>
  348. EntryData* TSTable<EntryData>::Lock(DWORD dwID,
  349. DWORD timeout)
  350. {
  351. EntryData* pEntryData = NULL;
  352. WORD wIndex,
  353. wUID;
  354. BreakID(dwID, &wIndex, &wUID);
  355. // Lock the table
  356. LockTable();
  357. // Verify the index is within bounds
  358. if (wIndex >= wSize)
  359. {
  360. goto EXIT;
  361. }
  362. // Verify that the entry is actually valid (ie the lock in non-NULL,
  363. // the object status is valid, and the unique ID matches).
  364. if (pLockTable[wIndex].hLock == NULL ||
  365. pLockTable[wIndex].bDeleted == TRUE ||
  366. pLockTable[wIndex].wUniqueID != wUID)
  367. {
  368. goto EXIT;
  369. }
  370. // If the timeout is INFINITE, then try to lock the entry using a more
  371. // "thread friendly" method. If a timeout is specified, then don't do
  372. // the spin lock since it could be implemented at a higher level.
  373. if(timeout == INFINITE)
  374. {
  375. // simulate infinity with a pseudo "spin lock"
  376. // This is more "thread friendly" in that it unlocks the table allowing some
  377. // other thread that is trying to unlock the same entry to be able to lock the
  378. // table.
  379. while(LockEntry(wIndex, 0) == FALSE)
  380. {
  381. UnLockTable();
  382. // give up the rest of this thread quantum, allowing others to run and potentially
  383. // unlock the entry
  384. Sleep(0);
  385. LockTable();
  386. // If the entry has been replaced, deleted or marked for deletion then
  387. // bag it (give up)
  388. if((pLockTable[wIndex].wUniqueID != wUID) ||
  389. (pLockTable[wIndex].hLock == NULL) ||
  390. (pLockTable[wIndex].bDeleted == TRUE))
  391. {
  392. goto EXIT;
  393. }
  394. }
  395. // we got the lock
  396. pEntryData = pDataTable[wIndex];
  397. }
  398. // Otherwise, do a normal lock
  399. else
  400. {
  401. if (LockEntry(wIndex, timeout) == TRUE)
  402. {
  403. pEntryData = pDataTable[wIndex];
  404. }
  405. }
  406. EXIT:
  407. // Unlock the table
  408. UnLockTable();
  409. return pEntryData;
  410. }
  411. /*
  412. ** TSTable::Unlock
  413. *
  414. * FILENAME: c:\msdev\projects\firewalls\inc\table.h
  415. *
  416. * PARAMETERS:
  417. *
  418. * DESCRIPTION:
  419. *
  420. * RETURNS:
  421. *
  422. */
  423. template <class EntryData>
  424. BOOL TSTable<EntryData>::Unlock(DWORD dwID)
  425. {
  426. BOOL bRetCode = TRUE;
  427. WORD wIndex,
  428. wUID;
  429. BreakID(dwID, &wIndex, &wUID);
  430. // Lock the table
  431. LockTable();
  432. // Verify the id is within bounds
  433. if (wIndex >= wSize)
  434. {
  435. bRetCode = FALSE;
  436. goto EXIT;
  437. }
  438. // verify that the UID matches
  439. if (pLockTable[wIndex].wUniqueID != wUID)
  440. {
  441. bRetCode = FALSE;
  442. goto EXIT;
  443. }
  444. // Verify that the lock is actually valid and that the entry has not been
  445. // deleted
  446. if (pLockTable[wIndex].hLock == NULL)
  447. {
  448. goto EXIT;
  449. }
  450. // Make sure that that thread has the lock on the entry
  451. if ((bRetCode = LockEntry(wIndex, 0)) == TRUE)
  452. {
  453. // if this table entry is marked for delete and the lock count is less than 2
  454. // (since the thread could have called delete after unlocking the entry...although
  455. // this is a no-no) then clean up the table entry
  456. if (pLockTable[wIndex].bDeleted == TRUE &&
  457. pLockTable[wIndex].iLockCount <= 2)
  458. {
  459. // If the caller specifed cleanup on delete, then get rid of memory
  460. if (pLockTable[wIndex].bCleanup == TRUE)
  461. {
  462. delete pDataTable[wIndex];
  463. }
  464. // Set the pointer to NULL
  465. pDataTable[wIndex] = NULL;
  466. // Decrement the count of used entries
  467. wNumUsed--;
  468. // Fix the entry so that it's next free index is what is currently
  469. // the next free pointed to by the current last free entry.
  470. // Then update the last free entry's next pointer, and finally,
  471. // update the last free index to this entry
  472. pLockTable[wIndex].wNextFree = pLockTable[wLastFree].wNextFree;
  473. pLockTable[wLastFree].wNextFree = wIndex;
  474. wLastFree = wIndex;
  475. }
  476. // Do two unlocks on the entry ... one for the original lock and another for
  477. // the lock we obtained during the test
  478. UnLockEntry(wIndex);
  479. UnLockEntry(wIndex);
  480. // Since the entire table is locked, then we can get away with this. If
  481. // the code is ever changed so that the entire table is not locked during
  482. // these operations, then this will cause a race condition.
  483. // If we got rid of the data, then close the handle to the mutex and
  484. // set the handle to NULL
  485. if (pDataTable[wIndex] == NULL)
  486. {
  487. CloseHandle(pLockTable[wIndex].hLock);
  488. pLockTable[wIndex].hLock = NULL;
  489. }
  490. }
  491. EXIT:
  492. // Unlock the table
  493. UnLockTable();
  494. return bRetCode;
  495. }
  496. /*
  497. ** TSTable::Delete
  498. *
  499. * FILENAME: c:\msdev\projects\firewalls\inc\table.h
  500. *
  501. * PARAMETERS:
  502. *
  503. * DESCRIPTION:
  504. *
  505. * RETURNS:
  506. *
  507. */
  508. template <class EntryData>
  509. BOOL TSTable<EntryData>::Delete(DWORD dwID,
  510. BOOL bCleanup)
  511. {
  512. BOOL bRetCode = TRUE;
  513. WORD wIndex,
  514. wUID;
  515. BreakID(dwID, &wIndex, &wUID);
  516. // Lock the table
  517. LockTable();
  518. // Verify that the ID is within bounds
  519. if (wIndex >= wSize)
  520. {
  521. bRetCode = FALSE;
  522. goto EXIT;
  523. }
  524. // verify that the UID matches
  525. if (pLockTable[wIndex].wUniqueID != wUID)
  526. {
  527. bRetCode = FALSE;
  528. goto EXIT;
  529. }
  530. // Verify that the entry is valid
  531. if (pDataTable[wIndex] == NULL)
  532. {
  533. bRetCode = FALSE;
  534. goto EXIT;
  535. }
  536. // Try to lock the entry (ie check to see if we had the entry locked)
  537. if (LockEntry(wIndex, 0) == TRUE)
  538. {
  539. // mark it for deletion, set the cleanp flag and then unlock it
  540. pLockTable[wIndex].bDeleted = TRUE;
  541. pLockTable[wIndex].bCleanup = bCleanup;
  542. UnLockEntry(wIndex);
  543. // Note: this function does not call ::Unlock() on behalf of the user.
  544. // Thus, the entry is only marked as deleted at this point and can no
  545. // longer be locked by any threads (including the one that marked it for delete).
  546. // The thread that marked the entry as deleted must call ::Unlock() to actually
  547. // free up the entry.
  548. }
  549. EXIT:
  550. // Unlock the table
  551. UnLockTable();
  552. return bRetCode;
  553. }
  554. /*
  555. ** TSTable::Lock
  556. *
  557. * FILENAME: c:\msdev\projects\firewalls\inc\table.h
  558. *
  559. * PARAMETERS:
  560. *
  561. * DESCRIPTION: Validates that an object still exists. Can be called
  562. * regardless if caller has entry locked or not.
  563. *
  564. * RETURNS:
  565. *
  566. */
  567. template <class EntryData>
  568. BOOL TSTable<EntryData>::Validate(DWORD dwID)
  569. {
  570. BOOL bRetCode = TRUE;
  571. WORD wIndex,
  572. wUID;
  573. BreakID(dwID, &wIndex, &wUID);
  574. // Lock the table
  575. LockTable();
  576. // Verify the index is within bounds
  577. if (wIndex >= wSize)
  578. {
  579. bRetCode = FALSE;
  580. goto EXIT;
  581. }
  582. // Verify that the entry is actually valid (ie the lock in non-NULL,
  583. // the object status is valid, the unique ID matches, and the data ptr is not null).
  584. if (pLockTable[wIndex].hLock == NULL ||
  585. pLockTable[wIndex].bDeleted == TRUE ||
  586. pLockTable[wIndex].wUniqueID != wUID ||
  587. pDataTable[wIndex] == NULL)
  588. {
  589. bRetCode = FALSE;
  590. goto EXIT;
  591. }
  592. EXIT:
  593. // Unlock the table
  594. UnLockTable();
  595. return bRetCode;
  596. }
  597. /*
  598. ** TSTable::EnumerateEntries
  599. *
  600. * FILENAME: c:\msdev\projects\firewalls\inc\table.h
  601. *
  602. * PARAMETERS:
  603. *
  604. * DESCRIPTION:
  605. *
  606. * RETURNS:
  607. *
  608. */
  609. template <class EntryData>
  610. EntryData* TSTable<EntryData>::EnumerateEntries(TABLE_CALLBACK callbackFunc,
  611. LPVOID context,
  612. BOOL bUnlockTable)
  613. {
  614. DWORD dwAction;
  615. WORD wIndex = wSize;
  616. EntryData* pEntryData = NULL;
  617. DWORD dwEntryID;
  618. // Make sure they passed a good function
  619. if (callbackFunc == NULL)
  620. {
  621. goto EXIT;
  622. }
  623. // Lock the table
  624. LockTable();
  625. // Run through the data table and pass the data to the callback function
  626. for (wIndex = 0; wIndex < wSize; wIndex++)
  627. {
  628. // Verify that there is actually data in the entry and that the entry has not
  629. // been marked for deletion.
  630. if (pDataTable[wIndex] == NULL ||
  631. pLockTable[wIndex].bDeleted == TRUE)
  632. {
  633. continue;
  634. }
  635. // Try to lock the entry...if we cannot, then we don't have the lock and
  636. // we will only report entries that we have locked (or are unlocked)
  637. if (LockEntry(wIndex, 0) == FALSE)
  638. {
  639. continue;
  640. }
  641. // build and remember the "full" entry ID so we can use it to unlock the entry
  642. dwEntryID = MakeID(wIndex, pLockTable[wIndex].wUniqueID);
  643. // Save the pointer to the object.
  644. pEntryData = pDataTable[wIndex];
  645. // note: only unlock the table during the callback if we are explicitly asked to (the
  646. // default is not to unlock the table).
  647. if(bUnlockTable == TRUE)
  648. UnLockTable();
  649. // Call their function
  650. dwAction = callbackFunc(pDataTable[wIndex], context);
  651. if(bUnlockTable == TRUE)
  652. LockTable();
  653. // If the action says to delete the entry, then do so...if we are also to delete
  654. // the object, pass in a TRUE.
  655. if (dwAction == CALLBACK_DELETE_ENTRY ||
  656. dwAction == CALLBACK_DELETE_ENTRY_AND_OBJECT)
  657. {
  658. Delete(dwEntryID, (dwAction == CALLBACK_DELETE_ENTRY ? FALSE : TRUE));
  659. }
  660. // If the action says abort, then break the loop...notice that means that
  661. // the entry is still locked
  662. else if (dwAction == CALLBACK_ABORT)
  663. {
  664. goto EXIT;
  665. }
  666. // Unlock the entry...notice we don't use UnLockEntry. The reason is that
  667. // if the entry has been marked as deleted, then we need to have
  668. // it destroyed and UnLockEntry doesn't do that.
  669. Unlock(dwEntryID);
  670. }
  671. EXIT:
  672. // Unlock the table
  673. UnLockTable();
  674. // Return NULL if we processed the entire table...if we were told to abort,
  675. // return a pointer to the entry we stopped on.
  676. return (wIndex == wSize ? NULL : pEntryData);
  677. }
  678. // helper functions - these assume table is locked and index is good
  679. /*
  680. ** TSTable::LockEntry
  681. *
  682. * FILENAME: c:\msdev\projects\firewalls\inc\table.h
  683. *
  684. * PARAMETERS:
  685. *
  686. * DESCRIPTION:
  687. *
  688. * RETURNS:
  689. *
  690. */
  691. template <class EntryData>
  692. BOOL TSTable<EntryData>::LockEntry(WORD wIndex,
  693. DWORD timeout)
  694. {
  695. BOOL bRetCode = TRUE;
  696. DWORD dwRetCode;
  697. // Try to lock the entry. If it succeeds, we'll bump up the lock count. If
  698. // the wait ended because another thread abandoned the mutex, then set the count
  699. // to one.
  700. dwRetCode = WaitForSingleObject(pLockTable[wIndex].hLock, timeout);
  701. if (dwRetCode == WAIT_OBJECT_0)
  702. {
  703. pLockTable[wIndex].iLockCount++;
  704. }
  705. else if (dwRetCode == WAIT_ABANDONED)
  706. {
  707. pLockTable[wIndex].iLockCount = 1;
  708. }
  709. else
  710. {
  711. bRetCode = FALSE;
  712. }
  713. return bRetCode;
  714. }
  715. /*
  716. ** TSTable::UnLockEntry
  717. *
  718. * FILENAME: c:\msdev\projects\firewalls\inc\table.h
  719. *
  720. * PARAMETERS:
  721. *
  722. * DESCRIPTION:
  723. *
  724. * RETURNS:
  725. *
  726. */
  727. template <class EntryData>
  728. BOOL TSTable<EntryData>::UnLockEntry(WORD wIndex)
  729. {
  730. BOOL bRetCode;
  731. // Release the mutex...if that succeeds, reduce the count
  732. if((bRetCode = ReleaseMutex(pLockTable[wIndex].hLock)) == TRUE)
  733. {
  734. pLockTable[wIndex].iLockCount--;
  735. }
  736. return bRetCode;
  737. }
  738. /*
  739. ** TSTable::GenerateUniqueID
  740. *
  741. * FILENAME: c:\msdev\projects\firewalls\inc\table.h
  742. *
  743. * PARAMETERS:
  744. *
  745. * DESCRIPTION: table should be locked before calling this function.
  746. *
  747. * RETURNS:
  748. *
  749. */
  750. template <class EntryData>
  751. WORD TSTable<EntryData>::GenerateUniqueID()
  752. {
  753. // table must be locked
  754. if(++wUniqueID == TSTABLE_INVALID_UNIQUE_ID)
  755. wUniqueID++;
  756. return(wUniqueID);
  757. }
  758. #endif