public void Acquire() { // Fast path. if (Interlocked.CompareExchange(ref _value, 1, 0) == 0) { return; } // Slow path 1 - spin for a while. /* * if (SpinEnabled) * { * for (int i = 0; i < SpinCount; i++) * { * if (Interlocked.CompareExchange(ref _value, 1, 0) == 0) * return; * } * } */ // Slow path 2 - wait on the event. // Note: see FastEvent.cs for a more detailed explanation of this // technique. CEvent newEvent = Interlocked.CompareExchange(ref _event, null, null); if (newEvent == null) { newEvent = new CEvent(true, false); if (Interlocked.CompareExchange(ref _event, newEvent, null) != null) { newEvent.Close(); } } // Loop trying to acquire the lock. Note that after we // get woken up another thread might have acquired the lock, // and that's why we need a loop. while (true) { if (Interlocked.CompareExchange(ref _value, 1, 0) == 0) { break; } if (!_event.Wait(Timeout.Infinite)) { Break("Failed to wait indefinitely on an object."); } } }
/// <summary> /// Dereferences the event, closing it if necessary. /// </summary> private void DerefEvent() { if ((InterlockedEx.Add(ref _value, -EventRefCountIncrement) >> EventRefCountShift) == 0) { if (_event != null) { _event.Close(); _event = null; } } }
public override void Close() { #if USE_FAST_EVENT m_isClosed = true; #else CEvent oldGate = Interlocked.CompareExchange(ref m_gate, null, m_gate); if (oldGate != null) { oldGate.Close(); } #endif base.Close(); }
private void TestEventCmd(string parameters) { switch (parameters.ToUpper()) { case "SET": myEvent.Set(); break; case "RESET": myEvent.Reset(); break; case "CLOSE": myEvent.Close(); break; case "CREATE": killThreads(); myEvent = new CEvent(); createTestCEventThreads(); break; case "CREATE FALSE FALSE": killThreads(); myEvent = new CEvent(false, false); createTestCEventThreads(); break; case "CREATE FALSE TRUE": killThreads(); myEvent = new CEvent(false, true); createTestCEventThreads(); break; case "CREATE TRUE FALSE": killThreads(); myEvent = new CEvent(true, false); createTestCEventThreads(); break; case "CREATE TRUE TRUE": killThreads(); myEvent = new CEvent(true, true); createTestCEventThreads(); break; default: break; } }
/// <summary> /// Waits for the event to be set. /// </summary> /// <param name="millisecondsTimeout">The number of milliseconds to wait.</param> /// <returns>Whether the event was set before the timeout period elapsed.</returns> public bool Wait(int millisecondsTimeout) { // 1. [Optional] If Value = 1, Return. // 2. [Optional] If Timeout = 0 And Value = 0, Return. // 3. [Optional] Reference the Global Event. // 4. [Optional] If Global Event is present, skip Step 5. // 5. Create Event. // 6. Global Event = Event only if Global Event is not present. // 7. If Value = 1, Return (rather, go to Step 9). // 8. Wait for Global Event. // 9. [Optional] Dereference the Global Event. int result = _autoReset ? InterlockedEx.And(ref _value, ~EventSet) : _value; // Shortcut: return immediately if the event is set. if ((result & EventSet) != 0) { return(true); } // Shortcut: if the timeout is 0, return immediately if // the event isn't set. if (millisecondsTimeout == 0) { return(false); } // Prevent the event from being closed or invalidated. RefEvent(); // Shortcut: don't bother creating an event if we already have one. CEvent newEvent = _event; // If we don't have an event, create one and try to set it. if (newEvent == null) { // Create an event. We might not need it, though. newEvent = new CEvent(_autoReset, false); // Atomically use the event only if we don't already // have one. if (Interlocked.CompareExchange(ref _event, newEvent, null) != null) { // Someone else set the event before we did. newEvent.Close(); } } try { // Check the value to see if we are meant to wait. This step // is essential, because if someone set the event before we // created the event (previous step), we would be waiting // on an event no one knows about. if ((_value & EventSet) != 0) { return(true); } return(_event.Wait(millisecondsTimeout)); } finally { // We don't need the event anymore. DerefEvent(); } }