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 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 #define TRACE_BUFFER_QUEUE 1 29 30 31 class UnixBufferQueue { 32 public: 33 UnixBufferQueue(size_t capacity); 34 ~UnixBufferQueue(); 35 36 size_t Readable() const { return fSize; } 37 size_t Writable() const 38 { return fCapacity >= fSize ? fCapacity - fSize : 0; } 39 40 status_t Read(size_t size, net_buffer** _buffer); 41 status_t Write(net_buffer* buffer, size_t maxSize); 42 43 size_t Capacity() const { return fCapacity; } 44 void SetCapacity(size_t capacity); 45 46 #if TRACE_BUFFER_QUEUE 47 void ParanoiaReadCheck(net_buffer* buffer); 48 void PostReadWrite(); 49 #endif 50 51 private: 52 typedef DoublyLinkedList<net_buffer, DoublyLinkedListCLink<net_buffer> > 53 BufferList; 54 55 BufferList fBuffers; 56 size_t fSize; 57 size_t fCapacity; 58 #if TRACE_BUFFER_QUEUE 59 off_t fWritten; 60 off_t fRead; 61 uint8* fParanoiaCheckBuffer; 62 uint8* fParanoiaCheckBuffer2; 63 #endif 64 }; 65 66 67 68 class UnixFifo : public Referenceable { 69 public: 70 UnixFifo(size_t capacity); 71 ~UnixFifo(); 72 73 status_t Init(); 74 75 bool Lock() 76 { 77 return benaphore_lock(&fLock) == B_OK; 78 } 79 80 void Unlock() 81 { 82 benaphore_unlock(&fLock); 83 } 84 85 void Shutdown(uint32 shutdown); 86 87 bool IsReadShutdown() const 88 { 89 return (fShutdown & UNIX_FIFO_SHUTDOWN_READ); 90 } 91 92 bool IsWriteShutdown() const 93 { 94 return (fShutdown & UNIX_FIFO_SHUTDOWN_WRITE); 95 } 96 97 status_t Read(size_t numBytes, bigtime_t timeout, net_buffer** _buffer); 98 status_t Write(net_buffer* buffer, bigtime_t timeout); 99 100 size_t Readable() const; 101 size_t Writable() const; 102 103 void SetBufferCapacity(size_t capacity); 104 105 private: 106 struct Request : DoublyLinkedListLinkImpl<Request> { 107 Request(size_t size) 108 : 109 size(size) 110 { 111 } 112 113 size_t size; 114 }; 115 116 typedef DoublyLinkedList<Request> RequestList; 117 118 private: 119 status_t _Read(Request& request, size_t numBytes, bigtime_t timeout, 120 net_buffer** _buffer); 121 status_t _Write(Request& request, net_buffer* buffer, bigtime_t timeout, 122 size_t& bytesWritten); 123 status_t _WriteNonBlocking(Request& request, net_buffer* buffer, 124 size_t& bytesWritten); 125 126 private: 127 benaphore fLock; 128 UnixBufferQueue fBuffer; 129 RequestList fReaders; 130 RequestList fWriters; 131 size_t fReadRequested; 132 size_t fWriteRequested; 133 ConditionVariable fReadCondition; 134 ConditionVariable fWriteCondition; 135 uint32 fShutdown; 136 }; 137 138 139 typedef AutoLocker<UnixFifo> UnixFifoLocker; 140 141 142 #endif // UNIX_FIFO_H 143