コード例 #1
0
        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.");
                }
            }
        }
コード例 #2
0
 /// <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;
         }
     }
 }
コード例 #3
0
        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();
        }
コード例 #4
0
        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;
            }
        }
コード例 #5
0
        /// <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();
            }
        }