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"); } }