- /*
- ==============================================================================
-
- This file is part of the JUCE library.
- Copyright (c) 2022 - Raw Material Software Limited
-
- JUCE is an open source library subject to commercial or open-source
- licensing.
-
- The code included in this file is provided under the terms of the ISC license
- http://www.isc.org/downloads/software-support-policy/isc-license. Permission
- To use, copy, modify, and/or distribute this software for any purpose with or
- without fee is hereby granted provided that the above copyright notice and
- this permission notice appear in all copies.
-
- JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
- EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
- DISCLAIMED.
-
- ==============================================================================
- */
-
- namespace juce
- {
-
- //==============================================================================
- /**
- Acts as the worker end of a coordinator/worker pair of connected processes.
-
- The ChildProcessWorker and ChildProcessCoordinator classes make it easy for an app
- to spawn a child process, and to manage a 2-way messaging connection to control it.
-
- To use the system, you need to create subclasses of both ChildProcessWorker and
- ChildProcessCoordinator. To instantiate the ChildProcessWorker object, you must
- add some code to your main() or JUCEApplication::initialise() function that
- calls the initialiseFromCommandLine() method to check the app's command-line
- parameters to see whether it's being launched as a child process. If this returns
- true then the worker process can be allowed to run, and its handleMessageFromCoordinator()
- method will be called whenever a message arrives.
-
- The juce demo app has a good example of this class in action.
-
- @see ChildProcessCoordinator, InterprocessConnection, ChildProcess
-
- @tags{Events}
- */
- class JUCE_API ChildProcessWorker
- {
- public:
- /** Creates a non-connected worker process.
- Use initialiseFromCommandLine to connect to a coordinator process.
- */
- ChildProcessWorker();
-
- /** Destructor. */
- virtual ~ChildProcessWorker();
-
- /** This checks some command-line parameters to see whether they were generated by
- ChildProcessCoordinator::launchWorkerProcess(), and if so, connects to that coordinator process.
-
- In an exe that can be used as a child process, you should add some code to your
- main() or JUCEApplication::initialise() that calls this method.
-
- The commandLineUniqueID should be a short alphanumeric identifier (no spaces!)
- that matches the string passed to ChildProcessCoordinator::launchWorkerProcess().
-
- The timeoutMs parameter lets you specify how long the child process is allowed
- to run without receiving a ping from the coordinator before the coordinator is considered to
- have died, and handleConnectionLost() will be called. Passing <= 0 for this timeout
- makes it use a default value.
-
- Returns true if the command-line matches and the connection is made successfully.
- */
- bool initialiseFromCommandLine (const String& commandLine,
- const String& commandLineUniqueID,
- int timeoutMs = 0);
-
- //==============================================================================
- /** This will be called to deliver messages from the coordinator process.
- The call will probably be made on a background thread, so be careful with your
- thread-safety! You may want to respond by sending back a message with
- sendMessageToCoordinator()
- */
- virtual void handleMessageFromCoordinator (const MemoryBlock& mb);
-
- [[deprecated ("Replaced by handleMessageFromCoordinator.")]]
- virtual void handleMessageFromMaster (const MemoryBlock&) {}
-
- /** This will be called when the coordinator process finishes connecting to this worker.
- The call will probably be made on a background thread, so be careful with your thread-safety!
- */
- virtual void handleConnectionMade();
-
- /** This will be called when the connection to the coordinator process is lost.
- The call may be made from any thread (including the message thread).
- Typically, if your process only exists to act as a worker, you should probably exit
- when this happens.
- */
- virtual void handleConnectionLost();
-
- /** Tries to send a message to the coordinator process.
- This returns true if the message was sent, but doesn't check that it actually gets
- delivered at the other end. If successful, the data will emerge in a call to your
- ChildProcessCoordinator::handleMessageFromWorker().
- */
- bool sendMessageToCoordinator (const MemoryBlock&);
-
- [[deprecated ("Replaced by sendMessageToCoordinator.")]]
- bool sendMessageToMaster (const MemoryBlock& mb) { return sendMessageToCoordinator (mb); }
-
- private:
- struct Connection;
- std::unique_ptr<Connection> connection;
-
- JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ChildProcessWorker)
- };
-
- using ChildProcessSlave [[deprecated ("Replaced by ChildProcessWorker.")]] = ChildProcessWorker;
-
- //==============================================================================
- /**
- Acts as the coordinator in a coordinator/worker pair of connected processes.
-
- The ChildProcessWorker and ChildProcessCoordinator classes make it easy for an app
- to spawn a child process, and to manage a 2-way messaging connection to control it.
-
- To use the system, you need to create subclasses of both ChildProcessWorker and
- ChildProcessCoordinator. When you want your coordinator process to launch the worker, you
- just call launchWorkerProcess(), and it'll attempt to launch the executable that
- you specify (which may be the same exe), and assuming it has been set-up to
- correctly parse the command-line parameters (see ChildProcessWorker) then a
- two-way connection will be created.
-
- The juce demo app has a good example of this class in action.
-
- @see ChildProcessWorker, InterprocessConnection, ChildProcess
-
- @tags{Events}
- */
- class JUCE_API ChildProcessCoordinator
- {
- public:
- /** Creates an uninitialised coordinator process object.
- Use launchWorkerProcess to launch and connect to a child process.
- */
- ChildProcessCoordinator();
-
- /** Destructor.
- Note that the destructor calls killWorkerProcess(), but doesn't wait for
- the child process to finish terminating.
- */
- virtual ~ChildProcessCoordinator();
-
- /** Attempts to launch and connect to a worker process.
- This will start the given executable, passing it a special command-line
- parameter based around the commandLineUniqueID string, which must be a
- short alphanumeric string (no spaces!) that identifies your app. The exe
- that gets launched must respond by calling ChildProcessWorker::initialiseFromCommandLine()
- in its startup code, and must use a matching ID to commandLineUniqueID.
-
- The timeoutMs parameter lets you specify how long the child process is allowed
- to go without sending a ping before it is considered to have died and
- handleConnectionLost() will be called. Passing <= 0 for this timeout makes
- it use a default value.
-
- If this all works, the method returns true, and you can begin sending and
- receiving messages with the worker process.
-
- If a child process is already running, this will call killWorkerProcess() and
- start a new one.
- */
- bool launchWorkerProcess (const File& executableToLaunch,
- const String& commandLineUniqueID,
- int timeoutMs = 0,
- int streamFlags = ChildProcess::wantStdOut | ChildProcess::wantStdErr);
-
- [[deprecated ("Replaced by launchWorkerProcess.")]]
- bool launchSlaveProcess (const File& executableToLaunch,
- const String& commandLineUniqueID,
- int timeoutMs = 0,
- int streamFlags = ChildProcess::wantStdOut | ChildProcess::wantStdErr)
- {
- return launchWorkerProcess (executableToLaunch, commandLineUniqueID, timeoutMs, streamFlags);
- }
-
- /** Sends a kill message to the worker, and disconnects from it.
- Note that this won't wait for it to terminate.
- */
- void killWorkerProcess();
-
- [[deprecated ("Replaced by killWorkerProcess.")]]
- void killSlaveProcess() { killWorkerProcess(); }
-
- /** This will be called to deliver a message from the worker process.
- The call will probably be made on a background thread, so be careful with your thread-safety!
- */
- virtual void handleMessageFromWorker (const MemoryBlock&);
-
- [[deprecated ("Replaced by handleMessageFromWorker")]]
- virtual void handleMessageFromSlave (const MemoryBlock&) {}
-
- /** This will be called when the worker process dies or is somehow disconnected.
- The call will probably be made on a background thread, so be careful with your thread-safety!
- */
- virtual void handleConnectionLost();
-
- /** Attempts to send a message to the worker process.
- This returns true if the message was dispatched, but doesn't check that it actually
- gets delivered at the other end. If successful, the data will emerge in a call to
- your ChildProcessWorker::handleMessageFromCoordinator().
- */
- bool sendMessageToWorker (const MemoryBlock&);
-
- [[deprecated ("Replaced by sendMessageToWorker.")]]
- bool sendMessageToSlave (const MemoryBlock& mb) { return sendMessageToWorker (mb); }
-
- private:
- std::unique_ptr<ChildProcess> childProcess;
-
- struct Connection;
- std::unique_ptr<Connection> connection;
-
- JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ChildProcessCoordinator)
- };
-
- using ChildProcessMaster [[deprecated ("Replaced by ChildProcessCoordinator.")]] = ChildProcessCoordinator;
-
- } // namespace juce
|