OpenShot Audio Library | OpenShotAudio 0.4.0
juce_NamedPipe.cpp
1/*
2 ==============================================================================
3
4 This file is part of the JUCE library.
5 Copyright (c) 2022 - Raw Material Software Limited
6
7 JUCE is an open source library subject to commercial or open-source
8 licensing.
9
10 The code included in this file is provided under the terms of the ISC license
11 http://www.isc.org/downloads/software-support-policy/isc-license. Permission
12 To use, copy, modify, and/or distribute this software for any purpose with or
13 without fee is hereby granted provided that the above copyright notice and
14 this permission notice appear in all copies.
15
16 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
17 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
18 DISCLAIMED.
19
20 ==============================================================================
21*/
22
23namespace juce
24{
25
26#if ! JUCE_WASM
27
29
31{
32 close();
33}
34
35bool NamedPipe::openExisting (const String& pipeName)
36{
37 close();
38
39 ScopedWriteLock sl (lock);
40 currentPipeName = pipeName;
41 return openInternal (pipeName, false, false);
42}
43
45{
46 ScopedReadLock sl (lock);
47 return pimpl != nullptr;
48}
49
50bool NamedPipe::createNewPipe (const String& pipeName, bool mustNotExist)
51{
52 close();
53
54 ScopedWriteLock sl (lock);
55 currentPipeName = pipeName;
56 return openInternal (pipeName, true, mustNotExist);
57}
58
60{
61 ScopedReadLock sl (lock);
62 return currentPipeName;
63}
64
65// other methods for this class are implemented in the platform-specific files
66
67
68//==============================================================================
69//==============================================================================
70#if JUCE_UNIT_TESTS
71
72class NamedPipeTests final : public UnitTest
73{
74public:
75 //==============================================================================
76 NamedPipeTests()
77 : UnitTest ("NamedPipe", UnitTestCategories::networking)
78 {}
79
80 void runTest() override
81 {
82 const auto pipeName = "TestPipe" + String ((intptr_t) Thread::getCurrentThreadId());
83
84 beginTest ("Pre test cleanup");
85 {
86 NamedPipe pipe;
87 expect (pipe.createNewPipe (pipeName, false));
88 }
89
90 beginTest ("Create pipe");
91 {
92 NamedPipe pipe;
93 expect (! pipe.isOpen());
94
95 expect (pipe.createNewPipe (pipeName, true));
96 expect (pipe.isOpen());
97
98 expect (pipe.createNewPipe (pipeName, false));
99 expect (pipe.isOpen());
100
101 NamedPipe otherPipe;
102 expect (! otherPipe.createNewPipe (pipeName, true));
103 expect (! otherPipe.isOpen());
104 }
105
106 beginTest ("Existing pipe");
107 {
108 NamedPipe pipe;
109
110 expect (! pipe.openExisting (pipeName));
111 expect (! pipe.isOpen());
112
113 expect (pipe.createNewPipe (pipeName, true));
114
115 NamedPipe otherPipe;
116 expect (otherPipe.openExisting (pipeName));
117 expect (otherPipe.isOpen());
118 }
119
120 int sendData = 4684682;
121
122 beginTest ("Receive message created pipe");
123 {
124 NamedPipe pipe;
125 expect (pipe.createNewPipe (pipeName, true));
126
127 WaitableEvent senderFinished;
128 SenderThread sender (pipeName, false, senderFinished, sendData);
129
130 sender.startThread();
131
132 int recvData = -1;
133 auto bytesRead = pipe.read (&recvData, sizeof (recvData), 2000);
134
135 expect (senderFinished.wait (4000));
136
137 expectEquals (bytesRead, (int) sizeof (recvData));
138 expectEquals (sender.result, (int) sizeof (sendData));
139 expectEquals (recvData, sendData);
140 }
141
142 beginTest ("Receive message existing pipe");
143 {
144 WaitableEvent senderFinished;
145 SenderThread sender (pipeName, true, senderFinished, sendData);
146
147 NamedPipe pipe;
148 expect (pipe.openExisting (pipeName));
149
150 sender.startThread();
151
152 int recvData = -1;
153 auto bytesRead = pipe.read (&recvData, sizeof (recvData), 2000);
154
155 expect (senderFinished.wait (4000));
156
157 expectEquals (bytesRead, (int) sizeof (recvData));
158 expectEquals (sender.result, (int) sizeof (sendData));
159 expectEquals (recvData, sendData);
160 }
161
162 beginTest ("Send message created pipe");
163 {
164 NamedPipe pipe;
165 expect (pipe.createNewPipe (pipeName, true));
166
167 WaitableEvent receiverFinished;
168 ReceiverThread receiver (pipeName, false, receiverFinished);
169
170 receiver.startThread();
171
172 auto bytesWritten = pipe.write (&sendData, sizeof (sendData), 2000);
173
174 expect (receiverFinished.wait (4000));
175
176 expectEquals (bytesWritten, (int) sizeof (sendData));
177 expectEquals (receiver.result, (int) sizeof (receiver.recvData));
178 expectEquals (receiver.recvData, sendData);
179 }
180
181 beginTest ("Send message existing pipe");
182 {
183 WaitableEvent receiverFinished;
184 ReceiverThread receiver (pipeName, true, receiverFinished);
185
186 NamedPipe pipe;
187 expect (pipe.openExisting (pipeName));
188
189 receiver.startThread();
190
191 auto bytesWritten = pipe.write (&sendData, sizeof (sendData), 2000);
192
193 expect (receiverFinished.wait (4000));
194
195 expectEquals (bytesWritten, (int) sizeof (sendData));
196 expectEquals (receiver.result, (int) sizeof (receiver.recvData));
197 expectEquals (receiver.recvData, sendData);
198 }
199 }
200
201private:
202 //==============================================================================
203 struct NamedPipeThread : public Thread
204 {
205 NamedPipeThread (const String& tName, const String& pName,
206 bool shouldCreatePipe, WaitableEvent& completed)
207 : Thread (tName), pipeName (pName), workCompleted (completed)
208 {
209 if (shouldCreatePipe)
210 pipe.createNewPipe (pipeName);
211 else
212 pipe.openExisting (pipeName);
213 }
214
215 NamedPipe pipe;
216 const String& pipeName;
217 WaitableEvent& workCompleted;
218
219 int result = -2;
220 };
221
222 //==============================================================================
223 struct SenderThread final : public NamedPipeThread
224 {
225 SenderThread (const String& pName, bool shouldCreatePipe,
226 WaitableEvent& completed, int sData)
227 : NamedPipeThread ("NamePipeSender", pName, shouldCreatePipe, completed),
228 sendData (sData)
229 {}
230
231 ~SenderThread() override
232 {
233 stopThread (100);
234 }
235
236 void run() override
237 {
238 result = pipe.write (&sendData, sizeof (sendData), 2000);
239 workCompleted.signal();
240 }
241
242 const int sendData;
243 };
244
245 //==============================================================================
246 struct ReceiverThread final : public NamedPipeThread
247 {
248 ReceiverThread (const String& pName, bool shouldCreatePipe,
249 WaitableEvent& completed)
250 : NamedPipeThread ("NamePipeSender", pName, shouldCreatePipe, completed)
251 {}
252
253 ~ReceiverThread() override
254 {
255 stopThread (100);
256 }
257
258 void run() override
259 {
260 result = pipe.read (&recvData, sizeof (recvData), 2000);
261 workCompleted.signal();
262 }
263
264 int recvData = -2;
265 };
266};
267
268static NamedPipeTests namedPipeTests;
269
270#endif
271#endif
272
273} // namespace juce
String getName() const
bool isOpen() const
bool createNewPipe(const String &pipeName, bool mustNotExist=false)
bool openExisting(const String &pipeName)
static ThreadID JUCE_CALLTYPE getCurrentThreadId()