Monday, 5 January 2009

Simple multithreading using closures

One nice application of closures is to create multithreaded software, suitable for multi-core CPUs. This example can give some inspiration:

procedure FooBar;
var
context:string;
res1,res2:string;
begin
context:='Test';

ParallelExecute (
procedure begin res1:=context+'1'; end,
procedure begin res2:=context+'2'; end);

ShowMessage (res1+slineBreak+res2);
end;


I used the variable name "context", because you would usually have a context in which you parallelize code. A context can be a database connection pool, or simply the raw data on which you want to operate.

ParallelExecute is implemented like this:

type
TParallelFunction=reference to procedure;
TExceptionClassType=class of Exception;
TSimpleThread=
class (TThread)
proc:TParallelFunction;
ExceptionMessage:string;
ExceptionType:string;
procedure Execute; override;
end;

procedure TSimpleThread.Execute;
begin
inherited;
try
proc;
except
on e:Exception do begin
ExceptionMessage:=e.Message;
ExceptionType:=e.ClassName;
end;
end;
end;

procedure ParallelExecute (p1,p2:TParallelFunction);
var
t1,t2:TSimpleThread;
begin
t1:=TSimpleThread.Create(true);
try
t1.proc:=p1;
t1.Resume;
try
t2:=TSimpleThread.Create(true);
try
t2.proc:=p2;
t2.Resume;
t2.WaitFor;
if t2.ExceptionMessage<>'' then
raise Exception.Create(t2.ExceptionType+': '+t2.ExceptionMessage);
finally
FreeAndNil (t2);
end;
finally
t1.WaitFor;
end;
if t1.ExceptionMessage<>'' then
raise Exception.Create(t1.ExceptionType+': '+t1.ExceptionMessage);
finally
FreeAndNil (t1);
end;
end;


The point is, that closures can be used to generate nice code.

3 comments:

Anonymous said...

Creating the threads on every call costs a lot of time. A thread pool would be much better. And with this change the "background code" becomes larger and you can use one of the already developed frameworks (like my AsyncCalls unit :-) )

Lars D said...

For other blog readers, here is the link to AsyncCalls.

Lars D said...

Andreas, I totally agree. I also see that you have implemented closures in it, very nice :-)