Inter Thread Message Based Communication: Alexandr Štefek Military Academy in Brno Alexandr@stefek - CZ
Inter Thread Message Based Communication: Alexandr Štefek Military Academy in Brno Alexandr@stefek - CZ
Alexandr tefek
Military Academy in Brno
[email protected]
Abstract
This paper present implementation of parallel execution. If we use parallel proces in programs we
have to solve synchronization. We show the effective implementation of parallel execution
without using critical sections, semaphores, mutexes or events.
Thread
The thread is system object defined on platform Win32. SDK defines some method for thread
creating and handling. In real implementation must be defined the procedure for all parallel
procedures. If in system Win32 thread create new window handle then all messages are handled
by this thread. For this fact commes the idea of problem solution.
We can simply create window handle on executing thread. When this thread executes loop for
message handling it is possible to send special message to thread window handle. The parameters
of message can be method to execute and parameter for this method. But method has 8 bytes and
the message parameter only 4. So we have allocate memory block, copy method to this block and
send adress of allocated block.
Coding the method
We want to create class that has method for sync parallel and async parallel execution of
methods. Now we show, how to code the 8 byte method to 4 byte adress of method.
function TAxThread.NotifyEventToPointer(Proc: TNotifyEvent): Longint;
var
Method: TMethod absolute Proc;
PMethod: ^TMethod;
begin
New(PMethod);
PMethod^ := Method;
Result := Longint(PMethod);
end;
procedure TAxThread.ExecProcedure(var Message: TMessage);
var
PMethod : ^TMethod;
Method : TMethod;
Event: TNotifyEvent absolute Method;
begin
PMethod := Pointer(Message.WParam);
Method := PMethod^;
Event(TObject(Message.LParam));
Dispose(PMethod);
if FThreadID = GetCurrentThreadId then
InterlockedDecrement(FMethodsToExecute);
end;
NotifyEventToPointer is method for copying method to memory block. Result of this method
is adress of memory block. Method ExeProcedure takes WParam of message, convert it back to
method and call decoded method with parametr defined by LParam of message.
Thread loop
We have to define thread message loop. Delphi define basic thread class TThread. This class has
virtual method execute. Defined class TAxThread is inherited from TThread. Method
TAxThread.Execute is overrided;
procedure TAxThread.Execute;
var
Msg: TMsg;
Done: Boolean;
begin
CreateHandleParallel;
FThreadID := GetCurrentThreadId;
while not Terminated do
begin
if Done then
begin
FIdleData := nil;
WaitMessage;
end;
while ProcessMessage(Msg) do {loop};
Idle(FIdleData, Done);
end;
end;
At first the class has to create handle (CreateHandleParallel). Loop while waits for messages
switched, message is immediately handled and control is returned to sending thread). The API
function PostMessage puts the message to message queue and continue in execution. When the
message is peek from queue, is handled and method is executed.
//Asynchro execute on parallel thread
procedure TAxThread.AsyncExecuteParallel(Proc: TNotifyEvent; ParamSender:
TObject);
begin
InterlockedIncrement(FMethodsToExecute);
PostMessageParallel(CM_EXECPROC, NotifyEventToPointer(Proc),
Longint(ParamSender));
end;
//Synchro execute on parallel thread
procedure TAxThread.SyncExecuteParallel(Proc: TNotifyEvent; ParamSender:
TObject);
begin
InterlockedIncrement(FMethodsToExecute);
SendMessageParallel(CM_EXECPROC, NotifyEventToPointer(Proc),
Longint(ParamSender));
end;
Private variable FExecutingThread is thread on witch the metods will be executed. There are
three public method in form of TNotifyEvent (can be executed on selected thread).
procedure TMainForm.btnRandomizeClick(Sender: TObject);
var
PomBMP : TBitmap;
begin
if FExecutingThread = nil then
FExecutingThread := TAxThread.Create;
PomBMP := TBitmap.Create;
PomBMP.Width := 200;
PomBMP.Height := 200;
PomBMP.PixelFormat := pf24bit;
FExecutingThread.AsyncExecuteParallel(RandomizeBMP, PomBMP);
end;
When user clicked on button then method btnRandomizeClick is called. Method calls
AsyncExecuteParallel. Main thread continue in responsing to user interaction. When the
X : Longint;
Y : Longint;
Color : Longint;
begin
if not(Data is TBitmap) then
Exit;
PomBMP := Data as TBitmap;
CurrentThread := TAxThread.GetCurrentThread;
I := 0;
try
PomBMP.Canvas.Lock;
while not CurrentThread.Terminated do
begin
Inc(I);
if I > MaxPoints then
Break;
X := Random(200);
Y := Random(200);
Color := Random(256) * 256 * 256 + Random(256) * 256 + Random(256);
if (I mod (MaxPoints div 100)) = 0 then
CurrentThread.SyncExecuteMain(Progress, TObject(I));
//slow for demonstration
PomBMP.Canvas.Pixels[X, Y] := Color;
end;
finally
PomBMP.Canvas.Unlock;
CurrentThread.AsyncExecuteMain(DoUpdate, PomBMP);
end;
end;
Method RandomizeBMP decode parameter as Bitmap and fills it with some random points.
When
randomize
is
finished,
the
thread
notify
main
thread
(CurrentThread.AsyncExecuteMain).
Conclusion
We present implementation of thread class for async (sync) execution. The designed library has
very effective method for developing of parallel computing.