void Inode::NotifyEndClosed(bool writer) { TRACE("Inode %p::%s(%s)\n", this, __FUNCTION__, writer ? "writer" : "reader"); if (writer) { // Our last writer has been closed; if the pipe // contains no data, unlock all waiting readers TRACE(" buffer readable: %zu\n", fBuffer.Readable()); if (fBuffer.Readable() == 0) { ReadRequestList::Iterator iterator = fReadRequests.GetIterator(); while (ReadRequest* request = iterator.Next()) request->Notify(); if (fReadSelectSyncPool) notify_select_event_pool(fReadSelectSyncPool, B_SELECT_READ); } } else { // Last reader is gone. Wake up all writers. fWriteCondition.NotifyAll(); if (fWriteSelectSyncPool) { notify_select_event_pool(fWriteSelectSyncPool, B_SELECT_WRITE); notify_select_event_pool(fWriteSelectSyncPool, B_SELECT_ERROR); } } }
void Inode::Close(int openMode, file_cookie* cookie) { TRACE("Inode %p::Close(openMode = %d)\n", this, openMode); MutexLocker locker(RequestLock()); // Notify all currently reading file descriptors ReadRequestList::Iterator iterator = fReadRequests.GetIterator(); while (ReadRequest* request = iterator.Next()) { if (request->Cookie() == cookie) request->Notify(B_FILE_ERROR); } if ((openMode & O_ACCMODE) == O_WRONLY && --fWriterCount == 0) NotifyEndClosed(true); if ((openMode & O_ACCMODE) == O_RDONLY || (openMode & O_ACCMODE) == O_RDWR) { if (--fReaderCount == 0) NotifyEndClosed(false); } if (fWriterCount == 0) { // Notify any still reading writers to stop // TODO: This only works reliable if there is only one writer - we could // do the same thing done for the read requests. fWriteCondition.NotifyAll(B_FILE_ERROR); } if (fReaderCount == 0 && fWriterCount == 0) { fActive = false; fBuffer.DeleteBuffer(); } }