|
![]() |
![]() |
version 2003
An external process is a process that belongs to a plug-in, launched by the routine
PA_NewProcess
. The plug-in runs the process, takes care of its windows and menus, and interacts with the user if necessary. An external process can be invisible and/or can have no user interface.
4th Dimension allows the plug-in the possibility of creating this external process and then send it all events belonging to it if it has a user interface.
To create and manage an external process, the plug-in must execute the following instructions:
- Create the process, by calling PA_
NewProcess
, passing it a stack size, a process name, and a pointer to the routine that runs the process.
- Run the process code(see below) and interact with the user if necessary.
- Repetitively call
PA_IsProcessDying
to know if it must terminate
- Call
PA_KillProcess
when it has finished its work.
While writing an external process, the following actions MUST be performed:
· The routine of the process code has no parameters.
· At the very beginning of the code,
PA_YieldAbsolute
must be called. This allows the 4D scheduler to correctly handle the addition of the external process to its internal process table.
· If, as it should be, the external process includes a waiting loop :
- it must call
PA_WaitNextEvent
to get the current event returned (such as
mouseDown
). On Macintosh, it can use
GetNextEvent
instead, but for cross-platform purpose it is recommended to use
PA_WaitNextEvent
. Calling
PA_WaitNextEvent
is important, since this routine gives the hand to 4D for other processes. If the main loop of the external process never calls it, other processes will be frozen.
NOTE
If the external process has no user interface, the main loop can either call
PA_WaitNextEvent
or
PA_Yield
to give time for other running processes.
- it must call
PA_IsProcessDying
to see if the user or 4th Dimension wants the process to abort. If
PA_IsProcessDying
returns 1, the external process must exit the event loop as soon as possible and call
PA_KillProcess
.
Executing external processes receives 1 in
PA_IsProcessDying
when:
· The user chooses Quit , New Database , or Open Database from the 4D File menu
· The 4D command
QUIT 4D
is called,
· The routine
PA_Quit
is called.
· The user chooses "Abort" in the Runtime Explorer
The 4D scheduler takes control and tells the external processes that it must terminate. It waits for a predetermined period of time and then forcefully aborts any remaining executing processes . If the process is terminated because the database is closed, it is at this point that 4D will call the
kDeInitPlugin
or
kServerDeInitPlugin
phase of the 4D plug-in.
· Calling
PA_IsProcessDying
MUST be the last action performed by a terminating external process. This assures that the 4D scheduler is notified of the termination and updates its internal process table according.
· The 4D plug-in should NOT call any API's routine that would trigger the execution of a 4D command that displays a 4D Form from within the external process, such as
ADD RECORD
,
DISPLAY RECORD
,
DISPLAY SELECTION
,
MODIFY SELECTION
and
DIALOG
. Executing one of these 4th Dimension commands from within the external process may lead to a System Error.
· If the external process has user interface components it may open as many windows as is required. These windows belong to the external process and form the external processes' window list. For the cases where user interfaces components are required it is the responsibility of the 4D plug-in to set up its own menu bars. 4th Dimension automatically inserts the Apple (MacOS) or Help (Windows) menus.
The external process can be made invisible. For example, another process applying the 4D command
HIDE PROCESS
to the 4D plug-in process is valid. In such cases the visible field of the 4D plug-in window records are set to FALSE.
There are differences between Macintosh and Windows windows, as everyone knows.
If the programmer uses Macintosh routines and Altura Mac2Win to run its code under Windows, he can write its code "as usual" : the plug-in creates its windows and processes them into an event loop.
A Windows programmer can create and use windows and their WinProc as usual. 4th Dimension will give the correct event to winProc of the window that receive it. But remember that, as the windows were created from an external process and belongs to it, and not to 4th Dimension, this process must run the event loop that calls
PA_WaitNextEvent
and
PA_IsProcessDying
to keep a "reference" to the code that created the windows. There is no problem to add a winProc to the window by calling the Windows routine
SetWindowLong
.
Under MacOS, most of the Windows Manager routines are patched by 4th Dimension. In order to comply with the 4D multitasking environment the 4D plug-in must use them rather than directly accessing data structures or System Globals. For instance, the MacOS toolbox function call
FrontWindow
will return the front most window within the 4D plug-ins external process. Meanwhile, the System Global WindowList ($9D6) will contain a pointer to the front most window for the entire 4th Dimension active session.
In both cases, the programmer can use
PA_NewWindow
to create the window on both platform and insure that it will be added to the 4th Dimension application windows list.
Summary of an external process code
// No parameter, no returned value
// -----------------------------
void TheProcess (void)
{
PA_Event event;
char done = 0;
// Tell 4D the process exists and runs
// -----------------------------------
PA_Yield()
while(!done)
{
// Check if the loop must end
// --------------------------
done = PA_IsProcessDying();
// Get event/Give hand to other processes
// --------------------------------------
if( !done && PA_WaitNextEvent( &event ) )
{
/* . . . */
}
// NOTE PA_Yield() can be used instead of PA_WaitNextEvent if there is no user interface
}
// Last line of the code : tell 4D we we've finish
PA_KillProcess();
}
Example
Sample code of an external process without user interface. This is the skeleton of what should be done by every external process. In this sample, the external process loops until there are 8 processes running.
To run this process, the plug-in simply calls:
aProcessNum = PA_NewProcess(SampleProcess, (32 * 1024), "Sample process")
Here is the code of the process :
/* =======================================================
Code of the sample external process
This external process loops until 8 processes at least are running.
During its loop, the process MUST call PA_WaitNextEvent to give
hand to the 4D scheduler. If it does not that, the user will think
its machine has froze.
Note that :
- PA_WaitNextEvent will always returns 0 when there is no
user interface
- You can call PA_Yield instead (we use this in this sample)
======================================================= */
void SampleProcess ()
{
char done = (char) 0;
long myProcess;
// ______________________________________ 1st "must be done"
// Tell 4D to schedule us
PA_YieldAbsolute();
// Get our number
myProcess = PA_GetCurrentProcessNumber();
// Main loop
while (!done)
{
// ______________________________________ 2nd "must be done"
// Give time to other processes
PA_Yield();
// Sleep a little bit, say 5 seconds
PA_PutProcessToSleep(myProcess, 300);
// If we are dying, leave the loop
// ______________________________________ 3rd "must be done"
done = PA_IsProcessDying();
if(!done)
{
if( PA_CountActiveProcess() >= 8 )
{
PA_Alert("There are at least 8 active processes");
done = (char) 1;
}
}
}
// ______________________________________ 4th "must be done"
// At least, tell 4D we have finish
PA_KillProcess();
} /* SampleProcess */