Given the following program –
#include <iostream> #include <uv.h> int main() { uv_loop_t loop; uv_loop_init(&loop); std::cout << "Libuv version: " << UV_VERSION_MAJOR << "." << UV_VERSION_MINOR << std::endl; int r = 0; uv_timer_t t1_handle; r = uv_timer_init(&loop, &t1_handle); uv_timer_start(&t1_handle, [](uv_timer_t *t) { std::cout << "Timer1 calledn"; }, 0, 2000); uv_run(&loop, UV_RUN_DEFAULT); // second timer uv_timer_t t2_handle; r = uv_timer_init(&loop, &t2_handle); uv_timer_start(&t2_handle, [](uv_timer_t *t) { std::cout << "Timer2 calledn"; }, 0, 1000); uv_loop_close(&loop); }
The second timer handle is never run on the loop, since the loop is already running, and “Timer2 called” is never printed. So I tried stopping the loop temporarily after running it and then adding the second timer –
.... uv_run(&loop, UV_RUN_DEFAULT); // some work uv_stop(&loop); // now add second timer uv_run(&loop, UV_RUN_DEFAULT); // run again ....
But this again didn’t work, probably because the later lines won’t be executed after 1st loop starts running with an repeating timer. So how should I add a new timer handle to already running uvloop?
Advertisement
Answer
You are right that loop needs to be stopped before it can register a new handle. It cannot be achieved by calling uv_stop
function right after uv_run
, because uv_run
needs to return first. It can be achieved for example by stopping it using a handle callback. Here is quite silly example of how it can be done using the existing Timer1 handle. It stops the loop exactly one time on the first run.
#include <iostream> #include <uv.h> int main() { uv_loop_t loop; uv_loop_init(&loop); std::cout << "Libuv version: " << UV_VERSION_MAJOR << "." << UV_VERSION_MINOR << std::endl; int r = 0; uv_timer_t t1_handle; r = uv_timer_init(&loop, &t1_handle); *(bool *)t1_handle.data = true; // need to stop the loop uv_timer_start(&t1_handle, [](uv_timer_t *t) { std::cout << "Timer1 calledn"; bool to_stop = *(bool *)t->data; if (to_stop) { std::cout << "Stopping loop and resetting the flagn"; uv_stop(t->loop); *(bool *)t->data = false; // do not stop the loop again } }, 0, 2000); uv_run(&loop, UV_RUN_DEFAULT); std::cout << "After uv_runn"; // second timer uv_timer_t t2_handle; r = uv_timer_init(&loop, &t2_handle); uv_timer_start(&t2_handle, [](uv_timer_t *t) { std::cout << "Timer2 calledn"; }, 0, 1000); std::cout << "Start loop againn"; uv_run(&loop, UV_RUN_DEFAULT); uv_loop_close(&loop); }
So the output is
Libuv version: 1.9 Timer1 called Stopping loop and resetting the flag After uv_run Start loop again Timer2 called Timer2 called Timer1 called Timer2 called Timer2 called Timer1 called