New in PixInsight 1.8.6: Interprocess Communication (IPC)

Juan Conejero

PixInsight Staff
Staff member
As I described in the official announcement, PixInsight 1.8.6 ships with fully operational interprocess communication (IPC) functionality. Basically, this means that there can be several instances of the PixInsight core application running simultaneously on the same machine, and that all of them can send and receive messages and share data with each other. Although this feature may seem relatively 'simple', if you think on the kinds of things that can be done this way you'll realize that IPC extends PixInsight's flexibility, applicability and processing force enormously.

To demonstrate how IPC works in PixInsight 1.8.6, consider the following scripts:

sender.js
Code:
function main()
{
   console.abortEnabled = true;
   console.show();
   console.writeln( "<end><cbr>
Sending messages ... " );

   for ( let count = 0; ; ++count )
   {
      processEvents();
      if ( console.abortRequested )
         break;

      if ( CoreApplication.isInstanceRunning( 2 ) )
         CoreApplication.sendMessage( 2, format( "Message %d", count ) );

      msleep( 100 );
   }

   console.writeln( "<end><cbr>end." );
}

main();


listener.js
Code:
function main()
{
   console.abortEnabled = true;
   console.show();
   console.writeln( "<end><cbr>
Receiving messages ... " );

   let listener = new MessageListener;
   listener.onMessage = function( instance, uniqueId, message )
   {
      console.writeln( format( "<end><cbr>Received message from application instance %d with uuid = %s: %s", instance, uniqueId, message ) );
   };

   for ( ;; )
   {
      processEvents();
      if ( console.abortRequested )
         break;
      msleep( 10 );
   }

   listener.enabled = false;
   listener.onMessage = null;
   console.writeln( "<end><cbr>end." );

   console.writeln( format( "%u pending message(s).", CoreApplication.numberOfPendingMessages ) );
   CoreApplication.processPendingMessages();
}

main();

Copy and paste them in two new JavaScript documents (for example, using PixInsight's Script Editor) and save them as sender.js and listener.js, respectively. Now run a first instance of PixInsight in the usual way. Open Script Editor and load sender.js. Open the Process Console window and enter the following command to launch a second instance of PixInsight:

j CoreApplication.launchInstance( 2 )

Once launched, go to the second instance and load listener.js in Script Editor. Run it by pressing F9 (Ctrl+R on macOS). Go to the first instance and run sender.js in the same way. Go to the second instance and look at the console. As you'll see, the application instance #2 is receiving messages sent by the first instance and showing message data on the console. To stop the scripts, press Esc or click the Pause/Abort buttons. Now if you want to test IPC further, you can launch a third, fourth, ... application instance and run sender.js on each of them. Up to 255 instances of the PixInsight core application are supported.

These simple scripts let you grasp the significance of IPC in PixInsight. For example, a typical scenario could be an image acquisition procedure with asynchronous processing:
  • Application instance #1 acquires a new image and writes it as a new file, then sends an IPC message to instance #2 with the corresponding file path.
  • Application instance #2 receives the IPC message, loads the file, processes the image, and writes the processed image as a new file.
To sophisticate this example further, with a bit of additional work two or more application instances could be waiting for new images and processing them concurrently as soon as they are acquired. This parallel producer/consumer implementation would require just a simple protocol to differentiate busy and idle application states. Easy, clean, and extremely powerful!

The IPC functionality is available in the JavaScript runtime. As you can see in the scripts above, the key objects are CoreApplication and MessageListener. Both objects are very easy to use. Each IPC message transports a plain text payload, which can be received, along with a unique message identifier and the number of the sending instance (>= 1), in the onMessage event handler of a MessageListener (or derived from) object.

Each running application instance allocates an IPC segment, which is a block of contiguous memory dedicated to receive IPC messages. By default, IPC segments provide just 64 KiB of RAM. The maximum length of a message payload is smaller than that, about 60 KiB. This is indeed small, but ensures that we cannot have problems on machines with limited resources or custom configurations imposing strict limits to IPC resources. This default maximum message length is sufficient to send, for example, a file path, or other typical control messages. If a particular application of IPC requires more memory, the core application can be launched with two new command-line arguments:

Code:
--ipc-segment-size=<size>

      Set the size in bytes of the inter-process communication (IPC) segment. The
      valid range is [64KiB,1GiB]. The default IPC segment size is 64 KiB.

--ipc-index-length=<n>

      <n> is the length of the IPC message index. The minimum length is 16 and the
      maximum cannot exceed 1/4 of the IPC segment size. The default IPC message
      index length is 16.

The IPC message index is a dynamic data structure, allocated within the IPC segment, that allows receiving concurrent messages from more than one sender application. The default index length of 16 nodes is more than sufficient for most practical purposes.

_________________

Right now I cannot disclose more specific information, but successful experiments have already been done with new hardware control tools based on the new IPC functionality, and the results are promising. I hope more developers will find new opportunities of creativity thanks to this feature.
 
Back
Top