OpenShot Audio Library | OpenShotAudio  0.6.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 
23 namespace juce
24 {
25 
26 #if ! JUCE_WASM
27 
29 
31 {
32  close();
33 }
34 
35 bool NamedPipe::openExisting (const String& pipeName)
36 {
37  close();
38 
39  ScopedWriteLock sl (lock);
40  currentPipeName = pipeName;
41  return openInternal (pipeName, false, false);
42 }
43 
44 bool NamedPipe::isOpen() const
45 {
46  ScopedReadLock sl (lock);
47  return pimpl != nullptr;
48 }
49 
50 bool 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 
72 class NamedPipeTests final : public UnitTest
73 {
74 public:
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 
201 private:
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 
268 static 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()