OpenShot Library | OpenShotAudio  0.2.2
juce_NamedPipe.cpp
1 /*
2  ==============================================================================
3 
4  This file is part of the JUCE library.
5  Copyright (c) 2017 - ROLI Ltd.
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 
27 
29 {
30  close();
31 }
32 
33 bool NamedPipe::openExisting (const String& pipeName)
34 {
35  close();
36 
37  ScopedWriteLock sl (lock);
38  currentPipeName = pipeName;
39  return openInternal (pipeName, false, false);
40 }
41 
42 bool NamedPipe::isOpen() const
43 {
44  return pimpl != nullptr;
45 }
46 
47 bool NamedPipe::createNewPipe (const String& pipeName, bool mustNotExist)
48 {
49  close();
50 
51  ScopedWriteLock sl (lock);
52  currentPipeName = pipeName;
53  return openInternal (pipeName, true, mustNotExist);
54 }
55 
57 {
58  return currentPipeName;
59 }
60 
61 // other methods for this class are implemented in the platform-specific files
62 
63 
64 //==============================================================================
65 //==============================================================================
66 #if JUCE_UNIT_TESTS
67 
68 class NamedPipeTests : public UnitTest
69 {
70 public:
71  //==============================================================================
72  NamedPipeTests()
73  : UnitTest ("NamedPipe", UnitTestCategories::networking)
74  {}
75 
76  void runTest() override
77  {
78  const String pipeName ("TestPipe");
79 
80  beginTest ("Pre test cleanup");
81  {
82  NamedPipe pipe;
83  expect (pipe.createNewPipe (pipeName, false));
84  }
85 
86  beginTest ("Create pipe");
87  {
88  NamedPipe pipe;
89  expect (! pipe.isOpen());
90 
91  expect (pipe.createNewPipe (pipeName, true));
92  expect (pipe.isOpen());
93 
94  expect (pipe.createNewPipe (pipeName, false));
95  expect (pipe.isOpen());
96 
97  NamedPipe otherPipe;
98  expect (! otherPipe.createNewPipe (pipeName, true));
99  expect (! otherPipe.isOpen());
100  }
101 
102  beginTest ("Existing pipe");
103  {
104  NamedPipe pipe;
105 
106  expect (! pipe.openExisting (pipeName));
107  expect (! pipe.isOpen());
108 
109  expect (pipe.createNewPipe (pipeName, true));
110 
111  NamedPipe otherPipe;
112  expect (otherPipe.openExisting (pipeName));
113  expect (otherPipe.isOpen());
114  }
115 
116  int sendData = 4684682;
117 
118  beginTest ("Receive message created pipe");
119  {
120  NamedPipe pipe;
121  expect (pipe.createNewPipe (pipeName, true));
122 
123  WaitableEvent senderFinished;
124  SenderThread sender (pipeName, false, senderFinished, sendData);
125 
126  sender.startThread();
127 
128  int recvData = -1;
129  auto bytesRead = pipe.read (&recvData, sizeof (recvData), 2000);
130 
131  expect (senderFinished.wait (4000));
132 
133  expectEquals (bytesRead, (int) sizeof (recvData));
134  expectEquals (sender.result, (int) sizeof (sendData));
135  expectEquals (recvData, sendData);
136  }
137 
138  beginTest ("Receive message existing pipe");
139  {
140  WaitableEvent senderFinished;
141  SenderThread sender (pipeName, true, senderFinished, sendData);
142 
143  NamedPipe pipe;
144  expect (pipe.openExisting (pipeName));
145 
146  sender.startThread();
147 
148  int recvData = -1;
149  auto bytesRead = pipe.read (&recvData, sizeof (recvData), 2000);
150 
151  expect (senderFinished.wait (4000));
152 
153  expectEquals (bytesRead, (int) sizeof (recvData));
154  expectEquals (sender.result, (int) sizeof (sendData));
155  expectEquals (recvData, sendData);
156  }
157 
158  beginTest ("Send message created pipe");
159  {
160  NamedPipe pipe;
161  expect (pipe.createNewPipe (pipeName, true));
162 
163  WaitableEvent receiverFinished;
164  ReceiverThread receiver (pipeName, false, receiverFinished);
165 
166  receiver.startThread();
167 
168  auto bytesWritten = pipe.write (&sendData, sizeof (sendData), 2000);
169 
170  expect (receiverFinished.wait (4000));
171 
172  expectEquals (bytesWritten, (int) sizeof (sendData));
173  expectEquals (receiver.result, (int) sizeof (receiver.recvData));
174  expectEquals (receiver.recvData, sendData);
175  }
176 
177  beginTest ("Send message existing pipe");
178  {
179  WaitableEvent receiverFinished;
180  ReceiverThread receiver (pipeName, true, receiverFinished);
181 
182  NamedPipe pipe;
183  expect (pipe.openExisting (pipeName));
184 
185  receiver.startThread();
186 
187  auto bytesWritten = pipe.write (&sendData, sizeof (sendData), 2000);
188 
189  expect (receiverFinished.wait (4000));
190 
191  expectEquals (bytesWritten, (int) sizeof (sendData));
192  expectEquals (receiver.result, (int) sizeof (receiver.recvData));
193  expectEquals (receiver.recvData, sendData);
194  }
195  }
196 
197 private:
198  //==============================================================================
199  struct NamedPipeThread : public Thread
200  {
201  NamedPipeThread (const String& tName, const String& pName,
202  bool shouldCreatePipe, WaitableEvent& completed)
203  : Thread (tName), pipeName (pName), workCompleted (completed)
204  {
205  if (shouldCreatePipe)
206  pipe.createNewPipe (pipeName);
207  else
208  pipe.openExisting (pipeName);
209  }
210 
211  ~NamedPipeThread()
212  {
213  stopThread (100);
214  }
215 
216  NamedPipe pipe;
217  const String& pipeName;
218  WaitableEvent& workCompleted;
219 
220  int result = -2;
221  };
222 
223  //==============================================================================
224  struct SenderThread : public NamedPipeThread
225  {
226  SenderThread (const String& pName, bool shouldCreatePipe,
227  WaitableEvent& completed, int sData)
228  : NamedPipeThread ("NamePipeSender", pName, shouldCreatePipe, completed),
229  sendData (sData)
230  {}
231 
232  void run() override
233  {
234  result = pipe.write (&sendData, sizeof (sendData), 2000);
235  workCompleted.signal();
236  }
237 
238  const int sendData;
239  };
240 
241  //==============================================================================
242  struct ReceiverThread : public NamedPipeThread
243  {
244  ReceiverThread (const String& pName, bool shouldCreatePipe,
245  WaitableEvent& completed)
246  : NamedPipeThread ("NamePipeSender", pName, shouldCreatePipe, completed)
247  {}
248 
249  void run() override
250  {
251  result = pipe.read (&recvData, sizeof (recvData), 2000);
252  workCompleted.signal();
253  }
254 
255  int recvData = -2;
256  };
257 };
258 
259 static NamedPipeTests namedPipeTests;
260 
261 #endif
262 
263 } // namespace juce
void close()
Closes the pipe, if it's open.
~NamedPipe()
Destructor.
Allows threads to wait for events triggered by other threads.
int read(void *destBuffer, int maxBytesToRead, int timeOutMilliseconds)
Reads data from the pipe.
The JUCE String class!
Definition: juce_String.h:42
NamedPipe()
Creates a NamedPipe.
bool isOpen() const
True if the pipe is currently open.
This is a base class for classes that perform a unit test.
Definition: juce_UnitTest.h:73
int write(const void *sourceBuffer, int numBytesToWrite, int timeOutMilliseconds)
Writes some data to the pipe.
A cross-process pipe that can have data written to and read from it.
bool createNewPipe(const String &pipeName, bool mustNotExist=false)
Tries to create a new pipe.
Encapsulates a thread.
Definition: juce_Thread.h:46
bool wait(int timeOutMilliseconds=-1) const
Suspends the calling thread until the event has been signalled.
Automatically locks and unlocks a ReadWriteLock object.
String getName() const
Returns the last name that was used to try to open this pipe.
bool openExisting(const String &pipeName)
Tries to open a pipe that already exists.