Ejemplo n.º 1
0
 /// <summary>
 /// Constructs a SyncGate object
 /// </summary>
 /// <param name="blockReadersUntilFirstWriteCompletes">Pass true to have readers block until the first writer has created the data that is being protected by the ReaderWriterGate.</param>
 public ChoSyncGate(bool blockReadersUntilFirstWriteCompletes)
 {
     this._syncLock       = new object();
     this._qWriteRequests = new Queue <SyncGateAsyncResult>();
     this._qReadRequests  = new Queue <SyncGateAsyncResult>();
     this._state          = blockReadersUntilFirstWriteCompletes ? SyncGateStates.ReservedForWriter : SyncGateStates.Free;
 }
Ejemplo n.º 2
0
        /// <summary>
        /// Call this method after accessing the resource to notify the SyncGate that it can grant access to other code.
        /// </summary>
        /// <param name="result">The IAsyncResult object given to the callback method when access was granted.</param>
        public void EndRegion(IAsyncResult result)
        {
            ChoGuard.ArgumentNotNull(result, "result");

            SyncGateAsyncResult sgar = (SyncGateAsyncResult)result;

            sgar.EndInvoke();
            lock (_syncLock)
            {
                if ((sgar.Mode != SyncGateMode.Shared) || (--this._numReaders <= 0))
                {
                    if (_qWriteRequests.Count > 0)
                    {
                        _state = SyncGateStates.OwnedByWriter;
                        QueueCallback(_qWriteRequests.Dequeue());
                    }
                    else if (_qReadRequests.Count > 0)
                    {
                        _state      = SyncGateStates.OwnedByReaders;
                        _numReaders = _qReadRequests.Count;
                        while (_qReadRequests.Count > 0)
                        {
                            QueueCallback(_qReadRequests.Dequeue());
                        }
                    }
                    else
                    {
                        _state = SyncGateStates.Free;
                    }
                }
            }
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Call this method after accessing the resource to notify the SyncGate that it can grant access to other code.
        /// </summary>
        /// <param name="result">The IAsyncResult object given to the callback method when access was granted.</param>
        public void EndRegion(IAsyncResult result)
        {
            if (result == null)
            {
                throw new ArgumentNullException("result");
            }
            SyncGateAsyncResult sgar = (SyncGateAsyncResult)result;

            sgar.EndInvoke();

            Monitor.Enter(m_syncLock);
            if (sgar.Mode == SyncGateMode.Shared)
            {
                // Subtract a reader and return (without changing the gate's state)
                // if this is not the last reader
                if (--m_numReaders > 0)
                {
                    Monitor.Exit(m_syncLock);
                    return;
                }

                // This was the last reader, wake up any queued requests
            }

            Contract.Assume(m_qReadRequests != null);
            Contract.Assume(m_qWriteRequests != null);

            // Wake-up any queued requests
            if (m_qWriteRequests.Count > 0)
            {
                // A writer is queued, invoke it
                m_state = SyncGateStates.OwnedByWriter;
                QueueCallback(m_qWriteRequests.Dequeue());
            }
            else if (m_qReadRequests.Count > 0)
            {
                // Reading requests are queued, invoke all of them
                m_state      = SyncGateStates.OwnedByReaders;
                m_numReaders = m_qReadRequests.Count;
                while (m_qReadRequests.Count > 0)
                {
                    // The 1st reader can run on this thread; the others will be on thread pool threads
                    QueueCallback(m_qReadRequests.Dequeue());
                }
            }
            else
            {
                // No requests are queued, free the gate
                m_state = SyncGateStates.Free;
            }
            Monitor.Exit(m_syncLock);
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Allows the caller to notify the SyncGate that it wants exclusive or shared access to a resource.
        /// </summary>
        /// <param name="mode">Indicates if exclusive or shared access is desired.</param>
        /// <param name="asyncCallback">The callback method to invoke once access can be granted.</param>
        /// <param name="asyncState">Additional state to pass to the callback method.</param>
        public void BeginRegion(SyncGateMode mode, ChoAsyncCallback asyncCallback, object asyncState)
        {
            ChoGuard.ArgumentNotNull(asyncCallback, "asyncCallback");

            SyncGateAsyncResult ar = new SyncGateAsyncResult(mode, asyncCallback, asyncState);

            lock (_syncLock)
            {
                switch (mode)
                {
                case SyncGateMode.Exclusive:
                    switch (_state)
                    {
                    case SyncGateStates.OwnedByReaders:
                    case SyncGateStates.OwnedByReadersAndWriterPending:
                        _state = SyncGateStates.OwnedByReadersAndWriterPending;
                        _qWriteRequests.Enqueue(ar);
                        break;

                    case SyncGateStates.OwnedByWriter:
                        _qWriteRequests.Enqueue(ar);
                        break;
                    }
                    break;

                case SyncGateMode.Shared:
                    switch (_state)
                    {
                    case SyncGateStates.Free:
                    case SyncGateStates.OwnedByReaders:
                        _state = SyncGateStates.OwnedByReaders;
                        _numReaders++;
                        QueueCallback(ar);
                        break;

                    case SyncGateStates.OwnedByReadersAndWriterPending:
                    case SyncGateStates.OwnedByWriter:
                    case SyncGateStates.ReservedForWriter:
                        _qReadRequests.Enqueue(ar);
                        break;
                    }
                    break;
                }
            }
        }
Ejemplo n.º 5
0
      /// <summary>
      /// Allows the caller to notify the SyncGate that it wants exclusive or shared access to a resource. 
      /// </summary>
      /// <param name="mode">Indicates if exclusive or shared access is desired.</param>
      /// <param name="asyncCallback">The callback method to invoke once access can be granted.</param>
      /// <param name="asyncState">Additional state to pass to the callback method.</param>
      public void BeginRegion(SyncGateMode mode, AsyncCallback asyncCallback, Object asyncState) {
         Contract.Assume(m_qReadRequests != null);
         Contract.Assume(m_qWriteRequests != null);
         // This method supports the method callback version of the IAsyncResult APM only; therefore,
         // a callback method must always be specified and this is also why the method returns void 
         // instead of returning an IAsyncResult
         if (asyncCallback == null) throw new ArgumentNullException("asyncCallback");
         SyncGateAsyncResult ar = new SyncGateAsyncResult(mode, asyncCallback, asyncState);
         Boolean goodToGo = false;
         Monitor.Enter(m_syncLock);
         switch (mode) {
            case SyncGateMode.Exclusive:
               switch (m_state) {
                  case SyncGateStates.Free:             // If Free  | RFW -> OBW, invoke, return
                  case SyncGateStates.ReservedForWriter:
                     m_state = SyncGateStates.OwnedByWriter;
                     goodToGo = true;  // QueueCallback(ar);
                     break;

                  case SyncGateStates.OwnedByReaders:   // If OBR | OBRAWP -> OBRAWP, queue, return
                  case SyncGateStates.OwnedByReadersAndWriterPending:
                     m_state = SyncGateStates.OwnedByReadersAndWriterPending;
                     m_qWriteRequests.Enqueue(ar);
                     break;

                  case SyncGateStates.OwnedByWriter:   // If OBW, queue, return
                     m_qWriteRequests.Enqueue(ar);
                     break;
               }
               break;

            case SyncGateMode.Shared:
               switch (m_state) {
                  case SyncGateStates.Free:   // If Free | OBR -> OBR, NR++, invoke, return
                  case SyncGateStates.OwnedByReaders:
                     m_state = SyncGateStates.OwnedByReaders;
                     m_numReaders++;
                     goodToGo = true; // QueueCallback(ar);
                     break;

                  case SyncGateStates.OwnedByWriter:   // If OBW | OBRAWP | RFW, queue, return
                  case SyncGateStates.OwnedByReadersAndWriterPending:
                  case SyncGateStates.ReservedForWriter:
                     m_qReadRequests.Enqueue(ar);
                     break;
               }
               break;
         }
         Monitor.Exit(m_syncLock);
         if (goodToGo) ar.SetAsCompleted(null, true);
      }
Ejemplo n.º 6
0
 public SyncGate(Boolean blockReadersUntilFirstWriteCompletes) {
    m_state = blockReadersUntilFirstWriteCompletes ? SyncGateStates.ReservedForWriter : SyncGateStates.Free;
 }
Ejemplo n.º 7
0
      /// <summary>
      /// Call this method after accessing the resource to notify the SyncGate that it can grant access to other code.
      /// </summary>
      /// <param name="result">The IAsyncResult object given to the callback method when access was granted.</param>
      public void EndRegion(IAsyncResult result) {
         if (result == null) throw new ArgumentNullException("result");
         SyncGateAsyncResult sgar = (SyncGateAsyncResult)result;
         sgar.EndInvoke();

         Monitor.Enter(m_syncLock);
         if (sgar.Mode == SyncGateMode.Shared) {
            // Subtract a reader and return (without changing the gate's state) 
            // if this is not the last reader
            if (--m_numReaders > 0) {
               Monitor.Exit(m_syncLock);
               return;
            }

            // This was the last reader, wake up any queued requests
         }

         Contract.Assume(m_qReadRequests != null);
         Contract.Assume(m_qWriteRequests != null);

         // Wake-up any queued requests
         if (m_qWriteRequests.Count > 0) {
            // A writer is queued, invoke it
            m_state = SyncGateStates.OwnedByWriter;
            QueueCallback(m_qWriteRequests.Dequeue());
         } else if (m_qReadRequests.Count > 0) {
            // Reading requests are queued, invoke all of them
            m_state = SyncGateStates.OwnedByReaders;
            m_numReaders = m_qReadRequests.Count;
            while (m_qReadRequests.Count > 0) {
               // The 1st reader can run on this thread; the others will be on thread pool threads
               QueueCallback(m_qReadRequests.Dequeue());
            }
         } else {
            // No requests are queued, free the gate
            m_state = SyncGateStates.Free;
         }
         Monitor.Exit(m_syncLock);
      }
Ejemplo n.º 8
0
 public SyncGate(Boolean blockReadersUntilFirstWriteCompletes)
 {
     m_state = blockReadersUntilFirstWriteCompletes ? SyncGateStates.ReservedForWriter : SyncGateStates.Free;
 }
Ejemplo n.º 9
0
        /// <summary>
        /// Allows the caller to notify the SyncGate that it wants exclusive or shared access to a resource.
        /// </summary>
        /// <param name="mode">Indicates if exclusive or shared access is desired.</param>
        /// <param name="asyncCallback">The callback method to invoke once access can be granted.</param>
        /// <param name="asyncState">Additional state to pass to the callback method.</param>
        public void BeginRegion(SyncGateMode mode, AsyncCallback asyncCallback, Object asyncState)
        {
            Contract.Assume(m_qReadRequests != null);
            Contract.Assume(m_qWriteRequests != null);
            // This method supports the method callback version of the IAsyncResult APM only; therefore,
            // a callback method must always be specified and this is also why the method returns void
            // instead of returning an IAsyncResult
            if (asyncCallback == null)
            {
                throw new ArgumentNullException("asyncCallback");
            }
            SyncGateAsyncResult ar       = new SyncGateAsyncResult(mode, asyncCallback, asyncState);
            Boolean             goodToGo = false;

            Monitor.Enter(m_syncLock);
            switch (mode)
            {
            case SyncGateMode.Exclusive:
                switch (m_state)
                {
                case SyncGateStates.Free:               // If Free  | RFW -> OBW, invoke, return
                case SyncGateStates.ReservedForWriter:
                    m_state  = SyncGateStates.OwnedByWriter;
                    goodToGo = true;   // QueueCallback(ar);
                    break;

                case SyncGateStates.OwnedByReaders:     // If OBR | OBRAWP -> OBRAWP, queue, return
                case SyncGateStates.OwnedByReadersAndWriterPending:
                    m_state = SyncGateStates.OwnedByReadersAndWriterPending;
                    m_qWriteRequests.Enqueue(ar);
                    break;

                case SyncGateStates.OwnedByWriter:     // If OBW, queue, return
                    m_qWriteRequests.Enqueue(ar);
                    break;
                }
                break;

            case SyncGateMode.Shared:
                switch (m_state)
                {
                case SyncGateStates.Free:     // If Free | OBR -> OBR, NR++, invoke, return
                case SyncGateStates.OwnedByReaders:
                    m_state = SyncGateStates.OwnedByReaders;
                    m_numReaders++;
                    goodToGo = true;  // QueueCallback(ar);
                    break;

                case SyncGateStates.OwnedByWriter:     // If OBW | OBRAWP | RFW, queue, return
                case SyncGateStates.OwnedByReadersAndWriterPending:
                case SyncGateStates.ReservedForWriter:
                    m_qReadRequests.Enqueue(ar);
                    break;
                }
                break;
            }
            Monitor.Exit(m_syncLock);
            if (goodToGo)
            {
                ar.SetAsCompleted(null, true);
            }
        }