Освобождение динамически размещенного экземпляра uv_timer_t (libuv) в C ++ 11

У меня есть функция, которая должна запланировать задачу в цикле событий libuv. Моя идея состояла в том, чтобы создать таймер с тайм-аутом 0 мс. Я пробовал следующий код:

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);
}

Этот подход работает хорошо, но проблема в том, что динамически распределенный таймер никогда не будет освобожден. Я попытался освободить таймер в обратном вызове, но это привело к ошибке сегментации:

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);
}

Я также пытался позвонить uv_timer_stop(timer); а также uv_unref((uv_handle_t*) timer); до фактического освобождения памяти, но ошибка сегментации все еще повторяется.

1

Решение

У меня была такая же проблема, и вот способ, которым вы справляетесь с этим:

Во-первых, вы захотите создать обратный вызов, когда ваш дескриптор таймера закроется:

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

Обратите внимание, что дескриптор будет освобожден в обратном вызове.

Когда вы идете, чтобы остановить и освободить свой таймер, вы сделаете это так:

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

Часть, которая не является интуитивной, является uv_close() вызов. Я не думаю, что видел это где-нибудь в документации. Я смог понять это только следуя источнику.

Таким образом, libuv выполнит ваш обратный вызов, когда это будет сделано с таймером, и затем вы сможете безопасно его освободить в этом обратном вызове.

7

Другие решения

Основываясь на ответе @IntelliAdmin, если вы не хотите закрывать его самостоятельно и просто хотите, чтобы он закрывался, когда на него больше нет ссылок, вы можете использовать умные указатели:

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 );
});

Затем для обратного вызова просто удалите указатель:

void OnTimerClose( uv_handle_t *handle )
{
delete handle;
}
1

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector