mono/mono — pull request #337 by robwilkens (2012-06-20 15:37:36+00:00)
Title: Fix:Idle event handler was called on every thread rather than thread ass...

...igned on

Summary of changes in order git diff --staged is giving them to me:

(1) Each Xplat driver :
-local "Idle" variable remove, replaced with a Driver-level Idle_Threads
which is assigned by what is now the Idle Property.

-When Idle Called from with thread it used to do:
if (Idle != null)
Idle (this, e)

now we have to do some additional checks and change the call similar to as
follows to get the per-thread idle event handler:

(pseudo-pseudo-code)
id=ManagedThreadId;
if (Idle_Threads is not null and it contains a key for the id and the key
indexes into a non-null event handler) then
Idle_Threads [id] (this, e);

(2) Xplat Driver
Here's where the property is added and assigns the Idle event handler to
Idle_Threads. A Lock was needed the first time we create the Idle_Threads
dictionary. The Idle_Threads dictionary indexes by managed thread id and
maps onto an event handler for each one.

(3) Win32 Specific change
In my testing, I noticed that Win32 did not call Idle as part of its normal
Run loop processing. So, when it would call GetMessage and it was Blocking
we now check Idle if we were going to block. We don't actually call idle
if we first peekMessage and find a message, in those cases we just treat
it as if GetMessage Got the message. If we are blocking and peek returns
no messages, we call idle. If we have already called idle once on this
pass through the GetMessage Loop we set CheckIdle to false and go
back to the to to PRocessNextMEssage but this time we block rather than
peek and call idle.

This code was tested on Win32, MacOS/Carbon and Linux/X11. There have been
some minor formatting changes (Code style) since the testing, which should
not affect test results.