32 : pipeInName (pipePath +
"_in"),
33 pipeOutName (pipePath +
"_out"),
34 createdPipe (createPipe)
36 signal (SIGPIPE, signalHandler);
37 juce_siginterrupt (SIGPIPE, 1);
52 bool connect (
int timeOutMilliseconds)
54 return openPipe (
true, getTimeoutEnd (timeOutMilliseconds)) != invalidPipe;
57 int read (
char* destBuffer,
int maxBytesToRead,
int timeOutMilliseconds)
59 auto timeoutEnd = getTimeoutEnd (timeOutMilliseconds);
62 while (bytesRead < maxBytesToRead)
64 const auto pipe = pipeIn.get();
66 auto bytesThisTime = maxBytesToRead - bytesRead;
67 auto numRead = (
int) ::read (
pipe, destBuffer, (
size_t) bytesThisTime);
71 const auto error =
errno;
73 if (! (error ==
EWOULDBLOCK || error ==
EAGAIN) || stopReadOperation.
load() || hasExpired (timeoutEnd))
76 const int maxWaitingTime = 30;
77 waitForInput (
pipe, timeoutEnd == 0 ? maxWaitingTime
78 :
jmin (maxWaitingTime,
84 destBuffer += numRead;
90 int write (
const char* sourceBuffer,
int numBytesToWrite,
int timeOutMilliseconds)
92 auto timeoutEnd = getTimeoutEnd (timeOutMilliseconds);
94 const auto pipe = openPipe (
false, timeoutEnd);
96 if (
pipe == invalidPipe)
101 while (bytesWritten < numBytesToWrite && ! hasExpired (timeoutEnd))
103 auto bytesThisTime = numBytesToWrite - bytesWritten;
104 auto numWritten = (
int) ::write (
pipe, sourceBuffer, (
size_t) bytesThisTime);
108 const auto error =
errno;
109 const int maxWaitingTime = 30;
112 waitToWrite (
pipe, timeoutEnd == 0 ? maxWaitingTime
113 :
jmin (maxWaitingTime,
121 bytesWritten += numWritten;
122 sourceBuffer += numWritten;
128 static bool createFifo (
const String& name,
bool mustNotExist)
133 bool createFifos (
bool mustNotExist)
135 createdFifoIn = createFifo (pipeInName, mustNotExist);
136 createdFifoOut = createFifo (pipeOutName, mustNotExist);
138 return createdFifoIn && createdFifoOut;
141 static constexpr auto invalidPipe = -1;
146 template <
typename Fn>
152 if (descriptor != invalidPipe)
157 return descriptor = fn();
165 if (descriptor == invalidPipe)
170 ::close (descriptor);
171 descriptor = invalidPipe;
182 int descriptor = invalidPipe;
185 const String pipeInName, pipeOutName;
187 bool createdFifoIn =
false, createdFifoOut =
false;
189 const bool createdPipe;
193 static void signalHandler (
int) {}
195 static uint32 getTimeoutEnd (
int timeOutMilliseconds)
200 static bool hasExpired (
uint32 timeoutEnd)
205 int openPipe (
const String& name,
int flags,
uint32 timeoutEnd)
209 auto p = ::open (name.toUTF8(), flags);
211 if (p != invalidPipe || hasExpired (timeoutEnd) || stopReadOperation.
load())
218 int openPipe (
bool isInput,
uint32 timeoutEnd)
220 auto&
pipe = isInput ? pipeIn : pipeOut;
221 const auto flags = (isInput ? O_RDWR : O_WRONLY) | O_NONBLOCK;
223 const String& pipeName = isInput ? (createdPipe ? pipeInName : pipeOutName)
224 : (createdPipe ? pipeOutName : pipeInName);
226 return pipe.get ([
this, &pipeName, &flags, &timeoutEnd]
228 return openPipe (pipeName, flags, timeoutEnd);
232 static void waitForInput (
int handle,
int timeoutMsecs)
noexcept
234 pollfd pfd { handle, POLLIN, 0 };
235 poll (&pfd, 1, timeoutMsecs);
238 static void waitToWrite (
int handle,
int timeoutMsecs)
noexcept
240 pollfd pfd { handle, POLLOUT, 0 };
241 poll (&pfd, 1, timeoutMsecs);