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.

392 lines
12 KiB

  1. #ifndef _TICKET_HPP_
  2. #define _TICKET_HPP_
  3. // Ruler
  4. // 1 2 3 4 5 6 7 8
  5. //345678901234567890123456789012345678901234567890123456789012345678901234567890
  6. /********************************************************************/
  7. /* */
  8. /* The standard layout. */
  9. /* */
  10. /* The standard layout for 'hpp' files for this code is as */
  11. /* follows: */
  12. /* */
  13. /* 1. Include files. */
  14. /* 2. Constants exported from the class. */
  15. /* 3. Data structures exported from the class. */
  16. /* 4. Forward references to other data structures. */
  17. /* 5. Class specifications (including inline functions). */
  18. /* 6. Additional large inline functions. */
  19. /* */
  20. /* Any portion that is not required is simply omitted. */
  21. /* */
  22. /********************************************************************/
  23. #include "Global.hpp"
  24. #include "Lock.hpp"
  25. #include "Vector.hpp"
  26. /********************************************************************/
  27. /* */
  28. /* Constants exported from the class. */
  29. /* */
  30. /* The ticket constants specify the initial size of the */
  31. /* ticket array. */
  32. /* */
  33. /********************************************************************/
  34. CONST SBIT32 TicketSize = 128;
  35. /********************************************************************/
  36. /* */
  37. /* Ticketing to maintain ordering. */
  38. /* */
  39. /* This class provides general purpose event ordering so */
  40. /* that events can arrive in any order but processed in */
  41. /* sequential order with a minimal amount of fuss. */
  42. /* */
  43. /********************************************************************/
  44. template <class TYPE,class LOCK=NO_LOCK> class TICKET : public LOCK
  45. {
  46. //
  47. // Private data structure.
  48. //
  49. typedef struct
  50. {
  51. BOOLEAN Available;
  52. TYPE Data;
  53. }
  54. STUB;
  55. //
  56. // Private data.
  57. //
  58. SBIT32 MaxSize;
  59. SBIT32 Back;
  60. SBIT32 Front;
  61. SBIT32 Base;
  62. SBIT32 Stride;
  63. VECTOR<STUB> Ticket;
  64. public:
  65. //
  66. // Public functions.
  67. //
  68. TICKET
  69. (
  70. SBIT32 Start = 0,
  71. SBIT32 NewMaxSize = TicketSize,
  72. SBIT32 NewStride = 1
  73. );
  74. BOOLEAN CollectTicket( TYPE *Data,SBIT32 *Ticket );
  75. SBIT32 NumberOfTickets( VOID );
  76. SBIT32 NewTicket( VOID );
  77. BOOLEAN PunchTicket( CONST TYPE & Data,SBIT32 Ticket );
  78. ~TICKET( VOID );
  79. //
  80. // Public inline functions.
  81. //
  82. SBIT32 LowestOutstandingTicket( VOID )
  83. { return Base; }
  84. private:
  85. //
  86. // Disabled operations.
  87. //
  88. TICKET( CONST TICKET & Copy );
  89. VOID operator=( CONST TICKET & Copy );
  90. };
  91. /********************************************************************/
  92. /* */
  93. /* Class constructor. */
  94. /* */
  95. /* Create a new ticket queue and prepare it for use. This call */
  96. /* is not thread safe and should only be made in a single thread */
  97. /* environment. */
  98. /* */
  99. /********************************************************************/
  100. template <class TYPE,class LOCK> TICKET<TYPE,LOCK>::TICKET
  101. (
  102. SBIT32 Start,
  103. SBIT32 NewMaxSize,
  104. SBIT32 NewStride
  105. ) :
  106. //
  107. // Call the constructors for the contained classes.
  108. //
  109. Queue( NewMaxSize,1,CacheLineSize )
  110. {
  111. #ifdef DEBUGGING
  112. if ( NewMaxSize > 0 )
  113. {
  114. #endif
  115. //
  116. // Setup the control information.
  117. //
  118. MaxSize = NewMaxSize;
  119. //
  120. // Setup the queue so it is empty.
  121. //
  122. Back = 0;
  123. Front = 0;
  124. //
  125. // Set the initial ticket number.
  126. //
  127. Base = Start;
  128. Stride = NewStride;
  129. #ifdef DEBUGGING
  130. }
  131. else
  132. { Failure( "MaxSize in constructor for TICKET" ); }
  133. #endif
  134. }
  135. /********************************************************************/
  136. /* */
  137. /* Issue a new ticket. */
  138. /* */
  139. /* We issue a new ticket and allocate a place in the line. We */
  140. /* also we reserve space in the ticket queue. */
  141. /* */
  142. /********************************************************************/
  143. template <class TYPE,class LOCK> SBIT32 TICKET<TYPE,LOCK>::NewTicket( VOID )
  144. {
  145. REGISTER SBIT32 Result;
  146. //
  147. // Claim an exclisive lock (if enabled).
  148. //
  149. ClaimExclusiveLock();
  150. //
  151. // Add element to the queue. If necessary wrap round
  152. // to the front of the array.
  153. //
  154. Ticket[ Back ++ ].Available = False;
  155. if ( Back >= MaxSize )
  156. { Back = 0; }
  157. //
  158. // Compute the ticket number.
  159. //
  160. Result = (Base + (NumberOfTickets() * Stride));
  161. //
  162. // Verify that the queue is not full. If it is full then
  163. // double its size and copy wrapped data to the correct
  164. // position in the new array.
  165. //
  166. if ( Front == Back )
  167. {
  168. REGISTER SBIT32 Count;
  169. REGISTER SBIT32 NewSize = (MaxSize * ExpandStore);
  170. //
  171. // Expand the queue (it will be at least doubled).
  172. //
  173. Ticket.Resize( NewSize );
  174. //
  175. // Copy the tail end of the queue to the correct
  176. // place in the expanded queue.
  177. //
  178. for ( Count = 0;Count < Back;Count ++ )
  179. { Ticket[ (MaxSize + Count) ] = Ticket[ Count ]; }
  180. //
  181. // Update the control information.
  182. //
  183. Back += MaxSize;
  184. MaxSize = NewSize;
  185. }
  186. //
  187. // Release any lock we claimed earlier.
  188. //
  189. ReleaseExclusiveLock();
  190. return Result;
  191. }
  192. /********************************************************************/
  193. /* */
  194. /* Punch a ticket and store any associated data. */
  195. /* */
  196. /* We punch a ticket so it can be collected and store any */
  197. /* related data. */
  198. /* */
  199. /********************************************************************/
  200. template <class TYPE,class LOCK> BOOLEAN TICKET<TYPE,LOCK>::PunchTicket
  201. (
  202. CONST TYPE & Data,
  203. SBIT32 Ticket
  204. )
  205. {
  206. REGISTER BOOLEAN Result;
  207. REGISTER SBIT32 TicketOffset;
  208. //
  209. // Claim an exclusive lock (if enabled).
  210. //
  211. ClaimExclusiveLock();
  212. //
  213. // Compute the offset in the ticket array.
  214. //
  215. TicketOffset = ((Ticket - Base) / Stride);
  216. //
  217. // Ensure the ticket refers to and active ticket
  218. // that has not already been recycled.
  219. //
  220. if ( (TicketOffset >= 0) && (TicketOffset < NumberOfTickets()) )
  221. {
  222. REGISTER STUB *Stub = & Ticket[ TicketOffset ];
  223. //
  224. // Ensure the ticket has not already been
  225. // punched.
  226. //
  227. if ( ! Stub -> Available )
  228. {
  229. Stub -> Available = True;
  230. Stub -> Data = Data;
  231. Result = True;
  232. }
  233. else
  234. { Result = False; }
  235. }
  236. else
  237. { Result = False; }
  238. //
  239. // Release any lock we claimed earlier.
  240. //
  241. ReleaseExclusiveLock();
  242. return Result;
  243. }
  244. /********************************************************************/
  245. /* */
  246. /* Collect the lowest numbered ticket. */
  247. /* */
  248. /* We try to collect the lowest numbered ticket that has been */
  249. /* issued. If it is has been punched and is available we */
  250. /* recycle it after returning any associated data to the caller. */
  251. /* */
  252. /********************************************************************/
  253. template <class TYPE,class LOCK> BOOLEAN TICKET<TYPE,LOCK>::CollectTicket
  254. (
  255. TYPE *Data,
  256. SBIT32 *Ticket
  257. )
  258. {
  259. REGISTER BOOLEAN Result;
  260. //
  261. // Claim an exclusive lock (if enabled).
  262. //
  263. ClaimExclusiveLock();
  264. //
  265. // We make sure the ticket queue is not empty.
  266. //
  267. if ( Front != Back )
  268. {
  269. REGISTER STUB *Stub = & Ticket[ Front ];
  270. //
  271. // We can collect the first ticket in the
  272. // ticket queue if it has been punched.
  273. //
  274. if ( Stub -> Available )
  275. {
  276. //
  277. // We have an ticket ready so return it to
  278. // the caller. If we walk off the end of
  279. // the ticket queue then wrap to the other
  280. // end.
  281. //
  282. (*Data) = Stub -> Data;
  283. (*Ticket) = (Base += Stride);
  284. if ( (++ Front) >= MaxSize )
  285. { Front = 0; }
  286. Result = True;
  287. }
  288. else
  289. { Result = False; }
  290. }
  291. else
  292. { Result = False; }
  293. //
  294. // Release any lock we claimed earlier.
  295. //
  296. ReleaseExclusiveLock();
  297. return Result;
  298. }
  299. /********************************************************************/
  300. /* */
  301. /* Calculate the size of the reorder queue. */
  302. /* */
  303. /* Calculate the size of the queue and return it to the caller. */
  304. /* */
  305. /********************************************************************/
  306. template <class TYPE,class LOCK> SBIT32 TICKET<TYPE,LOCK>::NumberOfTickets( VOID )
  307. {
  308. REGISTER SBIT32 Size;
  309. //
  310. // Compute the size of the reorder queue.
  311. //
  312. Size = (Back - Front);
  313. //
  314. // If the queue has wrapped then adjust as needed.
  315. //
  316. if ( Size < 0 )
  317. { Size += MaxSize; }
  318. return Size;
  319. }
  320. /********************************************************************/
  321. /* */
  322. /* Class destructor. */
  323. /* */
  324. /* Destory a queue. This call is not thread safe and should */
  325. /* only be made in a single thread environment. */
  326. /* */
  327. /********************************************************************/
  328. template <class TYPE,class LOCK> TICKET<TYPE,LOCK>::~TICKET( VOID )
  329. { /* void */ }
  330. #endif