CppCommon 1.0.5.0
C++ Common Library
Loading...
Searching...
No Matches
pipe.cpp
Go to the documentation of this file.
1
9#include "system/pipe.h"
10
11#include "errors/fatal.h"
13
14#include <cassert>
15
16#if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
17#include <unistd.h>
18#elif defined(_WIN32) || defined(_WIN64)
19#include <windows.h>
20#endif
21
22namespace CppCommon {
23
25
26class Pipe::Impl
27{
28public:
29 Impl()
30 {
31#if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
32 int result = pipe(_pipe);
33 if (result != 0)
34 throwex SystemException("Failed to create a new pipe!");
35#elif defined(_WIN32) || defined(_WIN64)
36 if (!CreatePipe(&_pipe[0], &_pipe[1], nullptr, 0))
37 throwex SystemException("Failed to create a new pipe!");
38#endif
39 }
40
41 ~Impl()
42 {
43 try
44 {
45 if (IsPipeOpened())
46 Close();
47 }
48 catch (const SystemException& ex)
49 {
50 fatality(SystemException(ex.string()));
51 }
52 }
53
54 void* reader() const noexcept
55 {
56 return (void*)(size_t)_pipe[0];
57 }
58
59 void* writer() const noexcept
60 {
61 return (void*)(size_t)_pipe[1];
62 }
63
64 bool IsPipeOpened() const noexcept
65 {
66 return IsPipeReadOpened() || IsPipeWriteOpened();
67 }
68
69 bool IsPipeReadOpened() const noexcept
70 {
71#if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
72 return (_pipe[0] >= 0);
73#elif defined(_WIN32) || defined(_WIN64)
74 return (_pipe[0] != INVALID_HANDLE_VALUE);
75#endif
76 }
77
78 bool IsPipeWriteOpened() const noexcept
79 {
80#if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
81 return (_pipe[1] >= 0);
82#elif defined(_WIN32) || defined(_WIN64)
83 return (_pipe[1] != INVALID_HANDLE_VALUE);
84#endif
85 }
86
87 size_t Read(void* buffer, size_t size)
88 {
89 if ((buffer == nullptr) || (size == 0))
90 return 0;
91
92 assert(IsPipeReadOpened() && "Pipe is not opened for reading!");
93 if (!IsPipeReadOpened())
94 throwex SystemException("Cannot read from the closed pipe!");
95#if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
96 ssize_t result = read(_pipe[0], buffer, size);
97 if (result < 0)
98 throwex SystemException("Cannot read from the pipe!");
99 return (size_t)result;
100#elif defined(_WIN32) || defined(_WIN64)
101 DWORD result = 0;
102 if (!ReadFile(_pipe[0], buffer, (DWORD)size, &result, nullptr))
103 if (GetLastError() != ERROR_BROKEN_PIPE)
104 throwex SystemException("Cannot read from the pipe!");
105 return (size_t)result;
106#endif
107 }
108
109 size_t Write(const void* buffer, size_t size)
110 {
111 if ((buffer == nullptr) || (size == 0))
112 return 0;
113
114 assert(IsPipeWriteOpened() && "Pipe is not opened for writing!");
115 if (!IsPipeWriteOpened())
116 throwex SystemException("Cannot write into the closed pipe!");
117#if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
118 ssize_t result = write(_pipe[1], buffer, size);
119 if (result < 0)
120 throwex SystemException("Cannot write into the pipe!");
121 return (size_t)result;
122#elif defined(_WIN32) || defined(_WIN64)
123 DWORD result = 0;
124 if (!WriteFile(_pipe[1], buffer, (DWORD)size, &result, nullptr))
125 if (GetLastError() != ERROR_BROKEN_PIPE)
126 throwex SystemException("Cannot write into the pipe!");
127 return (size_t)result;
128#endif
129 }
130
131 void CloseRead()
132 {
133 assert(IsPipeReadOpened() && "Pipe is not opened for reading!");
134 if (!IsPipeReadOpened())
135 throwex SystemException("Pipe is not opened for reading!");
136#if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
137 int result = close(_pipe[0]);
138 if (result != 0)
139 throwex SystemException("Cannot close the read pipe endpoint!");
140 _pipe[0] = -1;
141#elif defined(_WIN32) || defined(_WIN64)
142 if (!CloseHandle(_pipe[0]))
143 throwex SystemException("Cannot close the read pipe endpoint!");
144 _pipe[0] = INVALID_HANDLE_VALUE;
145#endif
146 }
147
148 void CloseWrite()
149 {
150 assert(IsPipeWriteOpened() && "Pipe is not opened for writing!");
151 if (!IsPipeWriteOpened())
152 throwex SystemException("Pipe is not opened for writing!");
153#if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
154 int result = close(_pipe[1]);
155 if (result != 0)
156 throwex SystemException("Cannot close the write pipe endpoint!");
157 _pipe[1] = -1;
158#elif defined(_WIN32) || defined(_WIN64)
159 if (!CloseHandle(_pipe[1]))
160 throwex SystemException("Cannot close the write pipe endpoint!");
161 _pipe[1] = INVALID_HANDLE_VALUE;
162#endif
163 }
164
165 void Close()
166 {
167 if (IsPipeReadOpened())
168 CloseRead();
169 if (IsPipeWriteOpened())
170 CloseWrite();
171 }
172
173private:
174#if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
175 int _pipe[2];
176#elif defined(_WIN32) || defined(_WIN64)
177 HANDLE _pipe[2];
178#endif
179};
180
182
184{
185 // Check implementation storage parameters
186 [[maybe_unused]] ValidateAlignedStorage<sizeof(Impl), alignof(Impl), StorageSize, StorageAlign> _;
187 static_assert((StorageSize >= sizeof(Impl)), "Pipe::StorageSize must be increased!");
188 static_assert(((StorageAlign % alignof(Impl)) == 0), "Pipe::StorageAlign must be adjusted!");
189
190 // Create the implementation instance
191 new(&_storage)Impl();
192}
193
195{
196 // Delete the implementation instance
197 reinterpret_cast<Impl*>(&_storage)->~Impl();
198}
199
200void* Pipe::reader() const noexcept { return impl().reader(); }
201void* Pipe::writer() const noexcept { return impl().writer(); }
202
203bool Pipe::IsPipeOpened() const noexcept { return impl().IsPipeOpened(); }
204bool Pipe::IsPipeReadOpened() const noexcept { return impl().IsPipeReadOpened(); }
205bool Pipe::IsPipeWriteOpened() const noexcept { return impl().IsPipeWriteOpened(); }
206
207size_t Pipe::Read(void* buffer, size_t size) { return impl().Read(buffer, size); }
208size_t Pipe::Write(const void* buffer, size_t size) { return impl().Write(buffer, size); }
209
210void Pipe::CloseRead() { return impl().CloseRead(); }
211void Pipe::CloseWrite() { return impl().CloseWrite(); }
212void Pipe::Close() { return impl().Close(); }
213
214void Pipe::swap(Pipe& pipe) noexcept
215{
216 using std::swap;
217 swap(_storage, pipe._storage);
218}
219
220} // namespace CppCommon
Pipe.
Definition pipe.h:31
bool IsPipeOpened() const noexcept
Is pipe opened for reading or writing?
Definition pipe.cpp:203
void CloseWrite()
Close the write pipe endpoint.
Definition pipe.cpp:211
friend void swap(Pipe &pipe1, Pipe &pipe2) noexcept
Definition pipe.inl:11
size_t Read(void *buffer, size_t size) override
Read a bytes buffer from the pipe.
Definition pipe.cpp:207
void Close()
Close all pipe endpoints.
Definition pipe.cpp:212
bool IsPipeWriteOpened() const noexcept
Is pipe opened for writing?
Definition pipe.cpp:205
bool IsPipeReadOpened() const noexcept
Is pipe opened for reading?
Definition pipe.cpp:204
size_t Write(const void *buffer, size_t size) override
Write a byte buffer into the pipe.
Definition pipe.cpp:208
void * reader() const noexcept
Get the native read endpoint handler.
Definition pipe.cpp:200
void * writer() const noexcept
Get the native write endpoint handler.
Definition pipe.cpp:201
void CloseRead()
Close the read pipe endpoint.
Definition pipe.cpp:210
virtual ~Pipe()
Definition pipe.cpp:194
#define throwex
Throw extended exception macro.
Definition exceptions.h:23
Fatal abort execution definition.
#define fatality(...)
Fatal abort execution extended macro.
Definition fatal.h:22
C++ Common project definitions.
void swap(FileCache &cache1, FileCache &cache2) noexcept
Definition filecache.inl:23
Pipe definition.
Aligned storage validator definition.