/// <summary> /// Implements the ResourceLock's DoneWriting behavior. /// </summary> protected override void OnLeave(Boolean exclusive) { // Pre-condition: Lock's state must be Owned // Post-condition: Lock's state must become Free (the lock is never passed) // Phase 1: Free the lock Int32 ls = InterlockedEx.And(ref m_LockState, ~c_lsOwned); if (ls == c_lsOwned) { StressPause(); // If no waiters, nothing to do, we can just return } else { // Phase 2: Possibly wake waiters // If lock is free, try to subtract 1 from the number of waiters ls &= ~c_lsOwned; if (IfThen(ref m_LockState, ls, ls - c_1Waiter)) { StressPause(); // We sucessfully subtracted 1, wake 1 waiter m_WaiterLock.Release(1); StressPause(); } else { // Lock's state changed by other thread, other thread will deal with it StressPause(); } } }
/// <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(); } }
/// <summary> /// Resets the event. /// </summary> public void Reset() { InterlockedEx.And(ref _value, ~EventSet); }
public static AtomicValue<T> operator &(AtomicValue<T> lhs, int rhs) { InterlockedEx.And (ref lhs.m_value, -rhs); return lhs; }