1eb8b342dSIngo Weinhold /* 2eb8b342dSIngo Weinhold * Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de. 3eb8b342dSIngo Weinhold * Distributed under the terms of the MIT License. 4eb8b342dSIngo Weinhold */ 5eb8b342dSIngo Weinhold #ifndef UNIX_FIFO_H 6eb8b342dSIngo Weinhold #define UNIX_FIFO_H 7eb8b342dSIngo Weinhold 8eb8b342dSIngo Weinhold #include <Referenceable.h> 9eb8b342dSIngo Weinhold 105b29b956SIngo Weinhold #include <condition_variable.h> 11eb8b342dSIngo Weinhold #include <lock.h> 12eb8b342dSIngo Weinhold #include <util/AutoLock.h> 13eb8b342dSIngo Weinhold #include <util/DoublyLinkedList.h> 14eb8b342dSIngo Weinhold 15eb8b342dSIngo Weinhold #include <net_buffer.h> 16eb8b342dSIngo Weinhold 17eb8b342dSIngo Weinhold 18eb8b342dSIngo Weinhold #define UNIX_FIFO_SHUTDOWN_READ 1 19eb8b342dSIngo Weinhold #define UNIX_FIFO_SHUTDOWN_WRITE 2 20eb8b342dSIngo Weinhold 21*ea035707SIngo Weinhold #define UNIX_FIFO_SHUTDOWN (B_ERRORS_END + 1) 22eb8b342dSIngo Weinhold // error code returned by Read()/Write() 23eb8b342dSIngo Weinhold 24eb8b342dSIngo Weinhold #define UNIX_FIFO_MINIMAL_CAPACITY 1024 25eb8b342dSIngo Weinhold #define UNIX_FIFO_MAXIMAL_CAPACITY (128 * 1024) 26eb8b342dSIngo Weinhold 27eb8b342dSIngo Weinhold 28*ea035707SIngo Weinhold struct ring_buffer; 29*ea035707SIngo Weinhold 30*ea035707SIngo Weinhold class UnixRequest : public DoublyLinkedListLinkImpl<UnixRequest> { 31*ea035707SIngo Weinhold public: 32*ea035707SIngo Weinhold UnixRequest(const iovec* vecs, size_t count, 33*ea035707SIngo Weinhold ancillary_data_container* ancillaryData); 34*ea035707SIngo Weinhold 35*ea035707SIngo Weinhold off_t TotalSize() const { return fTotalSize; } 36*ea035707SIngo Weinhold off_t BytesTransferred() const { return fBytesTransferred; } 37*ea035707SIngo Weinhold off_t BytesRemaining() const { return fTotalSize - fBytesTransferred; } 38*ea035707SIngo Weinhold 39*ea035707SIngo Weinhold void AddBytesTransferred(size_t size); 40*ea035707SIngo Weinhold bool GetCurrentChunk(void*& data, size_t& size); 41*ea035707SIngo Weinhold 42*ea035707SIngo Weinhold ancillary_data_container* AncillaryData() const { return fAncillaryData; } 43*ea035707SIngo Weinhold void SetAncillaryData(ancillary_data_container* data); 44*ea035707SIngo Weinhold void AddAncillaryData(ancillary_data_container* data); 45*ea035707SIngo Weinhold 46*ea035707SIngo Weinhold private: 47*ea035707SIngo Weinhold const iovec* fVecs; 48*ea035707SIngo Weinhold size_t fVecCount; 49*ea035707SIngo Weinhold ancillary_data_container* fAncillaryData; 50*ea035707SIngo Weinhold off_t fTotalSize; 51*ea035707SIngo Weinhold off_t fBytesTransferred; 52*ea035707SIngo Weinhold size_t fVecIndex; 53*ea035707SIngo Weinhold size_t fVecOffset; 54*ea035707SIngo Weinhold }; 55438df7ecSIngo Weinhold 56438df7ecSIngo Weinhold 57eb8b342dSIngo Weinhold class UnixBufferQueue { 58eb8b342dSIngo Weinhold public: 59eb8b342dSIngo Weinhold UnixBufferQueue(size_t capacity); 60eb8b342dSIngo Weinhold ~UnixBufferQueue(); 61eb8b342dSIngo Weinhold 62*ea035707SIngo Weinhold status_t Init(); 63eb8b342dSIngo Weinhold 64*ea035707SIngo Weinhold size_t Readable() const; 65*ea035707SIngo Weinhold size_t Writable() const; 66*ea035707SIngo Weinhold 67*ea035707SIngo Weinhold status_t Read(UnixRequest& request); 68*ea035707SIngo Weinhold status_t Write(UnixRequest& request); 69eb8b342dSIngo Weinhold 70eb8b342dSIngo Weinhold size_t Capacity() const { return fCapacity; } 71*ea035707SIngo Weinhold status_t SetCapacity(size_t capacity); 72438df7ecSIngo Weinhold 73eb8b342dSIngo Weinhold private: 74*ea035707SIngo Weinhold struct AncillaryDataEntry : DoublyLinkedListLinkImpl<AncillaryDataEntry> { 75*ea035707SIngo Weinhold ancillary_data_container* data; 76*ea035707SIngo Weinhold size_t offset; 77eb8b342dSIngo Weinhold }; 78eb8b342dSIngo Weinhold 79*ea035707SIngo Weinhold typedef DoublyLinkedList<AncillaryDataEntry> AncillaryDataList; 80*ea035707SIngo Weinhold 81*ea035707SIngo Weinhold ring_buffer* fBuffer; 82*ea035707SIngo Weinhold size_t fCapacity; 83*ea035707SIngo Weinhold AncillaryDataList fAncillaryData; 84*ea035707SIngo Weinhold }; 85eb8b342dSIngo Weinhold 86eb8b342dSIngo Weinhold 87eb8b342dSIngo Weinhold class UnixFifo : public Referenceable { 88eb8b342dSIngo Weinhold public: 89eb8b342dSIngo Weinhold UnixFifo(size_t capacity); 90eb8b342dSIngo Weinhold ~UnixFifo(); 91eb8b342dSIngo Weinhold 92eb8b342dSIngo Weinhold status_t Init(); 93eb8b342dSIngo Weinhold 94eb8b342dSIngo Weinhold bool Lock() 95eb8b342dSIngo Weinhold { 9639ae5e4dSIngo Weinhold return mutex_lock(&fLock) == B_OK; 97eb8b342dSIngo Weinhold } 98eb8b342dSIngo Weinhold 99eb8b342dSIngo Weinhold void Unlock() 100eb8b342dSIngo Weinhold { 10139ae5e4dSIngo Weinhold mutex_unlock(&fLock); 102eb8b342dSIngo Weinhold } 103eb8b342dSIngo Weinhold 104eb8b342dSIngo Weinhold void Shutdown(uint32 shutdown); 105eb8b342dSIngo Weinhold 106eb8b342dSIngo Weinhold bool IsReadShutdown() const 107eb8b342dSIngo Weinhold { 108eb8b342dSIngo Weinhold return (fShutdown & UNIX_FIFO_SHUTDOWN_READ); 109eb8b342dSIngo Weinhold } 110eb8b342dSIngo Weinhold 111eb8b342dSIngo Weinhold bool IsWriteShutdown() const 112eb8b342dSIngo Weinhold { 113eb8b342dSIngo Weinhold return (fShutdown & UNIX_FIFO_SHUTDOWN_WRITE); 114eb8b342dSIngo Weinhold } 115eb8b342dSIngo Weinhold 116*ea035707SIngo Weinhold ssize_t Read(const iovec* vecs, size_t vecCount, 117*ea035707SIngo Weinhold ancillary_data_container** _ancillaryData, bigtime_t timeout); 118*ea035707SIngo Weinhold ssize_t Write(const iovec* vecs, size_t vecCount, 119*ea035707SIngo Weinhold ancillary_data_container* ancillaryData, bigtime_t timeout); 120eb8b342dSIngo Weinhold 121eb8b342dSIngo Weinhold size_t Readable() const; 122eb8b342dSIngo Weinhold size_t Writable() const; 123eb8b342dSIngo Weinhold 124*ea035707SIngo Weinhold status_t SetBufferCapacity(size_t capacity); 125eb8b342dSIngo Weinhold 126eb8b342dSIngo Weinhold private: 127*ea035707SIngo Weinhold typedef DoublyLinkedList<UnixRequest> RequestList; 128eb8b342dSIngo Weinhold 129eb8b342dSIngo Weinhold private: 130*ea035707SIngo Weinhold status_t _Read(UnixRequest& request, bigtime_t timeout); 131*ea035707SIngo Weinhold status_t _Write(UnixRequest& request, bigtime_t timeout); 132*ea035707SIngo Weinhold status_t _WriteNonBlocking(UnixRequest& request); 133eb8b342dSIngo Weinhold 134eb8b342dSIngo Weinhold private: 13539ae5e4dSIngo Weinhold mutex fLock; 136eb8b342dSIngo Weinhold UnixBufferQueue fBuffer; 137eb8b342dSIngo Weinhold RequestList fReaders; 138eb8b342dSIngo Weinhold RequestList fWriters; 139*ea035707SIngo Weinhold off_t fReadRequested; 140*ea035707SIngo Weinhold off_t fWriteRequested; 1415b29b956SIngo Weinhold ConditionVariable fReadCondition; 1425b29b956SIngo Weinhold ConditionVariable fWriteCondition; 143eb8b342dSIngo Weinhold uint32 fShutdown; 144eb8b342dSIngo Weinhold }; 145eb8b342dSIngo Weinhold 146eb8b342dSIngo Weinhold 147eb8b342dSIngo Weinhold typedef AutoLocker<UnixFifo> UnixFifoLocker; 148eb8b342dSIngo Weinhold 149eb8b342dSIngo Weinhold 150eb8b342dSIngo Weinhold #endif // UNIX_FIFO_H 151