>>> I've found an interesting multithreading issue which is related not only 
>>> to
>>> ICS component but many many other components I've seen so far. It is a 
>>> race
>>> condition between two thread where one is triggering an event handler and
>>> the other is removing (setting to nil) the event handler.
>>> [..]
>> Quite normal. The proper way to disable a handler is not nil'ing it nor
>> grabbing and saving pointer to handler proc and then calling it (because
>> then the thread1 may do something that thread2 don't want do), but using
>> a global, protected by critical section variable.

> Sorry but I don't agree with you. The only proper way to disable an event 
> handler is to nilling it.

Only in case of single-threades applications or multithreaded ones that do
not use one component in several, parallel threads.

> Using a global variable is a very bad design or 
> even wrong design: you may have many instances of the same component. 

You can still use a descendant with another public field.

> Protecting using a critical section doesn't solve anything in that case and 
> would have a negative impact on performance.

Of course it does!

procedure TMyComponent.TriggerMyEvent(MyArg : Integer);
    if Assigned(OnMyEvent) then
        OnMyEvent(Self, MyArg);

Now we're certain that nothing would change OnMyEvent between the
"if...then" and OnMyEvent call, and old OnMyEvent won't be triggered even
if thread2 would nil it in-between if..then and OnMyEvent - thread2 will
nil it AFTER OnMyEvent occurence.

> It is thread's #2 
> responsability to handle the consequences of nilling the event handler. The 
> component having an handler nilled can trigger an null pointer exception 
> because of that but is not responsible for what happend outside of his own 
> code.

True, but what if thread2 nils the event handler AFTER thread1 saves the
event handler's procedure address? Thread2 may do this because of something
happened - something that requires the event to NOT occur. Now Thread1 has
saved the event handler address, Thread2 is certain that the event won't
occur, and voila - event occurs anyway. This may lead to difficult to debug
bugs. The only way to not complicate code and slow it down due to critical
section usage is to NOT nil events on which *other* thread relies.
Otherwise thread2 should enter critical section, nil it, and leave it.

Your solution isn't bad, it simply can cause some confusion if someone
relies on events not occuring.

Piotr Dalek

PS. Fajny portal... >>> http://link.interia.pl/f196a

To unsubscribe or change your settings for TWSocket mailing list
please goto http://www.elists.org/mailman/listinfo/twsocket
Visit our website at http://www.overbyte.be

Reply via email to