// throws InvalidOperationException public void UpWrite() { lock (lockObj) { //se n tiver sido invocado por uma thread que invocou o DownWrite //lança excepção if (writerInside != Thread.CurrentThread.ManagedThreadId) { throw new InvalidOperationException(); } //Nenhum escritor a escrever isWriting = false; //Se houver leitores/escritores à espera if (rwq.Count > 0) { //Se houver leitores à espera if (rwq.First.Value.rw == READER) { //Notificar todos os leitores que estão no inicio da fila, antes de uma escrita NotifyAllReaders(); } //Se houver escritores à espera else { //Notifica o primeiro escritor da lista SyncUtils.Notify(lockObj, rwq.First); } } } }
//Acedido na posse do lock - lockObj private void NotifyAllReaders() { for (LinkedListNode <Rw> curr = rwq.First; ; curr = curr.Next) { if (curr.Value.rw == WRITER) { return; } SyncUtils.Notify(lockObj, curr); } }
public void Leave(int key) { lock (map) { //Se não existe a key, retorna e não faz nada if (!map.ContainsKey(key)) { return; } //Região associada à key Region r = map[key]; //menos uma thread dentro da região r.inside--; //se houver threads à espera para entrar na região if (r.waiting.Count > 0) { //É notificada a primeira que entrou para cumprir a disciplina FIFO SyncUtils.Notify(map, r.waiting.First); } } }
// throws InvalidOperationException public void UpRead() { lock (lockObj) { if (!readersInside.Contains(Thread.CurrentThread.ManagedThreadId)) { throw new InvalidOperationException(); } //Menos um leitor a ler readersReading--; readersInside.Remove(Thread.CurrentThread.ManagedThreadId); //Se não esta nenhum leitor a ler e houver escritores à espera //Não pode haver leitores à espera no inicio da fila neste momento!! if (readersReading == 0 && rwq.Count > 0) { //Notifica o primeiro escritor da lista SyncUtils.Notify(lockObj, rwq.First); } } }