The Pedigree Project 0.1
RingBuffer.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 RINGBUFFER_H
21#define RINGBUFFER_H
22#include "pedigree/kernel/Atomic.h"
23#include "pedigree/kernel/process/Event.h"
24#include "pedigree/kernel/process/Semaphore.h"
25#include "pedigree/kernel/process/Thread.h"
26#include "pedigree/kernel/utilities/BufferMonitors.h"
27#include "pedigree/kernel/utilities/Mailbox.h"
28
29namespace RingBufferWait = MailboxWait;
30
32 void changed(bool becameReadable, bool becameWritable) {
33 if (becameReadable) {
34 readableGeneration += 1;
35 }
36 if (becameWritable) {
37 writableGeneration += 1;
38 }
39 monitors.notify();
40 }
41
42 void closed() {
43 monitors.notify();
44 }
45
46 Atomic<uint64_t> readableGeneration{0};
47 Atomic<uint64_t> writableGeneration{0};
48 BufferMonitors monitors;
49};
50
52template <class T, size_t preallocatedSize = 0>
53class EXPORTED_PUBLIC RingBuffer : public Mailbox<T, preallocatedSize, RingBufferNotifications> {
55
56 public:
57 explicit RingBuffer(size_t ringSize) : Base(ringSize) {}
58
59 uint64_t readableGeneration() const {
60 return this->m_Notifications.readableGeneration.value();
61 }
62
63 uint64_t writableGeneration() const {
64 return this->m_Notifications.writableGeneration.value();
65 }
66
80 bool monitor(Thread* pThread, Event* pEvent) {
81 typename Base::ActiveOperation operation(*this);
82 if (!operation) {
83 Event::SendLease registration;
84 if (pEvent->tryAcquireRegistration(registration)) {
85 EMIT_IF(THREADS) {
86 pThread->sendEvent(pEvent);
87 }
88 }
89 return false;
90 }
91
92 if (this->readsClosed()) {
93 Event::SendLease registration;
94 if (pEvent->tryAcquireRegistration(registration)) {
95 EMIT_IF(THREADS) {
96 pThread->sendEvent(pEvent);
97 }
98 }
99 return false;
100 }
101
102 return this->m_Notifications.monitors.add(pThread, pEvent);
103 }
104
106 bool monitor(Semaphore* pSemaphore) {
107 typename Base::ActiveOperation operation(*this);
108 if (!operation) {
109 EMIT_IF(THREADS) {
110 pSemaphore->release();
111 }
112 return false;
113 }
114
115 if (this->readsClosed()) {
116 EMIT_IF(THREADS) {
117 pSemaphore->release();
118 }
119 return false;
120 }
121
122 this->m_Notifications.monitors.add(pSemaphore);
123 return true;
124 }
125
127 void cullMonitorTargets(Thread* pThread) {
128 typename Base::ActiveOperation operation(*this);
129 if (!operation) {
130 return;
131 }
132
133 this->m_Notifications.monitors.cull(pThread);
134 }
135
137 void cullMonitorTargets(Semaphore* pSemaphore) {
138 typename Base::ActiveOperation operation(*this);
139 if (!operation) {
140 return;
141 }
142
143 this->m_Notifications.monitors.cull(pSemaphore);
144 }
145
147 void cullMonitorTargets(Event* pEvent) {
148 typename Base::ActiveOperation operation(*this);
149 if (!operation) {
150 return;
151 }
152
153 this->m_Notifications.monitors.cull(pEvent);
154 }
155};
156
157extern template class RingBuffer<char>; // IWYU pragma: keep
158extern template class RingBuffer<void*>; // IWYU pragma: keep
159
160#endif
Definition Event.h:49
bool tryAcquireRegistration(SendLease &registration)
Definition Event.cc:392
bool monitor(Thread *pThread, Event *pEvent)
monitor - add a new Event to be fired when something happens
Definition RingBuffer.h:80
void cullMonitorTargets(Semaphore *pSemaphore)
Cull all monitor targets pointing to pSemaphore.
Definition RingBuffer.h:137
bool monitor(Semaphore *pSemaphore)
Add a Semaphore to be signaled when readiness changes or the ring closes.
Definition RingBuffer.h:106
void cullMonitorTargets(Event *pEvent)
Cull all monitor targets pointing to pEvent.
Definition RingBuffer.h:147
void cullMonitorTargets(Thread *pThread)
Cull all monitor targets pointing to pThread.
Definition RingBuffer.h:127
void release(size_t n=1)
Definition Semaphore.cc:549
bool sendEvent(Event *pEvent)
Definition Thread.cc:1115