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.

484 lines
10 KiB

  1. #ifndef __READERWRITER_CPP
  2. #define __READERWRITER_CPP
  3. /*++
  4. Copyright (C) 1996-2001 Microsoft Corporation
  5. Module Name:
  6. ReaderWriter.cpp
  7. Abstract:
  8. Enhancements to current functionality:
  9. Timeout mechanism should track across waits.
  10. AddRef/Release on task when scheduling.
  11. Enhancement Ticker logic.
  12. History:
  13. --*/
  14. #include <windows.h>
  15. #include <ReaderWriter.h>
  16. /******************************************************************************
  17. *
  18. * Name:
  19. *
  20. *
  21. * Description:
  22. *
  23. *
  24. *****************************************************************************/
  25. WmiMultiReaderSingleWriter :: WmiMultiReaderSingleWriter (
  26. const LONG &a_ReaderSize
  27. ) : m_ReaderSize ( a_ReaderSize ) ,
  28. m_ReaderSemaphore ( NULL ) ,
  29. m_InitializationStatusCode ( e_StatusCode_Success ) ,
  30. m_WriterCriticalSection (NOTHROW_LOCK)
  31. {
  32. m_InitializationStatusCode = WmiHelper :: InitializeCriticalSection ( & m_WriterCriticalSection ) ;
  33. if ( m_InitializationStatusCode == e_StatusCode_Success )
  34. {
  35. m_ReaderSemaphore = CreateSemaphore ( NULL , m_ReaderSize , m_ReaderSize , NULL ) ;
  36. if ( ! m_ReaderSemaphore )
  37. {
  38. m_InitializationStatusCode = e_StatusCode_OutOfResources ;
  39. }
  40. }
  41. }
  42. /******************************************************************************
  43. *
  44. * Name:
  45. *
  46. *
  47. * Description:
  48. *
  49. *
  50. *****************************************************************************/
  51. WmiMultiReaderSingleWriter :: ~WmiMultiReaderSingleWriter ()
  52. {
  53. WmiHelper :: DeleteCriticalSection ( & m_WriterCriticalSection ) ;
  54. if ( m_ReaderSemaphore )
  55. {
  56. CloseHandle ( m_ReaderSemaphore ) ;
  57. }
  58. }
  59. /******************************************************************************
  60. *
  61. * Name:
  62. *
  63. *
  64. * Description:
  65. *
  66. *
  67. *****************************************************************************/
  68. WmiStatusCode WmiMultiReaderSingleWriter :: Initialize ()
  69. {
  70. return m_InitializationStatusCode ;
  71. }
  72. /******************************************************************************
  73. *
  74. * Name:
  75. *
  76. *
  77. * Description:
  78. *
  79. *
  80. *****************************************************************************/
  81. WmiStatusCode WmiMultiReaderSingleWriter :: UnInitialize ()
  82. {
  83. WmiStatusCode t_StatusCode = e_StatusCode_Success ;
  84. return t_StatusCode ;
  85. }
  86. /******************************************************************************
  87. *
  88. * Name:
  89. *
  90. *
  91. * Description:
  92. *
  93. *
  94. *****************************************************************************/
  95. WmiStatusCode WmiMultiReaderSingleWriter :: EnterRead ()
  96. {
  97. if ( m_InitializationStatusCode == e_StatusCode_Success )
  98. {
  99. WmiStatusCode t_StatusCode = WmiHelper :: EnterCriticalSection ( & m_WriterCriticalSection ) ;
  100. if ( t_StatusCode == e_StatusCode_Success )
  101. {
  102. LONG t_Reason = WaitForSingleObject ( m_ReaderSemaphore , INFINITE ) ;
  103. if ( t_Reason != WAIT_OBJECT_0 )
  104. {
  105. t_StatusCode = e_StatusCode_Unknown ;
  106. }
  107. WmiHelper :: LeaveCriticalSection ( & m_WriterCriticalSection ) ;
  108. }
  109. return t_StatusCode ;
  110. }
  111. return e_StatusCode_NotInitialized ;
  112. }
  113. /******************************************************************************
  114. *
  115. * Name:
  116. *
  117. *
  118. * Description:
  119. *
  120. *
  121. *****************************************************************************/
  122. WmiStatusCode WmiMultiReaderSingleWriter :: EnterWrite ()
  123. {
  124. if ( m_InitializationStatusCode == e_StatusCode_Success )
  125. {
  126. WmiStatusCode t_StatusCode = WmiHelper :: EnterCriticalSection ( & m_WriterCriticalSection ) ;
  127. if ( t_StatusCode == e_StatusCode_Success )
  128. {
  129. bool t_Waiting = true ;
  130. while ( t_Waiting )
  131. {
  132. LONG t_Reason = WaitForSingleObject ( m_ReaderSemaphore , INFINITE ) ;
  133. if ( t_Reason != WAIT_OBJECT_0 )
  134. {
  135. WmiHelper :: LeaveCriticalSection ( & m_WriterCriticalSection ) ;
  136. return e_StatusCode_Unknown ;
  137. }
  138. LONG t_SemaphoreCount = 0 ;
  139. BOOL t_Status = ReleaseSemaphore ( m_ReaderSemaphore , 1 , & t_SemaphoreCount ) ;
  140. if ( t_Status )
  141. {
  142. if ( t_SemaphoreCount == m_ReaderSize - 1 )
  143. {
  144. t_Waiting = false ;
  145. }
  146. else
  147. {
  148. SwitchToThread () ;
  149. }
  150. }
  151. else
  152. {
  153. WmiHelper :: LeaveCriticalSection ( & m_WriterCriticalSection ) ;
  154. return e_StatusCode_Unknown ;
  155. }
  156. }
  157. return t_StatusCode ;
  158. }
  159. }
  160. return e_StatusCode_NotInitialized ;
  161. }
  162. /******************************************************************************
  163. *
  164. * Name:
  165. *
  166. *
  167. * Description:
  168. *
  169. *
  170. *****************************************************************************/
  171. WmiStatusCode WmiMultiReaderSingleWriter :: LeaveRead ()
  172. {
  173. LONG t_SemaphoreCount = 0 ;
  174. BOOL t_Status = ReleaseSemaphore ( m_ReaderSemaphore , 1 , & t_SemaphoreCount ) ;
  175. if ( t_Status )
  176. {
  177. return e_StatusCode_Success ;
  178. }
  179. return e_StatusCode_Unknown ;
  180. }
  181. /******************************************************************************
  182. *
  183. * Name:
  184. *
  185. *
  186. * Description:
  187. *
  188. *
  189. *****************************************************************************/
  190. WmiStatusCode WmiMultiReaderSingleWriter :: LeaveWrite ()
  191. {
  192. return WmiHelper :: LeaveCriticalSection ( & m_WriterCriticalSection ) ;
  193. }
  194. /******************************************************************************
  195. *
  196. * Name:
  197. *
  198. *
  199. * Description:
  200. *
  201. *
  202. *****************************************************************************/
  203. WmiMultiReaderMultiWriter :: WmiMultiReaderMultiWriter (
  204. const LONG &a_ReaderSize ,
  205. const LONG &a_WriterSize
  206. ) : m_ReaderSize ( a_ReaderSize ) ,
  207. m_ReaderSemaphore ( NULL ) ,
  208. m_WriterSize ( a_WriterSize ) ,
  209. m_WriterSemaphore ( NULL ) ,
  210. m_InitializationStatusCode ( e_StatusCode_Success )
  211. {
  212. if ( m_InitializationStatusCode == e_StatusCode_Success )
  213. {
  214. m_ReaderSemaphore = CreateSemaphore ( NULL , m_ReaderSize , m_ReaderSize , NULL ) ;
  215. if ( ! m_ReaderSemaphore )
  216. {
  217. m_InitializationStatusCode = e_StatusCode_OutOfResources ;
  218. }
  219. }
  220. if ( m_InitializationStatusCode == e_StatusCode_Success )
  221. {
  222. m_WriterSemaphore = CreateSemaphore ( NULL , m_WriterSize , m_WriterSize , NULL ) ;
  223. if ( ! m_ReaderSemaphore )
  224. {
  225. m_InitializationStatusCode = e_StatusCode_OutOfResources ;
  226. }
  227. }
  228. }
  229. /******************************************************************************
  230. *
  231. * Name:
  232. *
  233. *
  234. * Description:
  235. *
  236. *
  237. *****************************************************************************/
  238. WmiMultiReaderMultiWriter :: ~WmiMultiReaderMultiWriter ()
  239. {
  240. if ( m_ReaderSemaphore )
  241. {
  242. CloseHandle ( m_ReaderSemaphore ) ;
  243. }
  244. if ( m_WriterSemaphore )
  245. {
  246. CloseHandle ( m_WriterSemaphore ) ;
  247. }
  248. }
  249. /******************************************************************************
  250. *
  251. * Name:
  252. *
  253. *
  254. * Description:
  255. *
  256. *
  257. *****************************************************************************/
  258. WmiStatusCode WmiMultiReaderMultiWriter :: Initialize ()
  259. {
  260. return m_InitializationStatusCode ;
  261. }
  262. /******************************************************************************
  263. *
  264. * Name:
  265. *
  266. *
  267. * Description:
  268. *
  269. *
  270. *****************************************************************************/
  271. WmiStatusCode WmiMultiReaderMultiWriter :: UnInitialize ()
  272. {
  273. WmiStatusCode t_StatusCode = e_StatusCode_Success ;
  274. return t_StatusCode ;
  275. }
  276. /******************************************************************************
  277. *
  278. * Name:
  279. *
  280. *
  281. * Description:
  282. *
  283. *
  284. *****************************************************************************/
  285. WmiStatusCode WmiMultiReaderMultiWriter :: EnterRead ( const LONG &a_Timeout )
  286. {
  287. if ( m_InitializationStatusCode == e_StatusCode_Success )
  288. {
  289. WmiStatusCode t_StatusCode = e_StatusCode_Success ;
  290. LONG t_Reason = WaitForSingleObject ( m_WriterSemaphore , INFINITE ) ;
  291. if ( t_Reason != WAIT_OBJECT_0 )
  292. {
  293. return e_StatusCode_Unknown ;
  294. }
  295. t_Reason = WaitForSingleObject ( m_ReaderSemaphore , INFINITE ) ;
  296. if ( t_Reason != WAIT_OBJECT_0 )
  297. {
  298. t_StatusCode = e_StatusCode_Unknown ;
  299. }
  300. LONG t_SemaphoreCount = 0 ;
  301. BOOL t_Status = ReleaseSemaphore ( m_WriterSemaphore , 1 , & t_SemaphoreCount ) ;
  302. if ( ! t_Status )
  303. {
  304. t_StatusCode = e_StatusCode_Unknown ;
  305. }
  306. return t_StatusCode ;
  307. }
  308. return e_StatusCode_NotInitialized ;
  309. }
  310. /******************************************************************************
  311. *
  312. * Name:
  313. *
  314. *
  315. * Description:
  316. *
  317. *
  318. *****************************************************************************/
  319. WmiStatusCode WmiMultiReaderMultiWriter :: EnterWrite ( const LONG &a_Timeout )
  320. {
  321. if ( m_InitializationStatusCode == e_StatusCode_Success )
  322. {
  323. WmiStatusCode t_StatusCode = e_StatusCode_Success ;
  324. LONG t_Reason = WaitForSingleObject ( m_WriterSemaphore , INFINITE ) ;
  325. if ( t_Reason != WAIT_OBJECT_0 )
  326. {
  327. return e_StatusCode_Unknown ;
  328. }
  329. bool t_Waiting = true ;
  330. while ( t_Waiting )
  331. {
  332. LONG t_Reason = WaitForSingleObject ( m_ReaderSemaphore , INFINITE ) ;
  333. if ( t_Reason != WAIT_OBJECT_0 )
  334. {
  335. LONG t_SemaphoreCount = 0 ;
  336. BOOL t_Status = ReleaseSemaphore ( m_WriterSemaphore , 1 , & t_SemaphoreCount ) ;
  337. if ( ! t_Status )
  338. {
  339. t_StatusCode = e_StatusCode_Unknown ;
  340. }
  341. return e_StatusCode_Unknown ;
  342. }
  343. LONG t_SemaphoreCount = 0 ;
  344. BOOL t_Status = ReleaseSemaphore ( m_ReaderSemaphore , 1 , & t_SemaphoreCount ) ;
  345. if ( t_Status )
  346. {
  347. if ( t_SemaphoreCount == m_ReaderSize - 1 )
  348. {
  349. t_Waiting = false ;
  350. }
  351. else
  352. {
  353. SwitchToThread () ;
  354. }
  355. }
  356. else
  357. {
  358. LONG t_SemaphoreCount = 0 ;
  359. BOOL t_Status = ReleaseSemaphore ( m_WriterSemaphore , 1 , & t_SemaphoreCount ) ;
  360. if ( ! t_Status )
  361. {
  362. t_StatusCode = e_StatusCode_Unknown ;
  363. }
  364. return e_StatusCode_Unknown ;
  365. }
  366. }
  367. return t_StatusCode ;
  368. }
  369. return e_StatusCode_NotInitialized ;
  370. }
  371. /******************************************************************************
  372. *
  373. * Name:
  374. *
  375. *
  376. * Description:
  377. *
  378. *
  379. *****************************************************************************/
  380. WmiStatusCode WmiMultiReaderMultiWriter :: LeaveRead ()
  381. {
  382. LONG t_SemaphoreCount = 0 ;
  383. BOOL t_Status = ReleaseSemaphore ( m_ReaderSemaphore , 1 , & t_SemaphoreCount ) ;
  384. if ( t_Status )
  385. {
  386. return e_StatusCode_Success ;
  387. }
  388. return e_StatusCode_Unknown ;
  389. }
  390. /******************************************************************************
  391. *
  392. * Name:
  393. *
  394. *
  395. * Description:
  396. *
  397. *
  398. *****************************************************************************/
  399. WmiStatusCode WmiMultiReaderMultiWriter :: LeaveWrite ()
  400. {
  401. LONG t_SemaphoreCount = 0 ;
  402. BOOL t_Status = ReleaseSemaphore ( m_WriterSemaphore , 1 , & t_SemaphoreCount ) ;
  403. if ( t_Status )
  404. {
  405. return e_StatusCode_Success ;
  406. }
  407. return e_StatusCode_Unknown ;
  408. }
  409. #endif __READERWRITER_CPP