public void SimpleTest(ReaderWriterGate gate)
    {
        Byte stop = 0;
          // Start a thread that posts periodic read requests
          ThreadPool.QueueUserWorkItem(delegate {
         for (Int32 x = 0; Thread.VolatileRead(ref stop) == 0; x++) {
            gate.BeginRead(ReadResourceCallback, x, delegate(IAsyncResult result) { gate.EndRead(result); }, null);
            Thread.Sleep(500);
         }
          });

          // While Read requests are being posted in the background, periodically post some write requests
          Int32 numWritersToQueue = 1;
          Thread.Sleep(2000);
          for (Int32 x = 0; numWritersToQueue > 0; x++) {
         for (int i = 0; i < numWritersToQueue; i++) {
            gate.BeginWrite(WriteResourceCallbackUI, x, delegate(IAsyncResult result) { gate.EndWrite(result); }, null);
         }
         Console.WriteLine("Writer request");
         if (!Int32.TryParse(Console.ReadLine(), out numWritersToQueue))
            numWritersToQueue = 1;
          }
          Thread.VolatileWrite(ref stop, 1);
          Console.WriteLine("Done queuing, hit <Enter> to exit test");
          Console.ReadLine();
    }
    public static void Main()
    {
        #if false
        // Functional test
        {
            FuncTest_ReaderWriterGate ftrwg = new FuncTest_ReaderWriterGate();
            ReaderWriterGate gate = new ReaderWriterGate(false);
            ftrwg.SimpleTest(gate);
            ftrwg.TestAll(gate);
        }
        #endif
        // Return value test
        {
            ReaderWriterGate gate = new ReaderWriterGate(false);
            gate.BeginRead(releaser => {
                releaser.ResultValue = "Releasing";
                releaser.Release(false);
                Thread.Sleep(5000);
                Object o = null;
                o.GetType();
                return "Returning";

            }, ar => Console.WriteLine(gate.EndRead(ar)));
            Console.ReadLine();
        }
        // Performance test
        {
            const Int32 c_PerfIterations = 10 * 1000 * 1000;

            ReaderWriterGate gate = new ReaderWriterGate();
            PerformanceTest pt = new PerformanceTest(c_PerfIterations);
            foreach (Boolean write in new Boolean[] { false, true }) {
                Console.WriteLine("{0} {1} {2}",
                   pt.Test(write, gate), write ? "writing" : "reading", gate.ToString());
            }
        }
    }
    public TimeSpan Test(Boolean exclusive, ReaderWriterGate gate)
    {
        ReaderWriterGateCallback gateCallback = delegate(ReaderWriterGateReleaser releaser) { return null; };
          gateCallback(null);
          gate.BeginRead(gateCallback, delegate(IAsyncResult result) { gate.EndRead(result); });
          gate.BeginWrite(gateCallback, delegate(IAsyncResult result) { gate.EndWrite(result); });
          GC.Collect();
          GC.WaitForPendingFinalizers();
          GC.Collect();

          Stopwatch stopWatch = Stopwatch.StartNew();
          for (Int32 x = 0; x < m_iterations; x++) {
         if (!exclusive) gate.BeginRead(gateCallback, delegate(IAsyncResult result) { gate.EndRead(result); });
         else gate.BeginWrite(gateCallback, delegate(IAsyncResult result) { gate.EndWrite(result); });
          }
          return stopWatch.Elapsed;
    }
 public void TestAll(ReaderWriterGate gate)
 {
     Test(gate, 0, 0, 1, 0); // Uncontended Read test
       Test(gate, 0, 0, 0, 1); // Uncontended Write test
       Test(gate, 0, 1, 1, 0); // A writer writing and a reader queued up
       Test(gate, 0, 1, 5, 0); // A writer writing and several readers queued up
       Test(gate, 0, 1, 0, 5); // A writer writing and several writers queued up
       Test(gate, 0, 1, 5, 5); // A writer writing and several readers & writers queued up
       Test(gate, 1, 0, 1, 5); // A reader reading and a writer queued up
       Test(gate, 5, 1, 0, 1); // Several readers reading and a writer queued up
 }
    public void Test(ReaderWriterGate gate, Int32 numInitialReaders, Int32 numInitialWriters,
        Int32 numAdditionalReaders, Int32 numAdditionalWriters)
    {
        Console.WriteLine();
          Console.WriteLine("FuncTest_Deadlock_Test: WR={0}, WW={1}, QR={2}, QW={3}",
         numInitialReaders, numInitialWriters, numAdditionalReaders, numAdditionalWriters);

          Thread.VolatileWrite(ref m_NumReaders, 0);
          Thread.VolatileWrite(ref m_NumWriters, 0);
          Thread.VolatileWrite(ref m_NumConcurrentWriters, 0);

          using (m_are = new AutoResetEvent(false)) {
         // Queue up a bunch of read requests
         for (Int32 i = 0; i < numInitialReaders; i++) {
            ThreadPool.QueueUserWorkItem(
               delegate { gate.BeginRead(ReadAndWait, delegate(IAsyncResult result) { gate.EndRead(result); }); });
         }

         // Make sure the readers have started to be processed
         Thread.Sleep(100);

         // Queue up a bunch of write requests (these should wait)
         for (Int32 i = 0; i < numInitialWriters; i++) {
            ThreadPool.QueueUserWorkItem(
               delegate { gate.BeginWrite(WriteAndWait, delegate(IAsyncResult result) { gate.EndWrite(result); }); });
         }

         // Make sure the writers have been queued
         Thread.Sleep(100);

         // Since readers own the gate with writers pending, all of these additional readers should queue
         for (int i = 0; i < numAdditionalReaders; i++) {
            gate.BeginRead(ReadResourceCallback, i, delegate(IAsyncResult result) { gate.EndRead(result); }, null);
         }

         // Since writers own the gate, these writers should be processed before the additional readers
         for (int i = 0; i < numAdditionalWriters; i++) {
            gate.BeginWrite(WriteResourceCallback, i, delegate(IAsyncResult result) { gate.EndWrite(result); }, null);
         }

         // Now, release the waiting reader threads
         for (int i = 0; i < numInitialReaders + numInitialWriters; i++) {
            m_are.Set();
            Thread.Sleep(50);
         }

         while (Thread.VolatileRead(ref m_NumReaders) != numInitialReaders + numAdditionalReaders)
            Thread.Sleep(1);
         Console.WriteLine("All readers done");

         while (Thread.VolatileRead(ref m_NumWriters) != numInitialWriters + numAdditionalWriters)
            Thread.Sleep(1);
         Console.WriteLine("All readers & writers done");
          }
    }