C++ `Timer` class implementation C++ `Timer` class implementation multithreading multithreading

C++ `Timer` class implementation


A possible solution is to just use one thread for all timers, and have a queue ordered by the timeout. The problem with this is that when a timer expires and you call the callback function, it will run in the context of the global timer thread and not separately.This can of course be solved by spawning a new thread just for the event, which is then joined directly, or by having a thread-pool to handle the events, so the main timer thread will not be "clogged up".


You could create one single timer thread, and for each client that "registers", create an entry in a tree. The key would be the client timeout and the value would be a reference to the client. This would order the clients by their timeout.

Then for the timer, set a cyclic timer, say every 100 milliseconds (tune accordingly). When the timer expires, iterate the tree removing and dispatching each client that has timed out. The iteration should stop when you reach a client timeout that hasnt timed out yet.

A more accurate improvement to this approach would be when the timer expires, and the clients are dispatched, calculate the timeout of the next client and set the timer accordingly. It just depends on how accurate the solution needs to be.


Now this is a design question, so everyone has different opinions and it also depends on your requirements, but IMO, the timer should not decide threading policy itself - the client should do that.

I am not sure what behavior you expect, but if you run 300 events on a timer on the same thread and one event handler blocks for some reason, other event handlers will never be triggered.

One possibility is to create a timer on a thread, but implement it in a way that event handlers are executed on other threads via thread pool. Of course, it is still possible to break things, because if you have many long running handlers, thread pool might get exhausted.

I strongly suggest not using explicit new thread for each handler, as context switching would likely kill the performance. Thread pool is much better at balancing this.