The Pedigree Project 0.1
Pipe-transfer.cc
1/* Copyright (c) 2026, Pedigree Developers. */
2#include "Pipe.h"
3
4namespace {
5class PipeStoragePin {
6 public:
7 explicit PipeStoragePin(Pipe& pipe) : m_Pipe(pipe.retainVfsReference() ? &pipe : nullptr) {}
8 ~PipeStoragePin() {
9 if (m_Pipe) {
10 m_Pipe->releaseVfsReference();
11 }
12 }
13 explicit operator bool() const {
14 return m_Pipe != nullptr;
15 }
16
17 private:
18 PipeStoragePin(const PipeStoragePin&) = delete;
19 PipeStoragePin& operator=(const PipeStoragePin&) = delete;
20 TerminationDeferral m_Termination;
21 Pipe* m_Pipe;
22};
23} // namespace
24
25Pipe::ReadReservation::~ReadReservation() {
26 cancel();
27}
28
29size_t Pipe::ReadReservation::size() const {
30 return m_Reservation.size();
31}
32
33void Pipe::ReadReservation::copyTo(uint8_t* destination, size_t count) const {
34 m_Reservation.copyTo(destination, count);
35}
36
37void Pipe::ReadReservation::consume(size_t accepted) {
38 m_Reservation.consume(accepted);
39 if (m_Pipe) {
40 Pipe* pipe = m_Pipe;
41 m_Pipe = nullptr;
42 pipe->releaseVfsReference();
43 }
44}
45
46void Pipe::ReadReservation::cancel() {
47 consume(0);
48}
49
50Pipe::WriteReservation::~WriteReservation() {
51 cancel();
52}
53
54size_t Pipe::WriteReservation::size() const {
55 return m_Reservation.size();
56}
57
58PipeBuffer::Result Pipe::WriteReservation::commit(const uint8_t* source, size_t accepted) {
59 const auto result = m_Reservation.commit(source, accepted);
60 if (m_Pipe) {
61 Pipe* pipe = m_Pipe;
62 m_Pipe = nullptr;
63 if (result.count) {
64 pipe->publishEvent(FileEvents::Modify);
65 }
66 pipe->releaseVfsReference();
67 }
68 return result;
69}
70
71void Pipe::WriteReservation::cancel() {
72 m_Reservation.cancel();
73 if (m_Pipe) {
74 Pipe* pipe = m_Pipe;
75 m_Pipe = nullptr;
76 pipe->releaseVfsReference();
77 }
78}
79
80PipeBuffer::Result Pipe::reserveRead(size_t maximum, bool block, ReadReservation& reservation) {
81 if (reservation.m_Pipe) {
82 return {PipeBuffer::Status::Invalid, 0};
83 }
84 if (!retainVfsReference()) {
85 return {PipeBuffer::Status::Closed, 0};
86 }
87 const auto result = m_Buffer.reserveRead(maximum, block, reservation.m_Reservation);
88 if (result.status == PipeBuffer::Status::Ready && result.count) {
89 reservation.m_Pipe = this;
90 } else {
92 }
93 return result;
94}
95
96PipeBuffer::Result Pipe::reserveWrite(size_t maximum, bool block, WriteReservation& reservation) {
97 if (reservation.m_Pipe) {
98 return {PipeBuffer::Status::Invalid, 0};
99 }
100 if (!retainVfsReference()) {
101 return {PipeBuffer::Status::Closed, 0};
102 }
103 const auto result = m_Buffer.reserveWrite(maximum, block, reservation.m_Reservation);
104 if (result.status == PipeBuffer::Status::Ready && result.count) {
105 reservation.m_Pipe = this;
106 } else {
108 }
109 return result;
110}
111
112PipeBuffer::Result Pipe::waitTransfer(bool writing, bool block) {
113 PipeStoragePin pin(*this);
114 return pin ? m_Buffer.waitTransfer(writing, block)
115 : PipeBuffer::Result{PipeBuffer::Status::Closed, 0};
116}
117
118PipeBuffer::Result Pipe::transferTo(Pipe& output, size_t maximum, bool consume, bool block) {
119 PipeStoragePin inputPin(*this);
120 PipeStoragePin outputPin(output);
121 if (!inputPin || !outputPin) {
122 return {PipeBuffer::Status::Closed, 0};
123 }
124 const auto result = m_Buffer.transferTo(output.m_Buffer, maximum, consume, block);
125 if (result.count) {
126 output.publishEvent(FileEvents::Modify);
127 }
128 return result;
129}
void publishEvent(FileEventMask mask, const StringView &name=StringView(), bool targetIsDirectory=false)
Definition File.cc:793
Definition Pipe.h:36
void releaseVfsReference() override
Definition Pipe.cc:274
bool retainVfsReference() override
Definition Pipe.cc:261
PipeBuffer m_Buffer
Definition Pipe.h:166