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.

587 lines
9.7 KiB

  1. /*++
  2. Copyright (c) 2000, Microsoft Corporation
  3. Module Name:
  4. Abstract:
  5. Author:
  6. Savas Guven (savasg) 27-Nov-2000
  7. Revision History:
  8. --*/
  9. #include "stdafx.h"
  10. //#include "sync.h"
  11. #define ERROR_CREATING_SYNC_OBJECT 0x0001
  12. //
  13. // STATIC MEMBER INITIALIZATIONS
  14. //
  15. const PCHAR COMPONENT_SYNC::ObjectNamep = "COMPONENT_SYNC";
  16. COMPONENT_SYNC::COMPONENT_SYNC()
  17. /*++
  18. Routine Description:
  19. Deafault Constructor
  20. Arguments:
  21. NONE
  22. Return Value:
  23. NONE
  24. --*/
  25. :Deleted(FALSE),
  26. bCleanupCalled(FALSE),
  27. m_ReferenceCount(1)
  28. {
  29. ICQ_TRC(TM_SYNC, TL_DUMP, ("%s> COMPONENT::DeFAULT Constructor",
  30. this->GetObjectName()));
  31. this->InitializeSync();
  32. }
  33. COMPONENT_SYNC::~COMPONENT_SYNC()
  34. /*++
  35. Routine Description:
  36. Destructor of the COMPONEN_REFERENCE and SYNC object
  37. Arguments:
  38. NONE
  39. Return Value:
  40. NONE
  41. --*/
  42. {
  43. ICQ_TRC(TM_SYNC, TL_DUMP, ("%s> COMPONENT::~ Destructor",
  44. this->GetObjectName()));
  45. if(this->bCleanupCalled is FALSE)
  46. {
  47. COMPONENT_SYNC::ComponentCleanUpRoutine();
  48. }
  49. this->bCleanupCalled = FALSE;
  50. }
  51. void
  52. COMPONENT_SYNC::ComponentCleanUpRoutine(void)
  53. /*++
  54. Routine Description:
  55. CleanupRoutine of the SYNCHRONIZATION Object.
  56. Only the CRITICAL_SECTION needs to be deleted properly.
  57. Arguments:
  58. NONE
  59. Return Value:
  60. NONE
  61. --*/
  62. {
  63. ICQ_TRC(TM_SYNC, TL_TRACE, ("%s> COMPONENT::ComponentCleanUpRoutine",
  64. this->GetObjectName()));
  65. DeleteSync();
  66. this->bCleanupCalled = TRUE;
  67. }
  68. void
  69. COMPONENT_SYNC::DeleteSync( void )
  70. /*++
  71. Routine Description:
  72. This routine is called to destroy a component reference.
  73. It may only be called after the lastreference to the component is released,
  74. i.e. after 'ReleaseComponentReference' has returned 'TRUE'.
  75. It may also be called from within the component's 'CleanupRoutine'.
  76. Arguments:
  77. ComponentReference - the component to be destroyed
  78. Return Value:
  79. none.
  80. --*/
  81. {
  82. DeleteCriticalSection(&this->m_Lock);
  83. #if COMPREF_DEBUG_TRACKING
  84. if ( m_RecordArray != NULL )
  85. HeapFree(GetProcessHeap(), 0, m_RecordArray);
  86. m_RecordArray = NULL;
  87. #endif
  88. }
  89. ULONG
  90. COMPONENT_SYNC::InitializeSync(void)
  91. /*++
  92. Routine Description:
  93. This routine is called to initialize a component reference.
  94. Arguments:
  95. ComponentReference - the component to be initialized
  96. CleanupRoutine - the routine to be called when the component
  97. is to be cleaned up (within the final 'ReleaseComponentReference').
  98. Return Value:
  99. none.
  100. --*/
  101. {
  102. ICQ_TRC(TM_SYNC, TL_DUMP, ("COMPONENT - InitializeSync"));
  103. InitializeCriticalSection(&this->m_Lock);
  104. this->Deleted = FALSE;
  105. this->bCleanupCalled = FALSE;
  106. this->m_ReferenceCount = 1;
  107. #if COMPREF_DEBUG_TRACKING
  108. m_RecordIndex = 0;
  109. m_RecordArray = (PCOMPREF_DEBUG_RECORD_)HeapAlloc(GetProcessHeap(),
  110. 0,
  111. sizeof(COMPREF_DEBUG_RECORD_) * _COMPREF_DEBUG_RECORD_COUNT );
  112. if ( m_RecordArray != NULL )
  113. {
  114. ZeroMemory(m_RecordArray,
  115. sizeof(COMPREF_DEBUG_RECORD_) * _COMPREF_DEBUG_RECORD_COUNT);
  116. }
  117. #endif
  118. return NO_ERROR;
  119. }
  120. BOOLEAN
  121. COMPONENT_SYNC::ReferenceSync(void)
  122. /*++
  123. Routine Description:
  124. This routine is called to increment the reference-count to a component.
  125. The attempt may fail if the initial reference has been released
  126. and the component is therefore being deleted.
  127. Arguments:
  128. ComponentReference - the component to be referenced
  129. Return Value:
  130. BOOLEAN - TRUE if the component was referenced, FALSE otherwise.
  131. --*/
  132. {
  133. ICQ_TRC(TM_SYNC, TL_TRACE, ("%s> COMPONENT - REFERENCE %u + 1",
  134. this->GetObjectName(),
  135. this->m_ReferenceCount));
  136. EnterCriticalSection(&this->m_Lock);
  137. if(this->Deleted)
  138. {
  139. LeaveCriticalSection(&this->m_Lock);
  140. return FALSE;
  141. }
  142. InterlockedIncrement( (LPLONG) &m_ReferenceCount) ;
  143. LeaveCriticalSection(&this->m_Lock);
  144. return TRUE;
  145. }
  146. BOOLEAN
  147. COMPONENT_SYNC::DereferenceSync( void )
  148. /*++
  149. Routine Description:
  150. This routine is called to drop a reference to a component.
  151. If the reference drops to zero, cleanup is performed.
  152. Otherwise, cleanup occurs later when the last reference is released.
  153. Arguments:
  154. ComponentReference - the component to be referenced
  155. Return Value:
  156. BOOLEAN - TRUE if the component was cleaned up, FALSE otherwise.
  157. --*/
  158. {
  159. ICQ_TRC(TM_SYNC, TL_TRACE, ("%s> DEREFERENCE %u - 1",
  160. this->GetObjectName(),
  161. this->m_ReferenceCount));
  162. this->AcquireLock();
  163. if( InterlockedDecrement((LPLONG) &m_ReferenceCount) )
  164. {
  165. this->ReleaseLock();
  166. return FALSE;
  167. }
  168. this->ReleaseLock();
  169. this->ComponentCleanUpRoutine();
  170. this->Deleted = TRUE;
  171. return TRUE;
  172. }
  173. //
  174. //
  175. //
  176. inline void
  177. COMPONENT_SYNC::AcquireLock()
  178. {
  179. ICQ_TRC(TM_SYNC, TL_DUMP, ("COMPONENT - Acquire Lock"));
  180. EnterCriticalSection(&m_Lock);
  181. }
  182. inline void
  183. COMPONENT_SYNC::ReleaseLock()
  184. {
  185. ICQ_TRC(TM_SYNC, TL_DUMP, ("COMPONENT - Release Lock"));
  186. LeaveCriticalSection(&m_Lock);
  187. }
  188. #if 0
  189. void
  190. COMPONENT_SYNC::ResetSync(void)
  191. /*++
  192. Routine Description:
  193. This routine is called to reset a component reference
  194. to an initial state.
  195. Arguments:
  196. ComponentReference - the component to be reset
  197. Return Value:
  198. none.
  199. --*/
  200. {
  201. EnterCriticalSection(&this->m_Lock);
  202. this->m_ReferenceCount = 1;
  203. this->Deleted = FALSE;
  204. #if COMPREF_DEBUG_TRACKING
  205. this->RecordIndex = 0;
  206. ZeroMemory(this->RecordArray,
  207. sizeof(COMPREF_DEBUG_RECORD_) * _COMPREF_DEBUG_RECORD_COUNT);
  208. #endif
  209. } // Release
  210. BOOLEAN
  211. COMPONENT_SYNC::ReleaseInitialSync(void)
  212. /*++
  213. Routine Description:
  214. This routine is called to drop the initial reference to a component,
  215. and mark the component as deleted.
  216. If the reference drops to zero, cleanup is performed right away.
  217. Arguments:
  218. ComponentReference - the component to be referenced
  219. Return Value:
  220. BOOLEAN - TRUE if the component was cleaned up, FALSE otherwise.
  221. --*/
  222. {
  223. this->AcquireLock();
  224. if(this->Deleted)
  225. {
  226. this->ReleaseLock();
  227. return TRUE;
  228. }
  229. this->Deleted = TRUE;
  230. if(--this->m_ReferenceCount)
  231. {
  232. this->ReleaseLock();
  233. return FALSE;
  234. }
  235. this->ReleaseLock();
  236. this->ComponentCleanUpRoutine();
  237. return TRUE;
  238. }
  239. #endif
  240. BOOLEAN
  241. COMPONENT_SYNC::RecordRef(
  242. ULONG RefId,
  243. PCHAR File,
  244. ULONG Line
  245. )
  246. /*++
  247. Routine Description:
  248. Arguments:
  249. FILE - Records in which file the SYNC object is accessed
  250. LINE - which Line in the FILE
  251. TYPE - and the TYPE of operation desired
  252. Return Value:
  253. none.
  254. --*/
  255. {
  256. #if COMPREF_DEBUG_TRACKING
  257. if ( NULL == m_RecordArray )
  258. {
  259. return FALSE;
  260. }
  261. this->AcquireLock();
  262. //
  263. // Find The first empty slot to which to add this.
  264. //
  265. for ( int i = 0; i < _COMPREF_DEBUG_RECORD_COUNT; i++ )
  266. {
  267. if ( FALSE == m_RecordArray[i].bInUse )
  268. {
  269. m_RecordArray[i].OpCode = RefId;
  270. m_RecordArray[i].File = File;
  271. m_RecordArray[i].Line = Line;
  272. m_RecordArray[i].Type = eReferencing;
  273. m_RecordArray[i].bInUse = TRUE;
  274. break;
  275. }
  276. }
  277. this->ReleaseLock();
  278. #endif
  279. return TRUE;
  280. }
  281. BOOLEAN
  282. COMPONENT_SYNC::RecordDeref(
  283. ULONG RefId,
  284. PCHAR File,
  285. ULONG Line
  286. )
  287. {
  288. int UnusedEntryIndex = -1;
  289. BOOLEAN bFound = FALSE;
  290. #if COMPREF_DEBUG_TRACKING
  291. if ( NULL == m_RecordArray )
  292. {
  293. return FALSE;
  294. }
  295. this->AcquireLock();
  296. //
  297. // Search for the RefId in the existing
  298. //
  299. for ( int i = 0; i < _COMPREF_DEBUG_RECORD_COUNT; i++ )
  300. {
  301. //
  302. // if you find a reference with the same OpCode / RefId delete the entry
  303. //
  304. if (
  305. ( TRUE == m_RecordArray[i].bInUse ) &&
  306. ( m_RecordArray[i].OpCode == RefId )
  307. )
  308. {
  309. ZeroMemory( &(m_RecordArray[i]), sizeof(COMPREF_DEBUG_RECORD_) );
  310. bFound = TRUE;
  311. break;
  312. }
  313. if ( (-1 == UnusedEntryIndex ) && (FALSE == m_RecordArray[i].bInUse) )
  314. {
  315. UnusedEntryIndex = i;
  316. }
  317. }
  318. //
  319. // if there is no REF code for this DEREF note it down
  320. //
  321. if ( (FALSE == bFound) && (0 <= UnusedEntryIndex) )
  322. {
  323. m_RecordArray[i].OpCode = RefId;
  324. m_RecordArray[i].File = File;
  325. m_RecordArray[i].Line = Line;
  326. m_RecordArray[i].Type = eDereferencing;
  327. m_RecordArray[i].bInUse = TRUE;
  328. }
  329. this->ReleaseLock();
  330. #endif
  331. return TRUE;
  332. }
  333. BOOLEAN
  334. COMPONENT_SYNC::ReportRefRecord()
  335. {
  336. #if COMPREF_DEBUG_TRACKING
  337. if ( NULL == m_RecordArray )
  338. {
  339. return FALSE;
  340. }
  341. //
  342. // scan the Ref Records and print them..
  343. //
  344. ICQ_TRC(TM_SYNC, TL_ERROR, ("Object Name: %s Ref History :",
  345. this->GetObjectName()));
  346. for (int i = 0; i < _COMPREF_DEBUG_RECORD_COUNT; i++)
  347. {
  348. if ( TRUE == m_RecordArray[i].bInUse )
  349. {
  350. ICQ_TRC(TM_SYNC, TL_ERROR,
  351. ("%d) OpCode (%X), File (%s), Line (%u), Type (%s)",
  352. i,
  353. m_RecordArray[i].OpCode,
  354. m_RecordArray[i].File,
  355. m_RecordArray[i].Line,
  356. (eReferencing == m_RecordArray[i].Type)?"Ref":"Deref"));
  357. }
  358. }
  359. #endif
  360. return TRUE;
  361. }