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