eXept Software AG Logo

Smalltalk/X Webserver

Documentation of class 'Process':

Home

Documentation
www.exept.de
Everywhere
for:
[back]

Class: Process


Inheritance:

   Object
   |
   +--Link
      |
      +--Process
         |
         +--OSProcess::ShufflerProcess

Package:
stx:libbasic
Category:
Kernel-Processes
Version:
rev: 1.277 date: 2023/12/15 16:58:15
user: stefan
file: Process.st directory: libbasic
module: stx stc-classLibrary: libbasic

Description:


WARNING:
    the offsets of the instance variables lookupActivations and lookupDisabled are known in the VM
    do not remove them, and do not insert/remove instance variables before them

Instances of Process represent lightweight smalltalk processes
(i.e. threads). These all run in a shared smalltalk/X address space,
and can thus access and communicate via any objects.
Do not confuse these with (heavy-weight) unix processes, which are
created differently, and do NOT run in the same address space.
Also notice, that heavy-weight process creation takes much longer.
(see OperatingSystemclass>>fork).

Smalltalk processes do not necessarily need to be implemented as native
threads - it may, but the actual implementation depends on the underlying
OS's features. However, even if implemented as native thread, the ST/X
kernel makes certain, that only one thread executes at a time (with certain,
well-defined exceptions). The reason is that the required locking in the
runtime system would make things slower in most cases.

Processes are typically created by sending #fork or #forkAt: to a block;
the block creates a new process, defines itself as its startBlock,
and (optionally) tells the Processor about the new process.

Scheduling is done by Processor, which is the sole instance of ProcessorScheduler.
In ST/X, the scheduling algorithms are fully implemented (and visible) on the
smalltalk level - beside the threadSwitch primitive, there is virtually no VM
support (i.e. it can be easily changed).


Processes can be terminated either soft or via a hardTerminate.

A soft terminate (see Process>>terminate) will raise a TerminationSignal
in the process, which can be handled by the process.
If no other handler was specified, the processes own handler
(see Process>>start) will catch the signal and terminate the process.
During this signal processing, normal unwind processing takes place,
this means that with a soft terminate, all valueOnUnwind:/valueNowOrOnUnwind:
cleanup blocks are evaluated.
(so a process which has set up those blocks correctly does not have to
 care especially about cleanup in case of termination).
Other than that, the TerminateSignal can be caught for special cleanup or
even to make the process continue execution.
If the process is suspended at termination time, it will be resumed
in order to perform its cleanup actions (i.e. the cleanup is always
done in the context of the terminating process itself).

A hard terminate (Process>>terminateNoSignal) will NOT do all of the above,
but quickly (and without any cleanup) terminate the process.
The debugger offers a quickTerminate option on its popupMenu for
situations, when soft termination fails. (for example, if some error was
coded into a handler or unwind block).

Leaving the processes startBlock has the same effect as a soft-terminate
(i.e. there is no need to send an explicit terminate).

Notice:
    in Smalltalk/X, processes are gone, when an image is restarted;
    this means that you have to take care of process re-creation yourself.
    Usually, this is done by depending on ObjectMemory, recreating the
    process(es) when the #returnFromSnapshot-change notifiction arrives.

    All views (actually windowGroups) recreate their window process
    on image-restart. You have to do so manually for your own processes.

A later version will allow specification of automatic restart, but
that's not yet implemented. However, even when implemented, restartable processes
will be recreated to restart from the beginning. It will not be possible to
automatically continue a processes execution where it left off.
This is a consequence of the portable implementation of ST/X, since in order to
implement process continuation, the machines stack had to be preserved and
recreated.  Although this is possible to do (and actually not too complicated),
this has not been implemented, since the machines stack layout is highly machine/compiler
dependent, thus leading to much bigger porting effort of ST/X (which conflicts
with ST/X's design goal of being highly portable).

Process synchronization:
    Synchronization with cooperating processes is supported as usual,
    via Semaphores (see Semaphore, Delay, SharedQueue etc.)

    With uncooperative processes, only synchronization on suspend
    and termination is possible:
      any other process can wait for a process to suspend or terminate.
      This waiting is implemented by using suspendSemaphore and exitBlocks
      (where an exitSemaphore is signalled).
      See waitUntilSuspended / waitUntilTerminated.

Implementation note:
    for historic and compatibility reasons, Process is a subclass of Link,
    which means, that instances are directly usable as nodes in a linkedList.
    However, this also means that processes can only be elements of a single LinkedList.
    This is somewhat dangerous, as unknowledgable programmers may unwillingly break the
    scheduler, by placing a process onto another linked list.
    Therefore, we plan to change this in the future.

Process states:
    #dead           process has (been) terminated;
                    the process instance has no underlying
                    thread.

    #run            the process is willing to run,
                    but not active (i.e. another higher prio
                    process is currently executing)

    #active         the process is the current process
                    (there is only one)

    #ioWait         waiting on some io-related semaphore
                    (typically in #readWait / #writeWait)

    #eventWait      waiting on some GUI event

    #timeWait       waiting on a timer-related semaphore

    #wait           waiting on some (other) semaphore

    #suspended      stopped from execution; however, an interrupt
                    will return it into the run state.

    #stopped        stopped from execution; an interrupt will
                    NOT return it into the run state (for debugging)

    #debug          debugger sitting on top of the processes
                    stack.

Win32 only:

    #osWait         waiting on an OS-API call to finish.
                    can be interrupted, terminated and aborted
                    (i.e. the usual context actions are possible).

    #halted         thread was caught while in a blocking API call
                    or primitive endless loop and has been halted by
                    the scheduler.
                    Can only be resumed or hard-terminated - abort
                    or soft terminate or unwind actions are not possible.
                    (due to win32 limitations)


[Instance variables:]

    id                     <SmallInteger>   a unique process-id

    creatorId              <SmallInteger>   the id of the process that
                                            created me (useful for debugging
                                            or monitoring).

    processGroupId                          usually the id of the creator,
                                            unless the process detached from
                                            the group and became a groupLeader.
                                            Groups can be easily terminated
                                            as a whole.
                                            Group leaders have a groupId of nil.
                                            A groupId of 0 (zero) marks a system
                                            process; these do not prevent a standAlone
                                            app from exiting.

    prio                   <SmallInteger>   the processes priority

    priorityRange          <Interval>       the processes dynamic priority range
                                            (or nil)

    state                  <Symbol>         the processes state
                                            (for process-monitor)

    startBlock             <Block>          the startup-block (the one that forked)

    name                   <String-or-nil>  the processes name (if any)
                                            (for process-monitor)

    suspendSemaphore       <Semaphore>      triggered when suspend (if nonNil)

    restartable            <Boolean>        is restartable; if true, the process
                                            will be restarted when an image is
                                            restarted. Otherwise, it remains dead.
                                            Running processes cannot be continued
                                            at the point where leftOff after an
                                            image-restart.

    interruptActions       <Collection>     interrupt actions as defined by interruptWith:,
                                            performed at interrupt time

    exitActions            <Collection of Block>
                                            additional cleanup actions to perform
                                            on termination (if nonEmpty)

    emergencySignalHandler <Block>          can be used for per-process
                                            emergency signal handling

    interruptsDisabled     <Boolean>        flag if interrupts (as installed
                                            via #interruptWith:) are currently
                                            disabled. (i.e. on-hold).
                                            Interrupts will be delivered when
                                            reenabled.

    exceptionHandlerSet    <ExceptionhandlerSet>
                                            Handled by any process; allows for
                                            exceptionHandlers and query-answerers to
                                            be added/removed dynamically.

[Class variables:]

    TerminateSignal         <Signal>        signal used to terminate processes
                                            (should not be caught - or at least
                                             rejected in handlers).
                                            If caught and proceeded, a process
                                            cannot be terminated via #terminate.
                                            For hardTermination (in case of emergency),
                                            send it a #erminateNoSignal message.

    RestartSignal           <Signal>        signal used to restart a process.
                                            Can be caught in additional handler(s),
                                            to perform all kind of re-initialization.
                                            However, these handlers should reject,
                                            for the restart to be really performed.

copyright

COPYRIGHT (c) 1992 by Claus Gittinger All Rights Reserved This software is furnished under a license and may be used only in accordance with the terms of that license and with the inclusion of the above copyright notice. This software may not be provided or otherwise made available to, or used by, any other person. No title to or ownership of the software is hereby transferred.

Class protocol:

Signal constants
o  restartSignal
return the signal used for process restart

o  terminateSignal
return the signal used for process termination

defaults
o  defaultMaximumStackSize
return the default max stack size. All new processes get
this limit initially.
It may be changed for individual processes with:
aProcess setMaximumStackSize:limit

Usage example(s):

     Process defaultMaximumStackSize

o  defaultMaximumStackSize: numberOfBytes
set the default max stack size, return the previous value.
All new processes get this stack limit initially.
It may be changed for individual processes with:
aProcess setMaximumStackSize:limit
Notice:
There is seldom any need to change the default setting,
except for highly recursive programs.

Usage example(s):

     Process defaultMaximumStackSize:500*1024

o  wrapStackSize
return the wrap stack size.
Under windows, blocking API calls are executed on a separate stack with this size.
If you ever encounter that a call to n external library function requires more stack than
this, you may change this size in your startup (or programmatically) during early startup.
Returns nil on non-windows machines.

o  wrapStackSize: newSize
set the wrap stack size.
Under windows, blocking API calls are executed on a separate stack with this size.
If you ever encounter that a call to n external library function requires more stack than
this, you may change this size in your startup (or programmatically) during early startup.
An argument of 0 changes the size back to the default.
Returns the previous size.

initialization
o  initialize
(comment from inherited method)
called only once - initialize signals

instance creation
o  for: aBlock priority: aPrio
create a new (unscheduled) process which will execute aBlock at
a given priority, once scheduled. The process will start execution once
it gets a #resume-message.

o  new
create a new (unscheduled) process which will execute the start
method, when scheduled. The process will start execution once
it gets a #resume-message.

instance retrieval
o  findProcessWithId: id
return a process with a particular id.
This is only a debugging helper, to allow
easy access of a process by name in the MiniDebugger.
Do not use - ask Processor instead!

** This is an obsolete interface - do not use it (it may vanish in future versions) **

o  findProcessWithName: name
return a process with a particular name.
This is only a debugging helper, to allow
easy access of a process by name in the MiniDebugger
Do not use - ask Processor instead!

** This is an obsolete interface - do not use it (it may vanish in future versions) **

o  findProcessesWithGroupId: aGroupId
return a collection of processes with the particular group id.
Do not use - ask Processor instead!

** This is an obsolete interface - do not use it (it may vanish in future versions) **


Instance protocol:

Compatibility-Squeak
o  isTerminated
( an extension from the stx:libcompat package )
return true, if the receiver is a dead process

Compatibility-V'Age
o  queueInterrupt: aBlock
( an extension from the stx:libcompat package )
VisualAge compatibility: alias for #interruptWith:
arrange for the receiver process to be interrupted and
evaluate aBlock in its interrupt handler.

accessing
o  beGUIProcess
mark the receiver as a gui process.
This is currently not used, but allows end-user applications
to terminate all subprocesses which are GUI related, and leave
other background processes in the same process group untouched.

o  beGroupLeader
make the receiver a processGroupLeader.
This detaches the process from its creator, so that it will not
be terminated when it terminates via #terminateGroup.
Also, processes forked from a groupLeader belong to that group
and can be terminated via #terminateGroup - unless they become
group leaders themself.
(windowgroup processes do this).

o  beSystemProcess
make the receiver a system process.
These processes have a groupId of 0.
When executed as standAlone application, smalltalk exits when
no more user processes are running.
(i.e. when there are only systemProcesses left)
To prevent any daemon processes from preventing this exit,
you should make them systemProcesses

o  changePriority: aNumber
same as priority:, but returns the old priority.
(cannot do this in #priority: for ST-80 compatibility)

o  creatorId
return the process creator's id.
This has no semantic meaning, but is useful to identify processes
when debugging.

o  exceptionHandlerSet
retrieve the exceptionHandlerSet, which includes the set of
exceptions which are caught by the process.
Initially being empty, this allows for default handlers to be
dynamically added/removed from the set of handled exceptions/queries.

o  id
return the processes id

o  interruptsDisabled

o  name
return the processes name

o  name: aString
set the processes name

o  priority
return the receiver's priority

o  priority: aNumber
set my priority

o  priorityRange
return my dynamic priority range

o  priorityRange: anInterval
change my dynamic priority range

o  processGroupId
return the processes processGroup id.
Normally, when created, a processes creator id is taken and used
as the processGroup id.
When #terminateGroup is sent to a process, the process and all of its
group members are terminated together.

Processes can detach themself from the process group to prevent being
killed when the parent terminates (windowgroup processes do this).

o  processGroupId: aGroupLeadersProcessID
set the processes processGroup id.
Normally, when created, a processes creator id is taken and used
as the processGroup id.
When #terminateGroup is sent to a process, the process and all of its
group members are terminated together.

Processes can detach themself from the process group to prevent being
killed when the parent terminates (windowgroup processes do this).

o  restartable: aBoolean
set/clear, the restartable flag.
Restartable processes will automatically be restarted by the
ProcessorScheduler upon image restart.
Others have to be restarted manually.

o  setStateRun
set the state - only to be used from scheduler

o  singleStep: aBoolean

o  startBlock
return the processes startup-block

o  startTimestamp
return the processes' start time

o  state
return a symbol describing the processes state

o  state: aSymbol
set the state - only to be used from scheduler

o  suspendedContext
return the processes suspended context
- this is the context from which a process switch into the scheduler
or another process occurred.
For the active process, a dead process, or one which
had no chance to run yet, nil is returned.
Typically, only the debugger is interested in this one.

accessing-change notifications
o  addExitAction: aBlock
add aBlock to the processes exit actions.
This block will be evaluated right before the process dies,
and can be used to trigger actions somewhere else (i.e. synchronization).

o  addSuspendAction: aBlock
add aBlock to the processes suspend actions.
This block will be evaluated when a process gets suspended.
You may ask what that is useful for - it is useful to flush
buffered graphic commands of a GUI process (i.e. to force xlib
to send buffered commands to the display).

o  emergencySignalHandler
return the emergencySignalHandler block.
See Signal>>documentation for more info.

o  emergencySignalHandler: aOneArgBlock
set the emergencySignalHandler block.
See Signal>>documentation for more info.

o  removeAllExitActions
remove all exit actions.

o  removeAllSuspendActions
remove all suspend actions.

o  removeExitAction: anExitAction ifAbsent: exceptionBlock
remove the identical exitAction; if found, remove and return it;
if not, return the value from evaluating exceptionBlock

o  terminateActionBlock: aBlock
for compatibility with OSProcess,
this adds a block to be called when the process terminates

accessing-stack
o  maximumStackSize
returns the processes stack limit - i.e. the process will be
interrupted with a recursionSignal-raise, if it ever
needs more stack (in bytes) than this number

o  setMaximumStackSize: limit
sets the processes stack limit - i.e. the process will be
interrupted with a recursionSignal-raise, if it ever
needs more stack (in bytes) than this number.
Returns the old value.

o  setStackInitialSize: initial increment: increment safe: safe
hook for fine-tuning. Sets the processes initialStackSize- and
and stackIncrement-parameters. Not for normal use.

inspecting
o  inspectorExtraMenuOperations
( an extension from the stx:libtool package )
extra operation-menu entries to be shown in an inspector.
Answers a collection of pairs containing aString and action aBlock.
aString is the label of the menu item.
aBlock is evaluated when the menu item is selected.

o  raiseDebuggerOfProcess
( an extension from the stx:libtool package )
raise the debugger window, which is debugging me - if any

interrupts
o  blockInterrupts
disable interrupt processing for the receiver process
- if disabled, incoming interrupts will be registered and handled as
soon as interrupts are reenabled via unblockInterrupts.
Returns the previous blocking status i.e. true if interrupts
where already blocked. You need this information for proper
unblocking, in case of nested block/unblock calls.
This is similar to OperatingSystem>>blockInterrupts, but only
affects interrupts for the receiver process
(i.e. those which are installed via #interruptWith:)

Usage example(s):

     |p1|

     p1 := [
	     Transcript showCR:'disabled ...'.
	     Transcript showCR:Processor activeProcess blockInterrupts.
	     Transcript showCR:'busy ...'.
	     Delay waitForSeconds:10.
	     Transcript showCR:'enabled ...'.
	     Processor activeProcess unblockInterrupts.
	   ] forkAt:9.

     p1 interruptWith:[Transcript showCR:'interrupted'].

o  hasInterruptActions
return true, if there are any interrupt actions to evaluate
(i.e. if the receiver has been interrupted).

o  interruptWith: aBlock
interrupt the receiver and make it evaluate aBlock.
If the receiver is currently suspended it is resumed.
NOTE: the process (i.e. the receiver) will only perform the block immediately,
IFF its priority is higher than the priority of the currently running process.
Otherwise, it will remain suspended, until its time comes.

aBlock is evaluated with an optional argument: the context, that has been interrupted.

Usage example(s):

      |p|

      p := [
               [
                   10 timesRepeat:[
                       Delay waitForSeconds:0.5.
                       Transcript showCR:'looping...'
                   ]
               ] ensure:[
                   Transcript showCR:'aborted'
               ]
           ] fork.
      Delay waitForSeconds:2.
      p interruptWith:[:interruptedContext|
        Transcript showCR:e'interrupted ctx={interruptedContext}'
      ].
      Delay waitForSeconds:2.
      p interruptWith:[ AbortOperationRequest raise ].

Usage example(s):

you cannot interrupt an already finished thread..

     |p|

     p := [] fork.
     p waitUntilTerminated.
     p interruptWith:[Transcript showCR:Processor activeProcess].

o  onResumeDo: aBlock
prepare for the receiver to evaluate aBlock when resumed.
This is like #interruptWith:, but does not resume the receiver
(i.e. it continues its sleep).
This is useful to place a breakpoint on a sleeping process, to be fired
when it awakes.

o  stepInterruptHandler
get the handler for stepInterrupts occurring in the receiver process.
This is an interface for the debugger and allows it to monitor a threads
stepInterrupts. Returns the previous handler.
Not for general use.

Usage example(s):

     Processor activeProcess stepInterruptHandler

o  stepInterruptHandler: anObject
set the handler for stepInterrupts occurring in the receiver process.
This is an interface for the debugger and allows it to monitor a threads
stepInterrupts. Returns the previous handler.
Not for general use.

o  unblockInterrupts
enable interrupt processing for the receiver process
- if any interrupts are pending, these will be handled immediately.
When unblocking interrupts, take care of nested block/unblock
calls - you should only unblock after a blockcall if they where
really not blocked before.
This is similar to OperatingSystem>>unblockInterrupts, but only
affects interrupts for the receiver process
(i.e. those which are installed via #interruptWith:)

interrupts-private
o  addInterruptAction: aBlock asFirstAction: aBoolean
make the receiver evaluate aBlock when resumed/interrupted.
The name is somewhat misleading (actually, its historic):
the block is also evaluated on resume.
With asFirstAction, if another interrupt action is already pending,
aBlock will be executed first (to allow interrupting a debugged thread).

o  evaluateInterruptActionsWithContext: aContext
evaluate my interrupt-actions.

o  forceInterruptOnReturnOf: aContext
helper entry for debugger. Force a stepInterrupt whenever aContext
returns either directly or via an unwind.

o  interrupt
evaluate my interrupt-actions.
The process will go back to where it got interrupted
after doing this.

This is also sent by the VM.

o  interruptedIn: aContext
evaluate my interrupt-actions.
This is indirectly called by the VM, when some #interruptWith: action
was scheduled for the process, and the process is resumed.
The process will go back to where it got interrupted after doing this.

monitoring
o  numberOfStackBoundaryHits
internal monitoring only - will vanish

o  numberOfStackSegments
return the processes number of stack segments currently used.
This method is for monitoring purposes only - it may vanish.

o  totalStackSize
return the processes maximum used stack size.
This method is for monitoring purposes only - it may vanish.

o  usedStackSize
Return the processes current stack size.
This method is for monitoring purposes only - it may vanish.

o  vmTrace: aBoolean
turn on/off VM message tracing for the receiver.
This is meant for ST/X debugging, and may vanish.
Expect lots of output, once this is turned on.

obsolete
o  exitAction: aBlock
Obsoleted by addExitAction: / removeAllExitActions.

Add aBlock to the processes exit actions.
This block will be evaluated right before the process dies.
An argument of nil removes all exitActions.

** This is an obsolete interface - do not use it (it may vanish in future versions) **

o  suspendAction: aBlock
Obsoleted by addSuspendAction: / removeAllSuspendActions.

Add aBlock to the processes suspend actions.
This block will be evaluated when a process gets suspended.
A nil argument removes all suspendActions.

** This is an obsolete interface - do not use it (it may vanish in future versions) **

o  terminateAllSubprocesses

** This is an obsolete interface - do not use it (it may vanish in future versions) **

o  terminateWithAllSubprocesses

** This is an obsolete interface - do not use it (it may vanish in future versions) **

printing & storing
o  printOn: aStream
a little more info in my printed representation

private
o  for: aBlock priority: aPrio
setup the new process - the receiver is not scheduled for
execution, to get it running, send it #resume

private-scheduler access
o  setId: idNumber state: stateSymbol
set id and state - not for public use

o  setPriority: aNumber
set priority without telling processor - not for public use

o  setPriorityRange: anInterval
set priority without telling processor - not for public use

o  setStartBlock: aBlock
set the receiver's startup block

o  setStateTo: newState if: oldState

o  setStateTo: newState if: oldState1 or: oldState2

queries
o  isActive
return true if I am the active process

o  isAlive
return false, if the receiver is a dead process

o  isDead
return true, if the receiver is a dead process

o  isDebugged
return true, iff the receiver process is currently being debugged
(i.e. is stopped and a debugger sits on top of it)

o  isDebuggedOrStopped
return true, iff the receiver process is currently being stopped
and possibly debugged (i.e. is stopped and a debugger sits on top of it)

o  isDebuggerProcess
return true, iff the receiver process is currently running a Debugger or
an Inspector. Senders may behave differently and e.g. timeout on
endless blocking operations.

o  isGUIProcess
return true, if this is a GUI process.
I.e. a windowGroup process.
This is currently not used, but allows end-user applications
to terminate all subprocesses which are GUI related, and leave
other background processes in the same process group untouched.

o  isRestartable
return true, iff the receiver is restartable

o  isRunning
return true, iff the receiver is running (state == #run);
this does not mean that it is currently active
(it might be suspended by the current process)

o  isSingleStepping

o  isStopped
return true, iff the receiver is stopped

o  isSystemProcess
return true if aProcess is a system process,
which should not be suspended/terminated etc..

o  isUserProcess
return true if aProcess is a user process.

o  nameOrId
return a string to identify the process - either name or id

o  parentProcess
answer my parent.
Notice: we do only keep the id here, to prevent the parentProcess from being
referenced (and therefore not garbage collected if it terminates)

Usage example(s):

     Processor activeProcess parentProcess

o  processGroupLeader
answer the parent of this process group

Usage example(s):

      Processor activeProcess processGroupLeader

special
o  externalLookupPopIfEqual: lookupObject
Called by method lookup MOP when an lookup context is to be unwound
to cleanup lookup stack

o  millisecondDelay: millis
suspend the current process for some time.
Attention:
If the receiver is a system process (i.e. scheduler or event dispatcher)
this blocks the whole Smalltalk for the time delta;
if it's a normal thread, only that thread is suspended.

o  trapRestrictedMethods: trap
Allow/deny the execution of restricted methods.
Process specific method restriction is not implemented yet, so this call is
redirected to ObjectMemory and causes a system wide restriction.

Notice: method restriction is a nonstandard feature, not supported
by other smalltalk implementations and not specified in the ANSI spec.
This is EXPERIMENTAL - and being evaluated for usability.
It may change or even vanish (if it shows to be not useful).

Usage example(s):

	Processor activeProcess trapRestrictedMethods:true
	Processor activeProcess trapRestrictedMethods:false

o  uninterruptablyDo: aBlock
execute aBlock with interrupts blocked.
This does not prevent preemption by a higher priority processes
if any becomes runnable due to the evaluation of aBlock
(i.e. if a semaphore is signalled there).

o  waitUntilSuspended
wait until the receiver is suspended.

o  waitUntilTerminated
wait until the receiver is terminated.
This method allows another process to wait till the receiver finishes.

Usage example(s):

     |p|

     p := [100 timesRepeat:[1000 factorial]] forkAt:4.

     Transcript showCR:'now waiting ...'.
     p waitUntilTerminated.
     Transcript showCR:'done.'

o  waitUntilTerminatedWithTimeout: secondsOrNilOrTimeDuration
wait until the receiver is terminated or (if non-nil) until
the time period exired.
Returns true if a timeout occurred.
This method allows another process to wait until the receiver finishes
(optionally) within some time.

Usage example(s):

     |p|

     p := [10 timesRepeat:[10000 factorial]] forkAt:4.

     Transcript showCR:'now waiting ...'.
     (p waitUntilTerminatedWithTimeout:2) ifTrue:[
         Transcript showCR:'timeout occurred.'
     ]

o  withHigherPriorityDo: aBlock
execute aBlock at a higher priority.

Usage example(s):

     Processor activeProcess withHigherPriorityDo:[3000 factorial]

o  withLowerPriorityDo: aBlock
execute aBlock at a lower priority. This can be used to perform
time-consuming operations at a more user-friendly priority.

Usage example(s):

     Processor activeProcess withLowerPriorityDo:[3000 factorial]

o  withPriority: aPrio do: aBlock
execute aBlock at another priority. This can be used to perform
time-consuming operations at a more user-friendly priority,
or some critical action at a higher priority. Do not use too high
of a priority to avoid locking up the system (event processing takes place
at 24)

Usage example(s):

     Processor activeProcess withPriority:7 do:[3000 factorial]

Usage example(s):

be careful - even ^C wont work until done:
     Processor activeProcess withPriority:25 do:[3000 factorial]

o  withPriority: lowPrio to: highPrio do: aBlock
execute aBlock at a priority range. This can be used to perform
time-consuming operations at a more user-friendly priority,
or some critical action at a higher priority. Do not use too high
of a priority to avoid locking up the system (event processing takes place
at 24)

Usage example(s):

     Processor activeProcess withPriority:7 to:8 do:[3000 factorial]

o  withSystemBackgroundPriorityDo: aBlock
execute aBlock at system background priority.
This can be used to perform
background operations at a more user-friendly priority.

Usage example(s):

     Processor activeProcess withSystemBackgroundPriorityDo:[3000 factorial]

o  withUserBackgroundPriorityDo: aBlock
execute aBlock at background priority. This can be used to perform
time-consuming operations at a more user-friendly priority.

Usage example(s):

     Processor activeProcess withUserBackgroundPriorityDo:[3000 factorial]

start & stop
o  imageRestart
restart the process from the beginning.
This is sent by the ProcessorScheduler at image restart time,
to all restartable processes.

o  restart
restart the process from the beginning.
This is only possible, if it's restartable.

o  start
start the process - this is sent by the VM to the process to get
the process up and running.
Sending #start to the process (instead of directly executing the startBlock)
allows more flexible handling of processes, since anything that responds
to #start can be handled transparently by the VM then ...

Usage example(s):

save block for possible restart

Usage example(s):

startBlock := nil

o  terminate
terminate the receiver process.
Termination is done by raising the terminateSignal in the receiver process,
which can be caught.
If the process is stopped, it will be resumed so that it can die.
All unwind actions and the exit-actions (if any)
will be performed before the process is really terminated.
Notice, that the terminate actions are performed by the receiver,
at its current priority. Therefore, in case higher prio processes are
running, it may take any arbitrary time until the termination is eventually
done.

o  terminateAllGUISubprocesses
terminate all the receiver's gui subprocesses and their children as well
(i.e. all processes which are offsprings of the receiver, except for
the receiver itself).

o  terminateAllSubprocessesInGroup
terminate all subprocesses which have the receiver process as groupID,
and their group-children as well.
That is all processes which have been directly or indirectly created
by the current process
(i.e. all processes in the receiver's process group, except for the receiver itself,
and recursively all of their group processes).

o  terminateAllSubprocessesInGroup: aGroup
terminate all subprocesses which have aGroup as groupID,
and their group-children as well
(i.e. all processes in the receiver's process group, except for the receiver itself,
and recursively all of their group processes).

o  terminateGroup
terminate the receiver with all of its created subprocesses
that are in the receiver's process group.

o  terminateNoSignal
hard-terminate the receiver process without sending a terminateSignal
or performing any unwind-handling.
However, exit-actions are performed.
This is useful in case of emergency, when a buggy terminationHandler
prevents you from getting a process to terminate.
Processes always perform this method when terminating - either normally or abnormally.

o  terminateSubprocesses
terminate all the receiver's subprocesses
(i.e. all processes in the receiver's process group, except for
the receiver itself).

o  terminateWithAllGUISubprocesses
terminate the receiver with all of its created gui subprocesses and their gui children.

o  terminateWithAllSubprocessesInGroup
terminate the receiver with
all subprocesses which have the receiver's process ID as groupID,
and their group-children as well.
(i.e. the receiver plus all processes in the receiver's process group,
and recursively all of their group processes).

o  terminateWithException: aTerminateException
terminate the receiver process.
Termination is done by raising aTerminateException in the receiver process,
which can be caught.
If the process is stopped, it will be resumed so that it can die.
All unwind actions and the exit-actions (if any)
will be performed before the process is really terminated.
Notice, that the terminate actions are performed by the receiver,
at its current priority. Therefore, in case higher prio processes are
running, it may take any arbitrary time until the termination is eventually
done.

suspend & resume
o  abort
raise an AbortOperationRequest in the receiver process.
Most processes willing to handle this will return to some save state
(typically, some kind of event loop).
If not handled, this will result in termination of the process.

o  resume
resume the receiver process

o  resumeForSingleSend
resume the receiver process, but only let it execute a single send.

o  stop
suspend the receiver process - will continue to run when a resume is sent.
A stopped process will not be resumed for interrupt processing.

o  suspend
suspend the receiver process - it will continue to run when a resume is sent.
Notice, that an interrupt will also resume the receiver,
so any waiting code should be prepared for premature return from
a suspend (see wait code in Semaphore).
Use #stop for a hard-suspend, which is not affected by interrupts.

o  suspendWithState: aStateSymbol
like suspend, this suspends the receiver process until a resume is sent.
This sets the state to the argument, aStateSymbol, which is shown
in the ProcessMonitor (instead of #suspended).
(i.e. no new functionality, but a bit more debuggability)
Notice, that an interrupt will also resume the receiver,
so any waiting code should be prepared for premature return from
a suspend (see wait code in Semaphore).
Use #stop for a hard-suspend, which is not affected by interrupts.
Should be called with interrupts disabled.

thread local storage
o  environment
return the dictionary holding thread local variables, or nil if there are none

o  environment: aDictionary
set the dictionary holding thread local variables, or nil if there are to be none

o  environmentAt: aKey
return the value of a thread local variable, or raise an error, if no such variable exists

o  environmentAt: aKey ifAbsent: aBlock
return the value of a thread local variable, or the value of defaultValue if no such variable exists

o  environmentAt: aKey put: aValue
set the value of a thread local variable. Returns aValue

o  environmentIncludesKey: aKey
true if there is a thread local variable, false if no such variable exists

o  stderr
the processes stderr.
By default, this is Stderr, but it can be overwritten
(for example to redirect a thread's error output to some other place

Usage example(s):

     Processor activeProcess stderr

o  stdin
the processes stdin.
By default, this is Stdin, but it can be overwritten
(for example to redirect a thread's input from some other place

o  stdout
the processes stdout.
By default, this is Stdout, but it can be overwritten
(for example to redirect a thread's output to some other place

o  threadVariableValueOf: aKey
return the value of a thread local variable,
or nil if no such variable exists

o  transcript
the processes transcript.
By default, this is Transcript, but it can be overwritten
(for example to redirect a thread's output to some other place

o  withThreadLocalVariables: aDictionary do: aBlock
evaluate a block with threadLocalVariables from aDictionary;
restore the old bindings afterwards.

o  withThreadVariable: variableNameSymbol boundTo: aValue do: aBlock
evaluate a block with the threadLocalVariable being bound to aValue;
undo the variable binding afterwards.

Usage example(s):

     |printIt|

     printIt := [
		    Transcript
			showCR:'foo is now ',
			(Processor activeProcess threadVariableValueOf:#foo) printString
		].

     Processor activeProcess
	 withThreadVariable:#foo
	 boundTo:1234
	 do:[
	    printIt value.
	    Processor activeProcess
		withThreadVariable:#foo
		boundTo:2345
		do:[
		    printIt value
		].
	    ]


Examples:


start a background process, computing 1000 factorial 100 times; the processes priority is set to not disturb any interactive process. Since its prio is higher than the 3D animation demos prio, you will notice, that those are suspended while the computation runs. But Interactive views (like browsers) will continue to react normal.
[
   'starting' printNL.
   100 timesRepeat:[1000 factorial].
   'done with factorial' printNL.
] forkAt:(Processor userBackgroundPriority).
start a background process, computing 1000 factorial 100 times; the processes priority is set to not disturb any process. The prio is set to 1 (which is the lowest possible) notice that now, the 3D animation demos also continue to run.
[
   'starting' printNL.
   100 timesRepeat:[1000 factorial].
   'done with factorial' printNL.
] forkAt:1.
start a background process, reading a pipe without blocking other processes;
[
   |p|

   'starting' printNL.
   p := PipeStream readingFrom:'ls -lR .'.
   [p atEnd] whileFalse:[
       p readWait.
       p nextLine printNL.
   ].
   p close.
   'done with pipe' printNL.
] forkAt:1.
see more examples in doc/coding (or search in the browser for senders of fork*)

ST/X 7.7.0.0; WebServer 1.702 at 20f6060372b9.unknown:8081; Sun, 22 Dec 2024 03:12:52 GMT