2.13.11Class Thread

Parallel agent main class.

Class Thread from \
                 Waitable( )

The Thread class controls the execution of parallel agents in the Falcon threading model.

The applicaiton willing to launch parallel agents should either derive the logical agent from the Thread class, or assign the run method of a Thread instance to a function of choice.

In example, both the following methods are valid:


      class MyThread from Thread
         function run()
            > "Hello from the thread"
         end
      end

      function parallel( param )
         > "Parallel called from another thread with ", param
      end

      // launching a thread using OOP inheritance...
      mt = MyThread()
      mt.start()

      // ... or using functional overload
      th = Thread()
      th.run = [parallel, "A parameter" ]
      th.start()

The static method Threading.start can be used to call an arbitrary function without encapsulating it in a Thread instance. The Threading class provides a set of static methods that can be used both by Thread instances and plain parallel code which has not been encapsulated in a instance of a class derived from Thread.

The Thread.start method will create a new system thread and a new Virtual Machine, configured as the machine in which it was called, but completely empty. The instance that is going to be started will be copied (via serialization) to the new Virtual Machine, and if the operation can be completed, the new Virtual Machine will execute the Thread.run method of the transferred instance.

As the new copy of the VM is clean, global objects and results of former elaboration in the calling VM are not available to the newborn thread, unless they are passed as members of the derived class or as parameters of the run deferred call.

This means that any synchronization structure needed for the thread must be set in the thread subclass instance (or in the parameters of the deferred call to run) before the thread is started. If provided with suitable structures that can transfer data to different threads, more data can be exchanged at a later time.

Methods
detachDisengage this threads from waits and garbage.
detachedReturns true if the target thread is detached.
getErrorGet the error that cause a thread to terminate, if any.
getNameSets the symbolic name of this thread.
getReturnGet the return value that was returned by the thread main function.
getSystemIDGets the system low level thread ID for this thread.
getThreadIDGets an unique numeric ID for this thread.
hadErrorReturns true if the target thread was terminated because of an uncaught raised item.
joinWaits for a thread to terminate and returns its return value.
runOverloading hook that will hold the thread main function.
sameThreadReturns true if the givevn thread is running the same thread as this object.
setNameSets the symbolic name of this thread.
startLaunches the thread in a parallel environment.
stopInterrupts the target thread.
terminatedReturns true if the target thread is terminated.
toStringReturns a string representation of this thread.
vwaitWait for one or more synchronization strucures to become available.
waitWait for one or more synchronization strucures to become available.
Methods inherited from class Waitable
releaseReleases a structure acquired by a waiting function.

Methods

detach

Disengage this threads from waits and garbage.

Thread.detach()

This method sets the thread for which it has been called in "detached" status. This means that the thread will just run in background for the rest of the application life, or for how long it needs, and the main application doesn't want to be notified about the thread termination, nor to control its behavior anymore.

The net effect is that the thread is free to run as long as the application is alive. The VM running the thread is not bound anymore to the calling VM, and stopping and destroying the calling VM will have no effect on the thread.

Normally, when the thread object is garbage collected, or when the calling VM is destroyed and its garbage freed, the collector joins the system thread before destroying the Falcon thread instance. In other words, the destructor will wait for the target thread to terminate naturally.

By detaching the thread, the caller signals that it doesn't want to use this thread object anymore, and that the system thread associated with this instance is free to run beyond the lifetime of this Falcon item.

As a side effect, it is not anymore possible to join this thread; threads eventually waiting for this thread to end will receive a JoinError, as threds trying to wait for its termination after that detach has been called.

The detached state is not reversible. Once detached, a thread is left to its own destiny. However, it's still possible to communicate to it through synchronization structures and through methods in this instance, as i.e. Thread.stop.

detached

Returns true if the target thread is detached.

Thread.detached()
ReturnTrue if the thread has been detached, false otherwise.

getError

Get the error that cause a thread to terminate, if any.

Thread.getError()
Returnnil if the thread terminated correctly, the error that caused thread termination otherwise.
Raise
JoinError if the thread is not terminated or detached.

This method return the item that was raised by a thread and that wasn't caught at thread toplevel. If a thread terminated because of an unhandled error, and not because of a clean exit from the run method, this method will return the raised item, which is usually an item of class Error.

getName

Sets the symbolic name of this thread.

Thread.getName()
ReturnA string containing the name of this thread (may be empty if not set).

See also: Thread, Thread.

getReturn

Get the return value that was returned by the thread main function.

Thread.getReturn()
ReturnThe value returned by the thread main fucntion.
Raise
JoinError if the thread is not terminated or detached.

This method return the item that was returned by the main thread function, wihch is the Thread.run method. If the thread terminated without returning any value, nil will be returned.

Note: The caller should ascertain that the thread wasn't terminated by an uncaught error with Thread.hadError before to call this method.

Note: The value retreived is actually a local copy of the value returned by the terminated thread. Changing it won't affect other threads willing to read the original value. Also, if the returned value is not serializable, this method will raise a CodeError.

getSystemID

Gets the system low level thread ID for this thread.

Thread.getSystemID()
ReturnA numeric thread ID.

UThis is the system ID for the thread that is being run in the target Falcon object; for those systems that doesn't provide a numeric thread ID, this method returns a pointer to the system resources identifying the thread (as an integer value). It is always granted that two different living threads have different identifiers, but a thread ID may be re-assigned to newly started threads after previous one are dead.

If the thread isn't started, the method returns a meaningless number.

getThreadID

Gets an unique numeric ID for this thread.

Thread.getThreadID()
ReturnA numeric thread ID.

This is an unique counter assigned to each thread as they are created.

hadError

Returns true if the target thread was terminated because of an uncaught raised item.

Thread.hadError()
ReturnTrue if the thread was terminated because of an uncaught raise, false if it terminated correctly.
Raise
JoinError if the thread is not terminated or detached.

join

Waits for a thread to terminate and returns its return value.

Thread.join()
ReturnThe exit value of the target thread.
Raise
JoinError if the thread is detached.
ThreadError if the thread didn't terminate correctly (i.e. raised an error).

This method is actually a shortcut for waiting the thread to become acquireable, and then checking for its termination value. Unless it can be proven that this is the only thread interested to the exit value of the thread to be joined, it is preferrable to use the Thread.wait method, and then checking the return value of the target thread with Thread.getReturn.

If the thread cannot be acquired after termination because it has been detached, this method will raise a JoinError. If the target thread exits with error (raises an item at toplevel) this method raises a ThreadError, and the item raised by the target thread is set as "next" error in the raised ThreadError.

Note: This method doesn't use system level "join" call or equivalent. Falcon calls join(), or equivalent means to dispose of the system-level thread resources only at garbage collecting, or in case a thread instance is used to start another thread after termination. In other words, it is NOT necessary to call this join method on threads started through this API.

run

Overloading hook that will hold the thread main function.

Thread.run()
ReturnA value that will be available for inspection in other threads.

This method is called by the new thread when the Thread.start method is called. The new thread executes the function in run(), and when the function returns, the thread is terminated.

Other threads may wait for this thread to terminate through one of the Waitings

The value returned by this method is made available to inspecting threads through serialization.

sameThread

Returns true if the givevn thread is running the same thread as this object.

Thread.sameThread( otherThread )
otherThread Another thread to be checked against.
ReturnTrue if the system thread running in this Falcon objects are the same.

setName

Sets the symbolic name of this thread.

Thread.setName( name )
name The new name for this thread.

See also: Thread.

start

Launches the thread in a parallel environment.

Thread.start()
Raise
ThreadError if the thread cannot be started.

This method checks for this instance to have a runnable Thread.run method, and then for this object to be fully serializable. Once the instance is readied to be transferred to a parallel environment, the method crates a new Virtual Machine, linking all the modules that are linked to the VM where the start method is called.

Finally, the instance is transferred to the other VM, de-serialized there and readied for execution. When everything is ready, the new thread is finally started and the run method is executed in the parallel environment.

This method represents a single point of discontinuity in the calling application. On failure, an error is raised, reporting the details of the problem. Problems preventing parallel execution may be due to system resources (i.e. limited thread handles or memory limits) or to programming error (i.e. having one of the properties in this instance being a complex object that cannot be serialized).

On success, the method return and the other thread is started immediately, or as soon as the system is able to start it.

If this object is connected to an already running thread, trying to start it will raise a ThreadError.

It is possible to start again the thread after it has terminated and joined, provided this is not a detached thread.

See also: Thread, Thread.

stop

Interrupts the target thread.

Thread.stop()

This method sends a kind request for wait interruption to the VM running the target thread. The VM interruption request will stop waiting calls and raise an InterruptedError in the target thread. The thread may either honor the request and terminate as soon as it can or discard the signalation and resume normal execution.

terminated

Returns true if the target thread is terminated.

Thread.terminated()
ReturnTrue if the thread is terminated, false otherwise.

The method will return true if the target thread is not running anymore, either because of a correct terminationor because of an error.

toString

Returns a string representation of this thread.

Thread.toString()
ReturnA string containing anagraphic data for this thread.

See also: Thread.

vwait

Wait for one or more synchronization strucures to become available.

Thread.vwait( structArray, [waitTime] )
structArray Array of structures to wait for
waitTime Maximum timeout in seconds and fractions.
Returnnil if timeout expires, an ID in the structArray or the acquired structure.
Raise
InterrutpedError in case the thread receives a stop request.

This method waits for one of the structures in the given structArray to become acquireable, and acquires it before returning.

This works exactly as Thread.wait, but, on success, the method returns the ID of the acquired item in structArray rather than the object itself. In this way, it is possible to rotate or change the list of items on which to wait for at each call.

See also: Thread.

wait

Wait for one or more synchronization strucures to become available.

Thread.wait( ..., [waitTime] )
... One or more synchronization structure to wait for.
waitTime Maximum timeout in seconds and fractions.
Returnnil if timeout expires, or the acquired item on success.
Raise
InterrutpedError in case the thread receives a stop request.

This method waits for one of the structures in the given parameters to become acquireable, and acquires it before returning.

The acquired structure must be released manually after the thread has used the shared resource.

Typical usage pattern is that of acquiring the needed structures in the thread main loop, work with the achieved structure and release it. Also, it is useful to test for interruption and eventually honor the interruption request as soon as possibile:


      class MyThread from Thread
      ...
         function run()
            loop
               try
                  // wait at max 1 second.
                  res = self.wait( resA, resB, 1.0 )
               catch InterruptedError
                  // honor the request
                  return
               end

               // what are we up to?
               switch res
                  case nil
                     // timed out; perform some periodic operations

                  case resA
                     // do things with resA
                     resA.release()

                  case resB
                     // do things with resB
                     resB.release()
               end

               // do extra work with signaled data (*)
            end
         end
      end

The method tries to acquire the resource in the same order they are passed as paramters. If the first resource is always available when the thread enters the wait, this will actually prevent the thread from acquiring other resources. As some resources can be acquired relatively often, it is necessary to be careful about this aspect. Repeated acquisition and release may cause starving of other threads and of other resources being in need of handling.

It is advisable to release the resources as soon as possible and perform work on the shared data after they have been release, in the code section marked with (*). Also, if the structured waited on may become available at the same time, it is advisable to use Thread.vwait instead, to easily rotate the order in which the call tries to acquire the resources.

See also: Threading.

Made with http://www.falconpl.org