[fpc-devel] Exact details for RTLeventWaitFor and related ?

Kirinn kirinn at mooncore.eu
Sat Aug 22 03:50:09 CEST 2020


When I researched synchronisation behavior and wrote the wiki page 
"Threads", I found that RTL events behave like this:

- When the event is set, a single waiting thread is released (in FIFO 
order), and the event is automatically immediately reset.

- The event can only be in a set or unset state; multiple sets do not 
stack. Even if the event is set twice or ten times, a single WaitFor or 
Reset will change it to unset. This is a likely cause for deadlocks.

- Because the event is automatically reset when a waiting thread is 
released, calling ResetEvent is generally unnecessary.

For set/reset counting we'd need a semaphore instead of an RTL event, 
but I don't think we have an actively supported semaphore implementation 
at this time.

Caveat: The above was true for FPC 3.0.4 on Windows and Linux. 3.2.0 or 
trunk may have changed something, and I can't vouch for other platforms.

~Kirinn


On 8/22/20 1:44 AM, Martin via fpc-devel wrote:
> I am tracing a race condition in lazCollections TLazThreadedQueue
> on win-64
>
> What is supposed to happen in the following case:
>
> 2 or more threads are waiting on the some event
>   RTLeventWaitFor(UniqueEvent)
>
> 1 thread sets it
>   RTLeventSetEvent(UniqueEvent)
>
> I expect that wakes up exactly ONE thread (never mind wich)?
> Or ALL?
>
> If no one resets the event (NO call to RTLeventResetEvent), then that 
> does not change anything? It is still just the one thread that got 
> woken up?
>
> Thanks for any feedback
> Martin
>
>
> p.s.
> Background
>
> TLazThreadedQueue.PopItem works like this
>
> EnterCritical
>   If item avail then return item
> ExitCritical
>    // race condition between those lines.
> RTLeventWaitFor(itemAdded)
> EnterCritical
>   If item avail then return
> ExitCritical
>
> If 2 or more reading (popping) threads are both at the indicated 
> location,
> and if during this time 2 or more items are added
> then there is a problem (I believe)
>
> adding (pushing) an item does
>   RTLeventSet(itemAdded)
> adding 2 items (with no pop in between) calls Set twice
>    => 
> https://lazarus-ccr.sourceforge.io/docs/rtl/system/rtleventsetevent.html
>     It is unclear if the 2nd RTLeventSet has any effect ?
>
>
> According to my tests:
> - I "sleep()" 2 listeners at the critical line, so they both will 
> WaitFor after the sleep
> - while they sleep I add 2 items (2 calls to RTLeventSet, no one 
> listening yet)
> - Both start RTLeventWaitFor
>   => only one listener wakes up.
> Is that the expected behaviour?
>
> _______________________________________________
> fpc-devel maillist  -  fpc-devel at lists.freepascal.org
> https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


More information about the fpc-devel mailing list