event_loop: refactor step into smaller processing methods

This clarifies the step processing by splitting the code in smaller
steps.

It also removes the @number_of_events_to_process mechanism as IMO
it lost its purpose: either @number_of_events_to_process was greater
than @queue.size and it would block, or it is smaller and therefore
useless. Since the blocking behaviour is definitely unwanted, its
only purpose was to count processed events so that we don't process
newly queued events. This is handled by a boolean parameter to
process_events
event_loop: fix interaction of zero-period timers and process_all_pending_work

This changes #timeout? so that zero-period timers don't get executed
if Time.now == @last_call (i.e. if the timer got called already)

For non-zero-period timers, this really has no effect as the equality
case would never happen outside of tests where Time is mocked.

For zero-period timers, it ensures that they won't get executed twice,
i.e. that process_timers(time) is idempotent (and step(time)) as well.
event_loop: fix thread-safety of process_events(false)

@events is accessed unlocked (that's the whole point of having
a Queue in the first place), so swapping the instance variable
is obviously not thread safe.

Revert back to the original counter-based scheme
event_loop: allow to register callbacks on timers that will be executed once the timer finishes its execution
event_loop: add some more tracing
thread_pool: create wait_for

And reimplement wait_for_one using it, but without the condition
block. When the goal of the caller is to wait for a condition,
wait_for_one was really ill suited as it forced the caller to loop
himself outside of the wait_for_one method (something wait_for_one was
already doing inside ...)
event_loop: fix AsyncTimer#start for a never-started timer

Starting an async timer that was would result in nothing being executed
as the setup done by #async_every was really assuming that it was starting
to "pump" right away.

This moves all the startup logic in #start to avoid the problem.