The Pedigree Project 0.1
Readiness.cc
1/*
2 * Copyright (c) 2026, Pedigree Developers
3 *
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted.
6 */
7
8#include "pedigree/kernel/LockGuard.h"
9#include "pedigree/kernel/Log.h"
10#include "pedigree/kernel/process/Mutex.h"
11#include "pedigree/kernel/process/OperationBarrier.h"
12#include "pedigree/kernel/process/Readiness.h"
13#include "pedigree/kernel/utilities/List.h"
14#include "pedigree/kernel/utilities/Vector.h"
15#include "pedigree/kernel/utilities/utility.h"
16
17namespace {
18constexpr ReadyMask AlwaysReported = ReadyError | ReadyHangup | ReadyInvalid;
19}
20
22 public:
23 ReadinessTarget(ReadyMask interest, ReadinessObserver* observer)
24 : m_Interest(interest), m_pObserver(observer), m_Notifications() {}
25
27 if (!m_Notifications.isClosedAndDrained()) {
28 m_Notifications.closeAndWait();
29 }
30 }
31
32 bool interestedIn(ReadyMask mask) const {
33 return (mask & (m_Interest | AlwaysReported)) != 0;
34 }
35
36 void notify(ReadyMask mask) {
37 OperationBarrier::Lease notification;
38 if (!m_Notifications.tryAcquire(notification)) {
39 return;
40 }
41
42 m_pObserver->readinessChanged(mask);
43 }
44
45 void retire() {
46 m_Notifications.closeAndWait();
47 }
48
49 private:
50 ReadyMask m_Interest;
51 ReadinessObserver* m_pObserver;
52 OperationBarrier m_Notifications;
53};
54
56 public:
57 ReadinessState() : m_Lock(), m_Targets(), m_bOpen(true) {}
58
60 LockGuard<Mutex> guard(m_Lock);
61 if (m_Targets.count()) {
62 FATAL("ReadinessState destroyed with live subscriptions.");
63 }
64 }
65
66 bool add(const SharedPointer<ReadinessTarget>& target) {
67 LockGuard<Mutex> guard(m_Lock);
68 if (!m_bOpen) {
69 return false;
70 }
71
72 m_Targets.pushBack(target);
73 return true;
74 }
75
76 void remove(const SharedPointer<ReadinessTarget>& target) {
77 {
78 LockGuard<Mutex> guard(m_Lock);
80 it != m_Targets.end(); ++it) {
81 if (*it == target) {
82 m_Targets.erase(it);
83 break;
84 }
85 }
86 }
87
88 target->retire();
89 }
90
91 void notify(ReadyMask mask) {
93 {
94 LockGuard<Mutex> guard(m_Lock);
95 for (const auto& target : m_Targets) {
96 if (target->interestedIn(mask)) {
97 targets.pushBack(target);
98 }
99 }
100 }
101
102 for (auto& target : targets) {
103 target->notify(mask);
104 }
105 }
106
107 void close(ReadyMask mask) {
109 {
110 LockGuard<Mutex> guard(m_Lock);
111 if (!m_bOpen) {
112 return;
113 }
114
115 m_bOpen = false;
116 for (const auto& target : m_Targets) {
117 if (target->interestedIn(mask)) {
118 targets.pushBack(target);
119 }
120 }
121 }
122
123 for (auto& target : targets) {
124 target->notify(mask);
125 }
126 }
127
128 private:
129 Mutex m_Lock;
131 bool m_bOpen;
132};
133
134ReadinessSubscription::ReadinessSubscription() : m_State(), m_Target(), m_Observer() {}
135
136ReadinessSubscription::ReadinessSubscription(ReadinessSubscription&& other) noexcept
137 : m_State(pedigree_std::move(other.m_State)),
138 m_Target(pedigree_std::move(other.m_Target)),
139 m_Observer(pedigree_std::move(other.m_Observer)) {}
140
141ReadinessSubscription::~ReadinessSubscription() {
142 reset();
143}
144
145ReadinessSubscription& ReadinessSubscription::operator=(ReadinessSubscription&& other) noexcept {
146 if (this != &other) {
147 reset();
148 m_State = pedigree_std::move(other.m_State);
149 m_Target = pedigree_std::move(other.m_Target);
150 m_Observer = pedigree_std::move(other.m_Observer);
151 }
152 return *this;
153}
154
155ReadinessSubscription::operator bool() const {
156 return static_cast<bool>(m_State) && static_cast<bool>(m_Target);
157}
158
159void ReadinessSubscription::reset() {
160 SharedPointer<ReadinessState> state = m_State;
161 SharedPointer<ReadinessTarget> target = m_Target;
162 if (state && target) {
163 state->remove(target);
164 }
165
166 m_Target.reset();
167 m_Observer.reset();
168 m_State.reset();
169}
170
171ReadinessSource::ReadinessSource() : m_ReadinessState(new ReadinessState) {}
172
173ReadinessSource::~ReadinessSource() {
175}
176
180
182 const SharedPointer<ReadinessObserver>& observer,
183 ReadinessSubscription& subscription) {
184 subscription.reset();
185 if (!observer || !interest) {
186 return false;
187 }
188
189 SharedPointer<ReadinessTarget> target(new ReadinessTarget(interest, observer.get()));
190 subscription.m_State = m_ReadinessState;
191 subscription.m_Target = target;
192 subscription.m_Observer = observer;
193 if (!m_ReadinessState->add(target)) {
194 subscription.reset();
195 return false;
196 }
197
198 return true;
199}
200
202 if (mask) {
203 SharedPointer<ReadinessState> state = m_ReadinessState;
204 state->notify(mask);
205 }
206}
207
209 SharedPointer<ReadinessState> state = m_ReadinessState;
210 state->close(mask);
211}
An iterator applicable for many data structures.
Definition Iterator.h:41
Definition List.h:61
Iterator begin()
Definition List.h:122
Iterator end()
Definition List.h:132
Definition Mutex.h:56
MUST_USE_RESULT bool tryAcquire(Lease &lease)
virtual void readinessChanged(ReadyMask mask)=0
void notifyReadiness(ReadyMask mask)
Definition Readiness.cc:201
void closeReadiness(ReadyMask mask=ReadyInvalid|ReadyHangup)
Definition Readiness.cc:208
MUST_USE_RESULT bool subscribeReadiness(ReadyMask interest, const SharedPointer< ReadinessObserver > &observer, ReadinessSubscription &subscription)
Definition Readiness.cc:181
virtual ReadinessGenerations readinessGenerations()
Definition Readiness.cc:177
T * get() const
A vector / dynamic array.
Definition Vector.h:33
Iterator erase(Iterator &Iter)
Definition List.h:352
size_t count() const
Definition List.h:212
void pushBack(const T &value)
Definition List.h:216
void pushBack(const T &value)
Definition Vector.h:275