private void EventConsumer() { while (!Disposed) { CounterQueueEvent evt = null; lock (_lock) { if (_events.Count > 0) { evt = _events.Dequeue(); } } if (evt == null) { _queuedEvent.WaitOne(); // No more events to go through, wait for more. } else { // Spin-wait rather than sleeping if there are any waiters, by passing null instead of the wake signal. evt.TryConsume(ref _accumulatedCounter, true, _waiterCount == 0 ? _wakeSignal : null); } if (_waiterCount > 0) { _eventConsumed.Set(); } } }
public void Dispose() { lock (_lock) { while (_events.Count > 0) { CounterQueueEvent evt = _events.Dequeue(); evt.Dispose(); } Disposed = true; } _queuedEvent.Set(); _consumerThread.Join(); foreach (BufferedQuery query in _queryPool) { query.Dispose(); } _queuedEvent.Dispose(); _wakeSignal.Dispose(); _eventConsumed.Dispose(); }
public CounterQueueEvent QueueReport(EventHandler <ulong> resultHandler, ulong lastDrawIndex) { CounterQueueEvent result; ulong draws = lastDrawIndex - _current.DrawIndex; lock (_lock) { // A query's result only matters if more than one draw was performed during it. // Otherwise, dummy it out and return 0 immediately. if (draws > 0) { _current.Complete(true); _events.Enqueue(_current); _current.OnResult += resultHandler; } else { _current.Complete(false); _current.Dispose(); resultHandler(_current, 0); } result = _current; _current = new CounterQueueEvent(this, GetTarget(Type), lastDrawIndex); } _queuedEvent.Set(); return(result); }
public CounterQueueEvent QueueReport(EventHandler <ulong> resultHandler, ulong lastDrawIndex, bool hostReserved) { CounterQueueEvent result; ulong draws = lastDrawIndex - _current.DrawIndex; lock (_lock) { // A query's result only matters if more than one draw was performed during it. // Otherwise, dummy it out and return 0 immediately. if (hostReserved) { // This counter event is guaranteed to be available for host conditional rendering. _current.ReserveForHostAccess(); } _current.Complete(draws > 0); _events.Enqueue(_current); _current.OnResult += resultHandler; result = _current; _current = new CounterQueueEvent(this, GetTarget(Type), lastDrawIndex); } _queuedEvent.Set(); return(result); }
public void FlushTo(CounterQueueEvent evt) { // Flush the counter queue on the main thread. Interlocked.Increment(ref _waiterCount); _wakeSignal.Set(); while (!evt.Disposed) { _eventConsumed.WaitOne(1); } Interlocked.Decrement(ref _waiterCount); }
internal CounterQueue(CounterType type) { Type = type; QueryTarget glType = GetTarget(Type); _queryPool = new Queue <BufferedQuery>(QueryPoolInitialSize); for (int i = 0; i < QueryPoolInitialSize; i++) { _queryPool.Enqueue(new BufferedQuery(glType)); } _current = new CounterQueueEvent(this, glType, 0); _consumerThread = new Thread(EventConsumer); _consumerThread.Start(); }
public CounterQueueEvent QueueReport(EventHandler <ulong> resultHandler) { CounterQueueEvent result; lock (_lock) { _current.Complete(); _events.Enqueue(_current); result = _current; result.OnResult += resultHandler; _current = new CounterQueueEvent(this, GetTarget(Type)); } _queuedEvent.Set(); return(result); }
public void FlushTo(CounterQueueEvent evt) { lock (_lock) { if (evt.Disposed) { return; } // Tell the queue to process all events up to this one. while (_events.Count > 0) { CounterQueueEvent flush = _events.Dequeue(); flush.TryConsume(ref _accumulatedCounter, true); if (flush == evt) { return; } } } }
public void Flush(bool blocking) { if (!blocking) { // Just wake the consumer thread - it will update the queries. _wakeSignal.Set(); return; } lock (_lock) { // Tell the queue to process all events. while (_events.Count > 0) { CounterQueueEvent flush = _events.Peek(); if (!flush.TryConsume(ref _accumulatedCounter, true)) { return; // If not blocking, then return when we encounter an event that is not ready yet. } _events.Dequeue(); } } }
private void EventConsumer() { while (!Disposed) { CounterQueueEvent evt = null; lock (_lock) { if (_events.Count > 0) { evt = _events.Dequeue(); } } if (evt == null) { _queuedEvent.WaitOne(); // No more events to go through, wait for more. } else { evt.TryConsume(ref _accumulatedCounter, true, _wakeSignal); } } }