// Obtain permissions to read objects in the workspace. This obtains // many permissions on the read access and should be called in // conjunction with _releaseAllReadPermissions. // This method suspends the calling thread until such permission // has been obtained. Permission is granted unless either another // thread has write permission, or there are threads that // have requested write permission and not gotten it yet. // @param count This is the number of read permissions desired on the // workspace. // @exception InternalErrorException If the calling thread is interrupted // while waiting to re-acquire read permissions. private synchronized void _reacquireReadPermissions(int count) { // If the count argument is equal to zero, which means we would like // the current thread to has read depth equal to 0, i.e. not a reader, // then it's already trivially done, since this method call is always // preceded by _releaseAllReadPermissions. if (count == 0) { return; } Thread current = Thread.currentThread(); AccessRecord record = null; if (current == _lastReader) { record = _lastReaderRecord; } else { record = _getAccessRecord(current, false); } if ((record == null) || (count > record.failedReadAttempts)) { throw new InvalidStateException( this, "Trying to reacquire " + "read permission not in record."); } // Go into an infinite 'while (true)' loop, and each time through // the loop, check if the condition is satisfied to have the current // thread as a writer. If not, then wait on the workspace. Upon // re-awakening, iterate in the loop again to check if the condition // is now satisfied. while (true) { // If the current thread has write permission, or if there // are no pending write requests, then grant read permission. if ((current == _writer) || ((_waitingWriteRequests == 0) && (_writer == null))) { _numReaders++; record.failedReadAttempts -= count; record.readDepth = count; return; } try { wait(); } catch (InterruptedException ex) { throw new InternalErrorException( "Thread interrupted while waiting for read access!" + ex.getMessage()); } } }
/** * Frees the thread of all the readAccesses on the workspace. The method _reacquireAllReadAccesses * should be called after this method is called. * * @return The number of readAccess that the thread possessed on the workspace */ private synchronized int _releaseAllReadPermissions() { // Find the current thread. Thread current = Thread.currentThread(); AccessRecord record = null; if (current == _lastReader) { record = _lastReaderRecord; } else { record = _getAccessRecord(current, false); } if ((record == null) || (record.readDepth == 0)) { // current thread is not a reader return 0; } else { _numReaders--; notifyAll(); int result = record.readDepth; record.failedReadAttempts += result; record.readDepth = 0; return result; } }