예제 #1
0
 // throws ThreadInterruptedException
 public void DownWrite()
 {
     lock (lockObj)
     {
         //Se não houver leitores/escritores à espera e não houver nenhum escritor a escrever e leitores a ler
         if (rwq.Count == 0 && !isWriting && readersReading == 0)
         {
             //Um escritor a escrever
             isWriting    = true;
             writerInside = Thread.CurrentThread.ManagedThreadId;
             return;
         }
         //Adicionar um novo escritor à lista de espera
         LinkedListNode <Rw> wr = rwq.AddLast(new Rw(WRITER));
         do
         {
             try
             {
                 //Espera
                 SyncUtils.Wait(lockObj, wr);
             }
             catch (ThreadInterruptedException)
             {
                 //Remover da lista de espera
                 rwq.Remove(wr);
                 //Lançar excepção
                 throw;
             }
             //Se for o primeiro da lista e não houver ninguém a escrever nem a ler
             if (rwq.First == wr && !isWriting && readersReading == 0)
             {
                 //Remover da lista de espera
                 rwq.Remove(wr);
                 //Escritor a escrever
                 isWriting    = true;
                 writerInside = Thread.CurrentThread.ManagedThreadId;
                 return;
             }
         } while (true);
     }
 }
예제 #2
0
 // throws ThreadInterruptedException
 public void DownRead()
 {
     lock (lockObj){
         //Se não houver escritores à espera, nem estiver nenhum escritor a escrever
         if (!isWriting && rwq.First.Value.rw != WRITER)
         {
             //mais um leitor a ler
             readersReading++;
             readersInside.AddLast(Thread.CurrentThread.ManagedThreadId);
             return;
         }
         //Adicionar um novo leitor à lista de espera
         LinkedListNode <Rw> rd = rwq.AddLast(new Rw(READER));
         do
         {
             try
             {
                 //Esperar
                 SyncUtils.Wait(lockObj, rd);
             }
             catch (ThreadInterruptedException)
             {
                 //Remover da lista de espera
                 rwq.Remove(rd);
                 //Lançar excepção
                 throw;
             }
             //Pode ler se ninguem estiver a escrever e se for o primeiro da lista de espera
             if (!isWriting && rwq.First == rd)
             {
                 //Remover da lista de espera
                 rwq.Remove(rd);
                 //Mais um leitor a ler
                 readersReading++;
                 readersInside.AddLast(Thread.CurrentThread.ManagedThreadId);
                 return;
             }
         } while (true);
     }
 }
예제 #3
0
    // throws ThreadInterruptedException
    public bool TryEnter(int key)
    {
        lock (map)
        {
            //Se não existir a key, adiciona-se essa key com uma nova região
            if (!map.ContainsKey(key))
            {
                map.Add(key, new Region());
            }

            //região associada à key
            Region r = map[key];
            //se a região não estiver cheia a thread pode entrar
            if (r.inside < maxInside)
            {
                //mais uma thread dentro da região
                r.inside++;
                //conseguiu entrar logo retorna true
                return(true);
            }
            //se a lista de espera para entrar na região não estiver cheia a thread pode ficar à espera
            if (r.waiting.Count < maxWaiting)
            {
                //Momento inicial da espera
                int lastTime = (waitTimeout != Timeout.Infinite) ? Environment.TickCount : 0;
                //Nova thread à espera - adiciona-se ao fim para cumprir a disciplina FIFO
                LinkedListNode <object> myRequest = r.waiting.AddLast(new object());
                do
                {
                    try
                    {
                        //Espera por waitTimeout ms
                        SyncUtils.Wait(map, myRequest, waitTimeout);
                    }
                    catch (ThreadInterruptedException)
                    {
                        //Se saiu por excepção então removo a thread da lista de espera
                        r.waiting.Remove(myRequest);
                        //A expecção é relançada
                        throw;
                    }

                    //Se a thread saiu por timeOut mas há espaço para entrar então entra na mesma
                    if (r.inside < maxInside)
                    {
                        //Removo a thread da lista de espera
                        r.waiting.Remove(myRequest);
                        //Thread entra na região
                        r.inside++;
                        //Conseguiu entrar logo retorna true
                        return(true);
                    }

                    //enquanto não tiver passado timeOut. Isto porque podem ocorrer saidas espurias
                } while (SyncUtils.AdjustTimeout(ref lastTime, ref waitTimeout) != 0);

                //Se a thread saiu por timeOut e não houve espaço para entrar na região então removo da lista de espera
                r.waiting.Remove(myRequest);
                //Lanço timeOut exception
                throw new TimeoutException();
            }
            //Não conseguiu entrar na região nem na lista de espera então retorna false
            return(false);
        }
    }