xref: /haiku/src/add-ons/kernel/network/protocols/unix/UnixFifo.h (revision 17889a8c70dbb3d59c1412f6431968753c767bab)
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