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@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel
_______________________________________________
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel

Reply via email to