public void ConditionVariableTest2() { InitializeSRWLock(out var cond_rwlock); InitializeConditionVariable(out var start_condition); var wake_all = false; var cnt = 0; try { var ghThreads = new SafeHTHREAD[5]; for (int i = 0; i < ghThreads.Length; i++) { ghThreads[i] = CreateThread(null, 0, ThreadProc, default, 0, out _);
public void Dispose() { ChatEndpoint = null; RenderClient = null; CaptureClient = null; AudioClient = null; if (ChatThread is not null) { ChatThread.Dispose(); ChatThread = default; } if (ShutdownEvent is not null) { ShutdownEvent.Dispose(); ShutdownEvent = null; } if (AudioSamplesReadyEvent is not null) { AudioSamplesReadyEvent.Dispose(); AudioSamplesReadyEvent = null; } }
public void ConditionVariableTest() { const int BUFFER_SIZE = 10; const int PRODUCER_SLEEP_TIME_MS = 50; const int CONSUMER_SLEEP_TIME_MS = 200; var Buffer = new int[BUFFER_SIZE]; int LastItemProduced = 0; uint QueueSize = 0, QueueStartOffset = 0, TotalItemsProduced = 0, TotalItemsConsumed = 0; var StopRequested = false; var rand = new Random(); InitializeConditionVariable(out var BufferNotEmpty); InitializeConditionVariable(out var BufferNotFull); InitializeCriticalSection(out var BufferLock); using (SafeHTHREAD hProducer1 = CreateThread(null, 0, ProducerThreadProc, (IntPtr)1L, 0, out _), hConsumer1 = CreateThread(null, 0, ConsumerThreadProc, (IntPtr)1L, 0, out _), hConsumer2 = CreateThread(null, 0, ConsumerThreadProc, (IntPtr)2L, 0, out _)) { SleepEx(5000, false); EnterCriticalSection(ref BufferLock); StopRequested = true; LeaveCriticalSection(ref BufferLock); WakeAllConditionVariable(ref BufferNotFull); WakeAllConditionVariable(ref BufferNotEmpty); WaitForMultipleObjects(new[] { hProducer1, hConsumer1, hConsumer2 }, true, INFINITE); TestContext.WriteLine("TotalItemsProduced: {0}, TotalItemsConsumed: {1}", TotalItemsProduced, TotalItemsConsumed); } uint ProducerThreadProc(IntPtr p) { var ProducerId = p.ToInt64(); while (true) { // Produce a new item. Sleep((uint)rand.Next(PRODUCER_SLEEP_TIME_MS)); var Item = InterlockedIncrement(ref LastItemProduced); EnterCriticalSection(ref BufferLock); while (QueueSize == BUFFER_SIZE && !StopRequested) { // Buffer is full - sleep so consumers can get items. SleepConditionVariableCS(ref BufferNotFull, ref BufferLock, INFINITE); } if (StopRequested) { LeaveCriticalSection(ref BufferLock); break; } // Insert the item at the end of the queue and increment size. Buffer[(QueueStartOffset + QueueSize) % BUFFER_SIZE] = Item; QueueSize++; TotalItemsProduced++; System.Diagnostics.Debug.Write($"Producer {ProducerId}: item {Item}, queue size {QueueSize}\r\n"); LeaveCriticalSection(ref BufferLock); // If a consumer is waiting, wake it. WakeConditionVariable(ref BufferNotEmpty); } System.Diagnostics.Debug.Write($"Producer {ProducerId} exiting\r\n"); return(0); } uint ConsumerThreadProc(IntPtr p) { var ConsumerId = p.ToInt64(); while (true) { EnterCriticalSection(ref BufferLock); while (QueueSize == 0 && !StopRequested) { // Buffer is empty - sleep so producers can create items. SleepConditionVariableCS(ref BufferNotEmpty, ref BufferLock, INFINITE); } if (StopRequested && QueueSize == 0) { LeaveCriticalSection(ref BufferLock); break; } // Consume the first available item. var Item = Buffer[QueueStartOffset]; QueueSize--; QueueStartOffset++; TotalItemsConsumed++; if (QueueStartOffset == BUFFER_SIZE) { QueueStartOffset = 0; } System.Diagnostics.Debug.Write($"Consumer {ConsumerId}: item {Item}, queue size {QueueSize}\r\n"); LeaveCriticalSection(ref BufferLock); // If a producer is waiting, wake it. WakeConditionVariable(ref BufferNotFull); // Simulate processing of the item. Sleep((uint)rand.Next(CONSUMER_SLEEP_TIME_MS)); } System.Diagnostics.Debug.Write($"Consumer {ConsumerId} exiting\r\n"); return(0); } }