Source code of Windows XP (NT5)
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.

350 lines
6.6 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. refcnt.c
  5. Abstract:
  6. This module exports Reference Counting support functions. By
  7. including a Reference Count Control Block (REF_CNT) in a
  8. dynamic type, and using this API, a Reference scheme can be
  9. implemented for that type.
  10. Author:
  11. Edward Buchwalter (v-edbuc) 14-Aug-1996
  12. Revision History:
  13. --*/
  14. //
  15. // Include Files
  16. //
  17. #include "irda.h"
  18. #define EXPAND_TAG(t) ((CHAR *)(&Tag))[0],((CHAR *)(&Tag))[1],((CHAR *)(&Tag))[2],((CHAR *)(&Tag))[3]
  19. VOID
  20. ReferenceInit
  21. (
  22. IN PREF_CNT pRefCnt,
  23. PVOID InstanceHandle,
  24. VOID (*DeleteHandler)( PVOID )
  25. )
  26. /*++
  27. Routine Description:
  28. ReferenceInit initializes and adds one reference to the
  29. supplied Reference Control Block. If provided, an instance
  30. handle and delete handler are saved for use by the ReferenceRemove
  31. function when all references to the instance are removed.
  32. Arguments:
  33. pRefCnt - pointer to uninitialized Reference Control Block
  34. InstanceHandle - handle to the managed instance.
  35. DeleteHandler - pointer to delete function, NULL is OK.
  36. Return Value:
  37. The function's value is VOID.
  38. --*/
  39. {
  40. DEBUGMSG( DBG_REF,( TEXT("ReferenceInit( 0x%x, 0x%x, 0x%x )\n"),
  41. pRefCnt, InstanceHandle, DeleteHandler ));
  42. ASSERT( pRefCnt );
  43. // Set the reference to 1 and save the instance
  44. // handle and the delete handler.
  45. pRefCnt->Count = 0;
  46. pRefCnt->Instance = InstanceHandle;
  47. pRefCnt->DeleteHandler = DeleteHandler;
  48. #if DBG
  49. pRefCnt->Sig = REF_SIG;
  50. RtlZeroMemory(pRefCnt->Tags, sizeof(REF_TAG) * TAG_CNT);
  51. pRefCnt->Tags[0].Tag = 'LTOT';
  52. CTEInitLock(&pRefCnt->Lock);
  53. #endif
  54. }
  55. VOID
  56. ReferenceAdd
  57. (
  58. IN PREF_CNT pRefCnt
  59. )
  60. /*++
  61. Routine Description:
  62. Arguments:
  63. Return Value:
  64. --*/
  65. {
  66. ASSERT( pRefCnt );
  67. InterlockedIncrement(&pRefCnt->Count);
  68. // DEBUGMSG( DBG_REF,( TEXT("R+%d\n"), pRefCnt->Count ));
  69. }
  70. VOID
  71. ReferenceAddCount
  72. (
  73. IN PREF_CNT pRefCnt,
  74. IN UINT Count
  75. )
  76. /*++
  77. Routine Description:
  78. Arguments:
  79. Return Value:
  80. --*/
  81. {
  82. ASSERT( pRefCnt->Count > 0 );
  83. CTEInterlockedExchangeAdd(&pRefCnt->Count, Count);
  84. }
  85. PVOID
  86. ReferenceRemove
  87. (
  88. IN PREF_CNT pRefCnt
  89. )
  90. /*++
  91. Routine Description:
  92. Arguments:
  93. Return Value:
  94. --*/
  95. {
  96. ASSERT( pRefCnt );
  97. // Trap remove reference on a zero count
  98. ASSERT( pRefCnt->Count > 0 );
  99. // If the decremented count is non zero return the instance handle
  100. if (InterlockedDecrement(&pRefCnt->Count) > 0 )
  101. {
  102. // DEBUGMSG( DBG_REF,( TEXT("R-%d\n"), pRefCnt->Count ));
  103. // DEBUGMSG( DBG_REF,( TEXT("ReferenceRemove:remaining: %d\n"), pRefCnt->Count ));
  104. return( pRefCnt->Instance );
  105. }
  106. // Delete this instance if a delete handler is available
  107. if( pRefCnt->DeleteHandler )
  108. {
  109. DEBUGMSG( DBG_REF,( TEXT("Executing DeleteHandler\n") ));
  110. (pRefCnt->DeleteHandler)( pRefCnt->Instance );
  111. }
  112. // Indicate no active references to this instance
  113. return( NULL );
  114. }
  115. //
  116. // API Test Support
  117. //
  118. #if DBG
  119. VOID
  120. ReferenceApiTest( VOID )
  121. {
  122. REF_CNT RefCnt;
  123. DEBUGMSG( 1,( TEXT("\nReferenceApiTest\n") ));
  124. DEBUGMSG( 1,( TEXT("\nTest #1: NULL delete handler\n") ));
  125. ReferenceInit( &RefCnt, &RefCnt, NULL );
  126. ReferenceAdd( &RefCnt );
  127. ReferenceAdd( &RefCnt );
  128. ReferenceAdd( &RefCnt );
  129. while( ReferenceRemove( &RefCnt ) )
  130. {
  131. ;
  132. }
  133. DEBUGMSG( 1,( TEXT("\nTest #2: Delete Handler - TBD\n") ));
  134. }
  135. VOID
  136. ReferenceAddDbg(PREF_CNT pRefCnt, ULONG Tag)
  137. {
  138. int i;
  139. CTELockHandle hLock;
  140. int TotalPerArray = 0;
  141. ASSERT(pRefCnt->Sig == REF_SIG);
  142. DEBUGMSG(DBG_REF, (TEXT("IRREF: add %X (%c%c%c%c) %d\n"),
  143. pRefCnt, EXPAND_TAG(Tag), pRefCnt->Count));
  144. CTEGetLock(&pRefCnt->Lock, &hLock);
  145. for (i = 1; i < TAG_CNT; i++)
  146. {
  147. if (pRefCnt->Tags[i].Tag == 0 || pRefCnt->Tags[i].Tag == Tag)
  148. {
  149. pRefCnt->Tags[i].Tag = Tag;
  150. InterlockedIncrement(&pRefCnt->Tags[i].Count);
  151. break;
  152. }
  153. }
  154. ASSERT(i < TAG_CNT);
  155. InterlockedIncrement(&pRefCnt->Tags[0].Count);
  156. InterlockedIncrement(&pRefCnt->Count);
  157. ASSERT(pRefCnt->Tags[0].Count == pRefCnt->Count);
  158. // sanity check
  159. /*
  160. for (i = 1; i < TAG_CNT; i++)
  161. {
  162. if (pRefCnt->Tags[i].Tag != 0)
  163. {
  164. TotalPerArray += pRefCnt->Tags[i].Count;
  165. continue;
  166. }
  167. }
  168. ASSERT(TotalPerArray == pRefCnt->Tags[0].Count);
  169. if (TotalPerArray != pRefCnt->Tags[0].Count)
  170. {
  171. DbgBreakPoint();
  172. }
  173. */
  174. CTEFreeLock(&pRefCnt->Lock, hLock);
  175. }
  176. VOID
  177. ReferenceRemoveDbg(PREF_CNT pRefCnt, ULONG Tag)
  178. {
  179. int i;
  180. CTELockHandle hLock;
  181. int TotalPerArray = 0;
  182. BOOLEAN FoundIt = FALSE;
  183. ASSERT(pRefCnt->Sig == REF_SIG);
  184. DEBUGMSG(DBG_REF, (TEXT("IRREF: remove %X (%c%c%c%c) %d\n"),
  185. pRefCnt, EXPAND_TAG(Tag), pRefCnt->Count));
  186. CTEGetLock(&pRefCnt->Lock, &hLock);
  187. for (i = 1; i < TAG_CNT; i++)
  188. {
  189. if (pRefCnt->Tags[i].Tag == Tag)
  190. {
  191. FoundIt = TRUE;
  192. ASSERT(pRefCnt->Tags[i].Count > 0);
  193. InterlockedDecrement(&pRefCnt->Tags[i].Count);
  194. if (pRefCnt->Tags[i].Count == 0)
  195. pRefCnt->Tags[i].Tag = Tag;
  196. break;
  197. }
  198. }
  199. ASSERT(FoundIt);
  200. ASSERT(pRefCnt->Tags[0].Count > 0);
  201. ASSERT(pRefCnt->Tags[0].Count == pRefCnt->Count);
  202. InterlockedDecrement(&pRefCnt->Tags[0].Count);
  203. if (InterlockedDecrement(&pRefCnt->Count) > 0 )
  204. {
  205. CTEFreeLock(&pRefCnt->Lock, hLock);
  206. }
  207. else if (pRefCnt->DeleteHandler)
  208. {
  209. DEBUGMSG( DBG_REF,( TEXT("Executing DeleteHandler\n") ));
  210. CTEFreeLock(&pRefCnt->Lock, hLock);
  211. (pRefCnt->DeleteHandler)( pRefCnt->Instance );
  212. }
  213. else
  214. {
  215. CTEFreeLock(&pRefCnt->Lock, hLock);
  216. }
  217. /*
  218. // sanity check
  219. for (i = 1; i < TAG_CNT; i++)
  220. {
  221. if (pRefCnt->Tags[i].Tag != 0)
  222. {
  223. TotalPerArray += pRefCnt->Tags[i].Count;
  224. continue;
  225. }
  226. }
  227. ASSERT(TotalPerArray == pRefCnt->Tags[0].Count);
  228. if (TotalPerArray != pRefCnt->Tags[0].Count)
  229. {
  230. DbgPrint(TEXT("Tag %X, RefCnt %X, perArray %d, total %d\n"), Tag, pRefCnt,
  231. TotalPerArray, pRefCnt->Tags[0].Count);
  232. DbgBreakPoint();
  233. }
  234. */
  235. }
  236. #endif