Contents

Class Process


Inheritance:

Object  »
  Link  »
    Process

A process represents an independent path of control in the system. This path of control may be stopped (by sending the message suspend) in such a way that it can later be restarted (by sending the message resume). When any one of several paths of control can be advanced, the single instance of ProcessorScheduler named Processor determines which one will actually be advanced.

Process is a subclass of Link. It is therefore possible to queue processes in a LinkedList as well as in a Semaphore.

A process lives in the Smalltalk image; it is not mapped to a process of your computer's operating system. It is not possible to associate a process with one of serveral processors of a multi-processor system.

Upon termination, a process unwinds its stack and evaluates the blocks of all ensure: and ifCurtailed: messages.

Instance Variables:

Process Creation

A process is always created from a block. The convenient shorthand to create a process is to send one of the messages fork, forkAt: to a block. These messages create a process that is immediately scheduled.

To simply create a new process and to obtain a reference to the new process, one sends the message newProcess to a block that is evaluated without arguments. To create a process from a block that is evaluated with arguments, one sends the message newProcessWith:.

Process States


Process states and state transitions

A process is always in one of these five states:

Process Termination

Two very different situations cause a process to terminate:

Process termination is a complicated operation that can include the finalization of blocks that are protected with either an ensure: or an ifCurtailed: block. A good understanding of process termination is required to avoid errors that are later difficult to find. Termination includes these steps:

  1. Termination of a process that is queued as either ready or blocked begins with the removal of the process from the queue. This is necessary to avoid activation or continuation of the process to be terminated.

  2. The call stack is unwound and all pending ensure: and ifCurtailed: blocks are evaluated.

ensure: and ifCurtailed: blocks are meant for cleanup operations. These blocks should have robust exception handling; ideally, they should catch all exceptions. It is recommended to avoid statements that could suspend process termination.

Example

reader := 
[  | stream |
 stream := 
   [FileStream readOnlyFileNamed: <filename>]
       on: Error
       do: [:exception | exception return: nil].
 stream notNil
   ifTrue:
     [[self processStream: stream]
        ensure: [stream close].
     ].
].

This example has both robust exception handling and termination-safe cleanup.

Here is an example for process termination:

  | sema process |

 sema := Semaphore new.

 process := 
  [ [sema wait.] ensure: 
	 [Transcript show: 'process is terminated'; cr]
  ] newProcess.

 process priority: Processor timingPriority;
         resume.

 Transcript show: 'queue length = ', sema size printString; cr.
 process terminate.
 Transcript show: 'queue length = ', sema size printString; cr.
 sema inspect.

The process process is given the highest priority; after resumption it runs until it enqueues itself into the queue of the semaphore. When this happened, the user interface process becomes active again and terminates the waiting process. During termination a message is written in the transcript window. Two additional transcript messages show that process termination removes a waiting process from the queue of the semaphore. The final inspect allows you to convince yourself that the semaphore is in fact left with an empty queue.


Contents