User Tools

Site Tools


mtthread_synchronization.htm
Navigation:  Advanced Topics > Thread Model Documentation > Multi-Threading Programming >====== Thread Synchronization ====== Previous pageReturn to chapter overviewNext page

The Clarion runtime has a variety of built in interfaces and procedures to help you maintain synchronization between your threads. The POST and EVENT functions have always been in the Clarion language for thread synchronization. SUSPEND and RESUME functions allow you to stop and start another thread, INSTANCE allows you to get another thread's contents for a variable and the ICriticalSection, IMutex, ISemaphore and IReaderWriterLock are interfaces to objects that allow you to synchronize the processing between multiple threads and also multiple processes.

POST/EVENT

You have always been able to synchronize thread processing by posting an event from one thread to another using POST() to send the event and EVENT() to receive it. See the SUSPEND/RESUME section below for an example on using these functions to synchronize two threads.

SUSPEND/RESUME

SUSPEND allows you to stop another process. RESUME starts that process again. You can issue multiple SUSPEND calls for a thread. The same number of RESUME calls must be made for that thread to restart.

The SUSPEND procedure suspends a thread specified by the threadno parameter. If the threadno parameter is a number of an active thread, its execution is suspended and a suspending counter is incremented. Each additional SUSPEND statement issued to the same active thread will increment the suspending counter by one. Therefore, a thread that has been suspended with a given number of SUSPEND statements can only resume thread execution when an equal number of RESUME statements has been executed.

EXTREME CAUTION should be taken with MDI programs using SUSPEND, as improper use can cause program lockups. All MDI child windows have an MDI client window as a parent, and the MDI client window can send rather than post messages to its child windows.

For example, calling the inter-thread SendMessage modal function causes the calling thread (the MDI client window) to suspend activity until the called thread (the MDI Child window) returns from the call. If the called thread is suspended, we would have a program lockup.

The SUSPEND and RESUME functions can be very useful for controlling threads that are CPU intensive. For example, rebuilding keys on a file. Here is an example program that starts a BUILD of a file and allows the user to pause the build and restart it.

PROGRAM

MAP

DoBuild(STRING)

END

MyFile FILE,DRIVER('TopSpeed'),PRE(F)

Key1     KEY(F:Field1),PRIMARY

Key2     KEY(F:Field2)

Key3     KEY(F:Field3, Field4)

RECORD

Field1     LONG

Field2     STRING(20)

Field3     STRING(20)

Field4     STRING(20)

END

END

BuilderWin WINDOW('Building File'),AT(,,81,22),GRAY

BUTTON('Suspend Build'),AT(2,3,75,14),USE(?Button)

END

AllDone  EQUATE(500H)

Building BYTE

ThreadID SIGNED,AUTO

CODE

OPEN(BuilderWin)

ThreadID = START(DoBuild, , THREAD())

Building = TRUE

ACCEPT

CASE EVENT()

OF AllDone

MESSAGE('Build Complete')

BREAK

OF Event:Accepted

IF ACCEPTED() = ?Button

IF Building

SUSPEND(ThreadID)

?Button{PROP:Text} = 'Resume Building'

ELSE

RESUME(ThreadID)

?Button{PROP:Text} = 'Suspend Build'

END

END

END

END

DoBuild PROCEDURE (parent)

CODE

MyFile{PROP:FullBuild} = TRUE

BUILD(MyFile)

POST(AllDone,,parent)

INSTANCE

In versions of Clarion prior to Clarion 6.0 a variable's memory location was constant regardless of which thread accessed the variable. Therefore this code would always work:

PROGRAM

MAP

AFunc()

END

GlobVar SIGNED,THREAD

Addr    LONG

CODE

Addr = ADDRESS(GlobVar,1)

START(AFunc)

AFunc PROCEDURE

CODE

IF Addr <;> ADDRESS(GlobVar)

MESSAGE('Panic')

END

This sort of code was used in ABFILE.CLW to make sure the file manager matched the file it was meant to manage. To allow programs to know what variable they are really using you can now use the INSTANCE function to get the address of the variable on any thread, and most importantly on thread 1. The above code would need to be modified as follows to work in Clarion 6.0.

PROGRAM

MAP

AFunc()

END

GlobVar SIGNED,THREAD

Addr    LONG

CODE

Addr = ADDRESS(GlobVar)

START(AFunc)

AFunc PROCEDURE

CODE

IF Addr <;> INSTANCE(GlobVar,0)

MESSAGE('Panic')

END

mtthread_synchronization.htm.txt · Last modified: 2021/04/15 15:57 by 127.0.0.1