Пример #1
0
 /* apenas pode ser invocado pelas threads que tenham
  * adquirido o semáforo para escrita, liberta o acesso para
  * escrita e, atomicamente, adquire acesso para leitura.*/
 public void DowngradeWriter()
 {
     if (waitingReaders != null && waitingReaders.waiters > 0)
     {
         readers            += waitingReaders.waiters;
         waitingReaders.done = true;         // dar acesso aos leitores
         waitingReaders      = null;         // retirar os leitores de espera
         MonitorEx.PulseAll(myLock, myLock); // notificar todos os leitores
     }
     else
     {
         GrantAccessToOneWritter();
     }
 }
Пример #2
0
 // DownWrite adquirem a posse do semáforo para escrita
 public void DownWrite()
 {
     lock (myLock) {
         // nao existem leitores em espera e neinguem está a escrever e a fila de escritores está vazia,
         // o escritor tem acesso ao semáforo
         if (readers == 0 && !writing && waitingWriters.Count == 0)
         {
             writing = true;
             return;
         }
         // o escritor fica em espera
         LinkedListNode <bool> wrnode = waitingWriters.AddLast(false);
         do
         {
             try {
                 MonitorEx.Wait(myLock, wrnode);
             }
             catch (ThreadInterruptedException) {
                 // acesso foi garantido, o escritor retira-se
                 if (wrnode.Value)
                 {
                     Thread.CurrentThread.Interrupt();
                     return;
                 }
                 // o escritor é removido da espera
                 waitingWriters.Remove(wrnode);
                 // garantir o acesso dos leitores ao semáforo
                 if (!writing && waitingWriters.Count == 0 && waitingReaders != null)
                 {
                     if (waitingReaders != null && waitingReaders.waiters > 0)
                     {
                         readers            += waitingReaders.waiters;
                         waitingReaders.done = true;         // dar acesso aos leitores
                         waitingReaders      = null;         // retirar os leitores de espera
                         MonitorEx.PulseAll(myLock, myLock); // notificar todos os leitores
                     }
                 }
                 throw;
             }
         } while (!wrnode.Value);
     }
 }
Пример #3
0
        private readonly LinkedList <bool> waitingWriters = new LinkedList <bool>(); // escritores em espera (entra um de cada vez no semáforo)

        // DownRead adquirem a posse do semáforo para leitura
        public void DownRead()
        {
            lock (myLock) {
                // não existem escritores à espera e não há nenhum esritor a escrever,
                // o leitor ganha acesso independentemente dos outros leitores
                if (waitingWriters.Count == 0 && !writing)
                {
                    readers++;
                    return;
                }
                // o leitor fica em espera
                WaitingReaders rdnode;
                if ((rdnode = waitingReaders) == null)
                {
                    waitingReaders = rdnode = new WaitingReaders();
                }
                rdnode.waiters++;
                do
                {
                    try {
                        MonitorEx.Wait(myLock, myLock);
                    }
                    catch (ThreadInterruptedException) {
                        // acesso foi garantido, o leitor retira-se
                        if (rdnode.done)
                        {
                            Thread.CurrentThread.Interrupt();
                            return;
                        }
                        // o leitor é removido da espera
                        if (--rdnode.waiters == 0)
                        {
                            waitingReaders = null;
                        }
                        throw;
                    }
                } while (!rdnode.done);
            }
        }