The Pedigree Project 0.1
Buffer.h
1/*
2 * Copyright (c) 2008-2014, Pedigree Developers
3 *
4 * Please see the CONTRIB file in the root of the source tree for a full
5 * list of contributors.
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20#ifndef KERNEL_UTILITIES_BUFFER_H
21#define KERNEL_UTILITIES_BUFFER_H
22#include "pedigree/kernel/Atomic.h"
23#include "pedigree/kernel/compiler.h"
24#include "pedigree/kernel/process/ConditionVariable.h"
25#include "pedigree/kernel/process/Event.h"
26#include "pedigree/kernel/process/Mutex.h"
27#include "pedigree/kernel/process/TerminationDeferral.h"
28#include "pedigree/kernel/processor/types.h"
29#include "pedigree/kernel/utilities/BufferMonitors.h"
30#include "pedigree/kernel/utilities/List.h"
31#include "pedigree/kernel/utilities/new"
32
33#include <config.h>
34
35class Semaphore;
36class Thread;
37
52template <class T, bool allowShortOperation = false>
53class EXPORTED_PUBLIC Buffer {
54 friend class UnixSocket; // to allow for calling notifyMonitors()
55
56 public:
57 Buffer(size_t bufferSize);
58 ~Buffer();
59
64 size_t write(const T* buffer, size_t count, bool block = true);
65
71 size_t writeAvailable(const T* buffer, size_t count, bool atomic = false);
72
78 size_t writeAtomic(const T* buffer, size_t count, bool block = true);
79
85 bool tryWrite(const T* buffer, size_t count);
86
91 size_t read(T* buffer, size_t count, bool block = true);
92
97 void disableWrites();
98
103 void disableReads();
104
110 bool enableWrites();
111
117 bool enableReads();
118
122 size_t getDataSize();
123
127 size_t getSize();
128
133 bool canWrite(bool block);
134
138 bool canRead(bool block);
139
141 uint64_t readableGeneration() const;
142 uint64_t writableGeneration() const;
143
147 void wipe();
148
154 void monitor(Thread* pThread, Event* pEvent);
155
159 void monitor(Semaphore* pSemaphore);
160
164 void cullMonitorTargets(Thread* pThread);
165
169 void cullMonitorTargets(Semaphore* pSemaphore);
170
174 void cullMonitorTargets(Event* pEvent);
175
176#if HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS
178 void acquireHostedOperationLock();
179 void releaseHostedOperationLock();
180 size_t getHostedActiveOperationCount();
181#endif
182
183 private:
184 WITHOUT_IMPLICIT_CONSTRUCTORS(Buffer);
185
187 public:
188 explicit ActiveOperation(Buffer& buffer)
189 : m_TerminationDeferral(), m_Buffer(buffer.beginOperation() ? &buffer : nullptr) {}
190
192 if (m_Buffer) {
193 m_Buffer->endOperation();
194 }
195 }
196
197 explicit operator bool() const {
198 return m_Buffer != nullptr;
199 }
200
201 private:
202 ActiveOperation(const ActiveOperation&) = delete;
203 ActiveOperation& operator=(const ActiveOperation&) = delete;
204
205 TerminationDeferral m_TerminationDeferral;
206 Buffer* m_Buffer;
207 };
208
209 bool beginOperation();
210 void endOperation();
211
217 void notifyMonitors();
218
220 void notifyMonitorsLocked();
221
223 size_t writeLocked(const T* buffer, size_t count);
224
228 void addSegment(const T* buffer, size_t count);
229
233 static const size_t m_SegmentSize = 32768;
234
239 struct Segment {
240 Segment() : data(), reader(0), size(0) {}
241
243 T data[m_SegmentSize];
244
246 size_t reader;
247
249 size_t size;
250 };
251
252 size_t m_BufferSize;
253 size_t m_DataSize;
254 Atomic<uint64_t> m_ReadableGeneration;
255 Atomic<uint64_t> m_WritableGeneration;
256
257 Mutex m_Lock;
258
259 ConditionVariable m_WriteCondition;
260 ConditionVariable m_ReadCondition;
261 ConditionVariable m_DrainCondition;
262
263 List<Segment*> m_Segments;
264 BufferMonitors m_Monitors;
265
266 bool m_bCanRead;
267 bool m_bCanWrite;
268 bool m_bClosing;
269 size_t m_ActiveOperations;
270};
271
272// Specializations are in a .cc file.
273extern template class Buffer<uint8_t, false>; // IWYU pragma: keep
274extern template class Buffer<uint8_t, true>; // IWYU pragma: keep
275extern template class Buffer<char, false>; // IWYU pragma: keep
276extern template class Buffer<char, true>; // IWYU pragma: keep
277extern template class Buffer<size_t, false>; // IWYU pragma: keep
278extern template class Buffer<size_t, true>; // IWYU pragma: keep
279
280#endif // KERNEL_UTILITIES_BUFFER_H
Definition Event.h:49
Definition List.h:61
Definition Mutex.h:56
size_t size
Definition Buffer.h:249
size_t reader
Definition Buffer.h:246
Definition waits.c:9