[fpc-pascal] PostMessage() from a thread (in a thread save manner)

Vinzent Höfler JeLlyFish.software at gmx.net
Mon Oct 20 18:35:11 CEST 2008


Graeme Geldenhuys wrote:
> Some developers prefer to pass in a GUI component to a thread
> instance, so the thread knows what widget to update. Other users
> prefer to post a "gui update" message to the application event queue.
> 
> I'm very new to threads and might know just enough to make in
> dangerous. :-)  In fpGUI the application's "custom" event queue is a
> linked-list structure.  If threads post messages to that queue, I
> obviously need to make the queue manipulation code thread safe.
> 
> fpgApplication is a global singleton of the TfpgApplication class.
> fpgPostMessage() is a stand-alone function (not a member of
> TfpgApplication class).  To make fpgPostMessage() thread save, I
> instantiated a TCriticalSection instance in the TfpgApplication class
> - in the constructor. I added two member functions .Lock and .Unlock
> which calls FCritSect.Enter and FCritSect.Leave respectively.  In
> fpgPostMessage, I call fpgApplication.Lock, then manipulate the
> message queue and then call fpgApplication.Unlock.
> 
> Is this the correct way to make my event queue thread save?

Yes and no. Allocating the message from the queue might be thread safe 
now, but I strongly suspect that other threads are trying to do 
something with the queue (like evaluating or removing messages).

>   fpgApplication.Lock;   // Enter the critical section
>   try
>     p := fpgAllocateMessage;
>     if p <> nil then
>     begin
>       p^.MsgCode := MsgCode;
>       p^.Sender  := Sender;
>       p^.Dest    := Dest;
>       p^.Params  := aparams;
>     end
>     else
>       DebugLn('THE MESSAGE QUEUE IS FULL.');
>   finally
>     fpgApplication.Unlock;  // leave the critical section
>   end;

So this piece of code is probably not enough to make the queue thread 
safe. IMO it would be best to encapsulate any thread-safety inside the 
queue class itself, instead of sprinkling "fpgApplication.{Un}Lock" all 
over the source. (I know, this can be inefficient, but when having the 
choice between "efficient" or "correct", I'd rather go for "correct".)


Vinzent.




More information about the fpc-pascal mailing list