Question

I have a function that needs to schedule a task to the libuv event loop. My idea was to create a timer with 0ms timeout. I have tried the following code:

void myFunction() {
    ...
    uv_timer_t* timer = new uv_timer_t();
    uv_timer_init(uv_default_loop(), timer);
    uv_timer_start(timer, [&](uv_timer_t* timer, int status) {
        // Scheduled task
    }, 0, 0);
}

This approach works well but the problem is, that the dynamically allocated timer will never be freed. I have tried freeing the timer in the callback, but that have led to segmentation fault:

void myFunction() {
    ...
    uv_timer_t* timer = new uv_timer_t();
    uv_timer_init(uv_default_loop(), timer);
    uv_timer_start(timer, [&](uv_timer_t* timer, int status) {
        // Scheduled task
        delete timer;
    }, 0, 0);
}

I have also tried to call uv_timer_stop(timer); and uv_unref((uv_handle_t*) timer); before the actual memory freeing, but the segmentation fault still remians.

Was it helpful?

Solution

I had the same problem, and here is the way you handle it:

First, you will want to create a callback for when your timer handle gets closed:

void on_timer_close_complete(uv_handle_t* handle)
{
    free(handle);
}

Notice that the handle will be freed in the callback.

When you go to stop and free your timer, you would do it like this:

uv_timer_stop(pTimerHandle);
uv_close((uv_handle_t *)pTimerHandle,on_timer_close_complete);

The part that is not intuitive is the uv_close() call. I don't think I have seen it anywhere in the documentation. I was only able to figure this out by following the source.

This way, libuv will execute your callback when it is done with the timer, and then you can free it safely within that callback.

OTHER TIPS

Based on the @IntelliAdmin answer, if you don't want to close it on your own, and just want it to be closed when there are no more references back to it, you can use smart pointers:

template<typename T>
using deleted_unique_ptr = std::unique_ptr<T, std::function<void( T* )>>;


deleted_unique_ptr<uv_timer_t> timer = deleted_unique_ptr<uv_timer_t>( new uv_timer_t, [&]( uv_timer_t *timerhandl ) {
    uv_close( reinterpret_cast<uv_handle_t *>( timerhandl ), OnTimerClose );
});

Then for the callback just delete the pointer:

void OnTimerClose( uv_handle_t *handle )
{
    delete handle;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top