Example #1
0
            public bool Enter()
            {
                // ainda há espaço
                if (!IsRegionFull())
                {
                    if (maxInside > 0)
                    {
                        this.maxInside--;
                        return(true); // a entrada foi feita com sucesso
                    }
                }

                /* não há espaço, vou ver se posso ficar em espera na waitingQueue
                 * não podem estar mais do que maxWaiting threads à espera de entrar na
                 * zona protegida pela mesma chave */
                if (IsWaitingQueueFull())
                {
                    return(false);
                }
                else
                {
                    LinkedListNode <bool> node = waitingQueue.AddLast(false);
                    int timeout  = waitTimeout;
                    int lastTime = (timeout != Timeout.Infinite) ? Environment.TickCount : 0;
                    do
                    {
                        try  {
                            Monitor.Wait(myLock, timeout);
                        }
                        // interrompido o bloqueio da thread
                        catch (ThreadInterruptedException e) {
                            waitingQueue.Remove(node);
                            throw;
                        }
                        // verificar se já fui sinalizado
                        if (node.Value)
                        {
                            waitingQueue.Remove(node);
                            if (maxInside > 0)
                            {
                                this.maxInside--;
                                return(true);
                            }
                        }

                        /* verificar se ocorreu timeout, uma thread não poderá esperar mais
                         * do que waitTimeout milésimos de segundo para entrar na zona
                         * protegida */
                        if (SyncUtils.AdjustTimeout(ref lastTime, ref timeout) == 0)
                        {
                            waitingQueue.Remove(node);
                            return(false);
                        }
                    } while (true);
                }
            }
Example #2
0
        public T Exchange(T mine, int timeout)   // throws ThreadInterruptedException
        {
            lock (myLock) {
                if (someoneIsWaiting)
                {
                    this.mail.secondMessage = mine;
                    this.mail.completed     = true;
                    someoneIsWaiting        = false;
                    Monitor.PulseAll(myLock);
                    return(this.mail.firstMessage);
                }
                if (timeout == 0)
                {
                    throw new TimeoutException();
                }

                int lastTime = (timeout != Timeout.Infinite) ? Environment.TickCount : 0;
                mail = new Mail <T>();
                mail.firstMessage  = mine;
                mail.secondMessage = default(T);
                someoneIsWaiting   = true;
                do
                {
                    try {
                        Monitor.Wait(myLock, timeout);
                    }
                    /* (c) a espera seja interrompida, terminado o método com o lançamento de ThreadInterruptedException. */
                    catch (ThreadInterruptedException) {
                        if (mail.completed)
                        {
                            return(mail.secondMessage);
                        }
                        else
                        {
                            someoneIsWaiting = false;
                            // vale a pena retiro a minha mensagem? visto q a proxima a entrar vai fazer default
                            throw;
                        }
                    }
                    /* (a) outra thread invoque o método Exchange , devolvendo o método a mensagem oferecida pela outra thread; */
                    if (mail.completed)
                    {
                        return(mail.secondMessage);
                    }
                    /* (b) expire o limite do tempo de espera especificado, situação em que o método devolve null , ou; */
                    if (SyncUtils.AdjustTimeout(ref lastTime, ref timeout) == 0)
                    {
                        someoneIsWaiting = false;
                        throw new TimeoutException();
                    }
                } while (true);
            }
        }
Example #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);
        }
    }
    public T Exchange(T mine, int timeout)
    {
        lock (lockObj)
        {
            //Se já existir um request então este request pode emparelhar com ele
            if (request != null)
            {
                //dois requests estão a emparelhar
                request.isExchanging = true;
                //Trocar mensagens
                T myMessage = request.message;
                request.message = mine;
                //Acorda a thread à espera de emparelhamento
                Monitor.Pulse(lockObj);
                //Retorna a mensagem
                return(myMessage);
            }

            //Ainda não existe nenhum request em espera de emparelhamento, logo tem de esperar por outro
            ThreadRequest req = new ThreadRequest(mine);
            request = req;

            //Momento inicial da espera
            int lastTime = (timeout != Timeout.Infinite) ? Environment.TickCount : 0;
            do
            {
                try
                {
                    //Esperar por outro emparelhamento
                    Monitor.Wait(lockObj, timeout);
                }
                catch (ThreadInterruptedException)
                {
                    //Se sair por excepção e estiver a emparelhar:
                    if (req.isExchanging)
                    {
                        //sinalizar esta thread como interrompida
                        Thread.CurrentThread.Interrupt();
                        //retornar a mensagem
                        return(req.message);
                    }
                    //Se sair por excepção e não estiver a emparelhar elimina o request e lança excepção
                    request = null;
                    throw;
                }

                //Se a thread acordou e estiver a emparelhar:
                if (req.isExchanging)
                {
                    //Apagar o request
                    request = null;
                    //Retornar a mensagem
                    return(req.message);
                }

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

            //Se a thread saiu por timeOut e está a emparelhar então continua e retorna
            if (req.isExchanging)
            {
                //Apagar o request
                request = null;
                //Retornar a mensagem
                return(req.message);
            }

            //Se a thread saiu por timeOut e não está a emparelhar então apaga o request e lança excepção
            request = null;
            throw new TimeoutException();
        }
    }