APLProcess
| Repository | https://github.com/dyalog/APLProcess |
| Copyright | Made with Material for MkDocs. Contents copyright ©2015-2024 Dyalog, LTD |
Overview
APLProcess is a cross-platform utility that enables you to easily start additional processes running Dyalog APL. This can be useful in a number of scenarios including:
- to distribute the processing load across multiple processors. This is what the isolate workspace does.
- to delegate processing to another process so that if there is some sort of failure, the primary process is not impacted.
APLProcess runs on Windows, Linux and MacOS. ssh support, which will enable you to start an APL process on another platform using the ssh protocol, is forthcoming.
Terminology
- Parent Process
- This is the process from where
APLProcessis used to start "child" processes. - Child Process
- This is a process started by a "parent" process. Each child process has a reference back to the "parent" process in the form of a "parent process ID" (PPID).
Note
While APLProcess itself is ⎕IO and ⎕ML insensitive, the examples in this documentation assume an environment of (⎕IO ⎕ML)←1.
Obtaining APLProcess
APLProcess is included with your Dyalog APL installation. To bring it into your workspace:
Dyalog APL Version 19.0 and later (using Link)
]import [ns] APLProcess
or, under program control, do:
⎕SE.Link.Import [ns] 'APLProcess'
where ns is an optional namespace name or reference in which to load APLProcess. If ns is not specified, APLProcess will be loaded into the current namespace.
Dyalog APL versions before 19.0 (using SALT)
]load APLProcess [-target=ns]
or, under program control, do:
⎕SE.SALT.Load 'APLProcess [-target=ns]'
-target=ns optionally specifies the namespace in which to load APLProcess where ns is the namespace name. If not specified, APLProcess will be loaded into the current namespace.
Upgrading to the Latest APLProcess
The documentation describes the latest released version of APLProcess which may be more recent than the version that came pre-installed with your Dyalog APL. Use APLProcess.Version to check the APLProcess version number.
The latest released version of APLProcess can be downloaded from the Assets section of the latest release page on GitHub.
APLProcess is Available as a Tatin Package
Tatin is a package manager for APL-based packages. APLProcess is available as a Tatin package. If you have the Tatin client installed, you can load APLProcess using:
]TATIN.LoadPackages APLProcess
The Tatin client will be included in your Dyalog installation beginning with Dyalog version 19.0. For earlier versions of Dyalog, refer to the Tatin website for instructions on installing the Tatin client.
User Guide
APLProcess starts a new Dyalog APL interpreter in another process. What that process does is entirely up to you. Common uses include:
- setting up a Remote Procedure Call (RPC) service to distribute processing load between multiple APL processes.
- delegating a long-running task to another APL process
- delegating processing to another APL process to reduce the potential impact of code failure. If the code running in another process fails, it's less likely to impact the processing in the current APL session.
Note
Currently APLProcess can start new APL processes only on the same platform. As most processors have multiple cores, this can still help distribute processing load and increase throughput. The ability to start new APL processes on other platforms using ssh is under development.
Terminology
Even though APLProcess is implemented as a Dyalog APL class, you do not need to know much about the object-oriented programming (OOP) features of Dyalog APL.
- Instance
- An "instance" of
APLProcessis created when you callAPLProcess.Newor the use the⎕NEWsystem function. Instances are independent of one another. - Method
- In OOP terminology, APL functions within classes are called "methods". An individual method can either apply only to an instance (this is called an "instance method"), or to the class itself (this is called a "shared method").
- Field or Setting
- In OOP terminology, variables are called "fields", but for this documentation, we'll refer to them as "settings".
Throughout this document we will use the following terms with the following meanings:
- Parent Process
- This is the process from where
APLProcessis used to start "child" processes. - Child Process
- This is an APL process started by a "parent" process. Each child process has a reference back to the "parent" process in the form of a "parent process ID" (PPID).
p- An instance of
APLProcesswhich is the result of runningAPLProcess.Newor using⎕NEW. Of course, you can use whatever name you prefer in your code.
Creating and starting APLProcess
There are three ways to create and run an instance of APLProcess.
Use ⎕NEW with constructor arguments
This will start an APL process and return an APLProcess instance.
p←⎕NEW APLProcess ('/myApp' '' 0 'SERVE:*:4502')
Use ⎕NEW without constructor arguments
This will create and return an instance of APLProcess. You can then set whatever parameters you need and start the APL process using the Run method.
p←⎕NEW APLProcess
p.(Ws RideInit)←'/myApp' 'SERVE:*:4502'
p.Run
Use APLProcess.New
APLProcess.New is a shared method that will create and return an instance of APLProcess, applying any arguments as parameters. You can then start the APL process using the Run method.
Supplying '' as the argument to APLProcess.New is equivalent of using ⎕NEW APLProcess without any arguments.
p←APLProcess.New '/myApp' '' 0 'SERVE:*:4502'
p.Run
Stopping an APL Process
Use p.Kill to terminate the child APL process. p.kill will return 1 if the child process was successfully terminated, 0 otherwise.
Checking if an APL Process is Running
Use p.HasExited to check if a child process is running. p.HasExited will return 1 is the child process is not running and 0 if the child process is running.
Cross-Platform Functionality
To the extent possible, APLProcess presents a consistent API across all platforms on which Dyalog APL runs. This way you shouldn't have to change your application code that uses APLProcess if you're using multiple platforms.
Once the child process has been started, the APLProcess instance contains an object named Proc. Under Windows, Proc is an instance of the .NET System.Diagnostics.Process class. On non-Windows platforms, Proc is a namespace with elements named the same as a selected subset of the features of the .NET class.
Reference
APLProcess Instance
You create an instance of APLProcess using either ⎕NEW or APLProcess.New as described in the Creating and Starting APLProcess.
Settings
APLProcess's settings can be provided as arguments to APLProcess.New or ⎕NEW. You can also specify settings in the APLProcess instance before launching the new process. When provided as arguments, the settings can be specified in two ways.
- A vector of positional settings in the following order:
Ws Args RunTime RideInit OutFile WorkingDir Detach
If you want to supply settings with intermediate unspecified setting, you will need to supply the default value for the intermediate settings. For example, to specify theWsandRideInitsettings, you would need to specify/myApp '' 0 'SERVE:*:4502, using the default values forArgsandRunTime. - A namespace containing named variables for the settings you wish to set.
ns←⎕NS ''
ns.(Ws RideInit)←'/myApp' 'SERVE:*:4502'
p←APLProcess.New ns
Note
Remember that using ⎕NEW with arguments, in either positional or namespace form, will start the APL process automatically.
Ws
| Description | Ws is the name of the workspace that the child process will load |
| Default | '' |
| Examples | p.Ws←⎕WSID ⍝ have the child process load the current workspace |
| Notes | An alternative to specifying Ws could be to use the Load and LX command line parameters. If you specify neither Ws nor the Load/LX command line parameters, the child process will sit there, languishing and doing nothing. |
Args
| Description | Args is a character vector which represents the Dyalog command line parameters, if any, to be passed to the interpreter in the child process. |
| Default | '' |
| Examples | p.Args←'Load=/myApp LX=Start' ⍝ load code from the /myApp folder and run the Start function |
RunTime
| Description | RunTime allows you to control the Dyalog interpreter that the child process will run. RunTime can have the following values:
|
| Default | 0 meaning do not use a runtime interpreter. |
| Examples | p.RunTime←1 ⍝ use a runtime interpreterp.RunTime←'/opt/mdyalog/19.0/64/unicode/dyalog' ⍝ use a specific interpreter |
| Notes | RunTime is a somewhat overloaded setting that has evolved over time to take on additional meanings other than just whether to use a runtime interpreter. There is a pending capability to use RunTime to specify parameters in order to start an APL process on another maching using ssh, but that functionality is currently under development. |
RideInit
| Description | RideInit specifies the RIDE_INIT command line parameter to use if you want to be able to RIDE into the child process's APL session. RideInit can be either:
4504 would be the equivalent of specifying 'SERVE:*:4504' |
| Default | '' which means RIDE access is not enabled for the child process |
| Examples | p.RideInit←4504 ⍝ run with SERVE:*:4504p.RideInit←'HTTP:*:4504 ⍝ run with zero-footprint RIDE on port 4504 |
| Notes | APLProcess will always set the RIDE_INIT command line parameter in order to not inherit the setting from the parent APL process. |
Load
| Description | Load specifies the LOAD parameter for the child process. Load specifies the workspace, folder, or file to be loaded and run by the child process. Load, if specified, overrides the workspace specified by Ws. |
| Default | '' |
| Examples | p.Load←'/home/user/myapp' |
| Notes | APLProcess will always set the LOAD command line parameter in order to not inherit the setting from the parent APL process. |
Lx
| Description | Lx specifies the LX parameter for the child process. Lx, if specified, overrides ⎕LX in the workspace, if a workspace is either specified by Ws or Load. |
| Default | '' which means that the child process will inherit the LX parameter, if any, set for the parent process. |
| Examples | p.Lx←'Start' |
| Notes | If LX is set for the parent process and Lx is not specified for the child process, the child process will inherit the parent's setting. This is likely to not be what you want. |
OutFile
| Description | OutFile specifies the name of a file to which the session output of the child APL process will be written. |
| Default | '' meaning session output will not be written to file. |
| Examples | p.OutFile←'/home/me/Desktop/output.txt' |
WorkingDir
| Description | WorkingDir specifies the working directory for the child APL process |
| Default | '' meaning use the default working directory for the child process's APL interpreter |
| Examples | p.WorkingDir←'/home/me/Desktop' |
Detach
| Description | Detach is a Boolean which indicates whether child process(es) should be terminated when the parent APLProcess instance is expunged.0 indicates that the child process(es) should be terminated.1 indicates that the child process(es) should not be terminated. |
| Default | 0 |
| Examples | p.Detach←1 ⍝ do not close the child APL process when the parent's APLProcess instance is expunged. |
| Notes | If Detach is set to 0, the child APL process will be terminated if the parent APL process exits; when set to 1 the child process will continue to run even if the parent APL process exits. |
Id
| Description | Id is a read-only setting that returns the process ID of the child APL process. If the child APL process has not been started, Id is set to ''. |
| Default | '' |
| Examples | (p←APLProcess.New '/myApp' '' 0 4505).Run0p.Id18212 |
Proc
| Description | Proc is not really a setting but rather an attempt to present consistent cross-platform interface. Proc is created when the child APL process is started.On Windows Proc is an instance of the .NET System.Diagnostic.Process class which has many more properties and methods than we expose in APLProcess.On non-Windows platforms, Proc is a namespace which emulates a subset of the System.Diagnostic.Process class which we deem necessary to start and manage the child APL process. |
Methods
Run
| Description | Run starts the child APL process. |
| Syntax | (rc msg)←p.Run where rc and msg are 0 and '' respectively if no error occurred when starting the child APL process; otherwise rc and msg are the APL error number and message. |
| Examples | (ns←⎕NS '').(Ws RideInit)←'/myApp' 4505p←APLProcess.New ns ⍝ load /myApp and RIDE on port 4505p.Run1 |
Kill
| Description | Kill will attempt to terminate the child APL process. |
| Syntax | r←p.Kill where r is 1 if the child APL process was terminated, 0 if the child APLProcess is still running |
| Examples | p←⎕NEW APLProcess ('myApp' '' 0 4505)p.Kill1 |
HasExited
| Description | HasExited reports whether the child APL process is running |
| Syntax | r←p.HasExited where r is a Boolean where 1 indicates the child process is not running, 0 indicates the child process is running. |
| Examples | p←APLProcess.New '/myApp' '' 0 4505r.Run1p.HasExited0p.Kill1p.HasExited1 |
Samples
Sample Uses
Remote Procedure Call (RPC)
The sample RPC application is located in the /samples/rpc folder. The basic flow for the RPC application is:
- Load the
rpcworkspace. - Run
Startto start a child process which also loads therpcworkspace and starts a Conga "command mode" server. - After a brief pause to allow the RPC server to come up, connect to the server.
- Use
Doto send statements to the RPC server to be executed. Doreturns a 2-element vector.- The first element is the
⎕DMfor the error, if any, caused by executing the statement. If no error occurred,''is returned. - The second element is the result of executing the statement, if no error has occurred in doing so, otherwise the offending statement is returned.
- The first element is the
- Use
Stopto stop the RPC server and tidy up the client environment.
These steps are seen below (]BOX on is used to show the structure of results):
)load /git/APLProcess/samples/rpc/rpc
/git/APLProcess/samples/rpc/rpc.dws saved ...
Sample Remote Procedure Call (RPC) application demonstrating the use of APLProcess
Use Start '' to start the application with default settings.
Start ''
┌─┬────────────────────────────────────┐
│0│Connected to RPC Server on port 8888│
└─┴────────────────────────────────────┘
Do '⍳3 3'
┌┬─────────────┐
││┌───┬───┬───┐│
│││1 1│1 2│1 3││
││├───┼───┼───┤│
│││2 1│2 2│2 3││
││├───┼───┼───┤│
│││3 1│3 2│3 3││
││└───┴───┴───┘│
└┴─────────────┘
Do '÷0'
┌────────────┬──┐
│DOMAIN ERROR│÷0│
│÷0 │ │
│∧ │ │
└────────────┴──┘
Stop
RPC Client closed and expunged
RPC Server process terminated
Conga shared library unloaded and Conga was erased
The relevant lines in Start which use APLProcess are shown below:
⍝ create and configure the instance of APLProcess
RPC_Process←APLProcess.New''
RPC_Process.Ws←⎕WSID ⍝ workspace to load
RPC_Process.Args←'RPC_Port=',⍕port ⍝ port to use
RPC_Process.Args,←' RPC_Threaded=',⍕threaded ⍝ run the server in a thread in the child process?
RPC_Process.RunTime←runtime ⍝ use runtime interpreter?
RPC_Process.RideInit←''(port+1)rideable⊃⍨0 1⍸rideable ⍝ RIDE port
RPC_Process.Detach←~detach ⍝ don't kill child process when p goes away
⍝ try to launch the child process
:If 0≠⊃(rc msg)←RPC_Process.Run
msg←'Failed to start APL process due to: ',∊⍕msg
→0
:EndIf
⎕DL 2 ⍝ pause to let child process initialize
:If ~RPC_Process.HasExited ⍝ check to make sure the child process is there
:If 0=⊃rc←RPCClt.Clt'RPCClient' 'localhost'port'Command'
msg←'Connected to RPC Server on port ',⍕port
msg,←rideable/(⎕UCS 13),'RIDE available on port ',⍕1+port
rc←0
:Else
msg←'Could not connect to RPC Server on port ',(⍕port),' due to ',∊⍕(4↑rc)[1 3 4]
:EndIf
:EndIf
About
MIT License
Copyright (c) 2024 Dyalog
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Release Notes
Version 2.4
- Added
LoadandLxparameters
Version 2.3
- First version of
APLProcessresiding in its own repository. - Added
Idproperty - Allow a namespace as constructor argument