[RFC PATCH v3 06/21] apps: common: event_loop: Add way to cancel deferred calls
Jacopo Mondi
jacopo.mondi at ideasonboard.com
Tue Feb 4 11:00:18 CET 2025
Hi Barnabás
On Thu, Jan 30, 2025 at 11:50:32AM +0000, Barnabás Pőcze wrote:
> Store a cookie value of `std::uintptr_t` with the callback to
> make later cancellation of the callback possible.
>
> Signed-off-by: Barnabás Pőcze <pobrn at protonmail.com>
> ---
> src/apps/common/event_loop.cpp | 18 ++++++++++++++----
> src/apps/common/event_loop.h | 6 ++++--
> 2 files changed, 18 insertions(+), 6 deletions(-)
>
> diff --git a/src/apps/common/event_loop.cpp b/src/apps/common/event_loop.cpp
> index b6230f4ba..0d7a4a024 100644
> --- a/src/apps/common/event_loop.cpp
> +++ b/src/apps/common/event_loop.cpp
> @@ -10,6 +10,7 @@
> #include <assert.h>
> #include <event2/event.h>
> #include <event2/thread.h>
> +#include <algorithm>
> #include <iostream>
>
> EventLoop *EventLoop::instance_ = nullptr;
> @@ -33,7 +34,7 @@ EventLoop::EventLoop()
> if (self->calls_.empty())
> break;
>
> - call = std::move(self->calls_.front());
> + call = std::move(self->calls_.front().first);
> self->calls_.pop_front();
> }
>
> @@ -73,16 +74,25 @@ void EventLoop::exit(int code)
> event_base_loopbreak(base_);
> }
>
> -void EventLoop::callLater(std::function<void()> &&func)
> +void EventLoop::callLater(std::function<void()> &&func, std::optional<std::uintptr_t> cookie)
Is this a good idea to make cookie optional ?
As far as I can see !cookie means all pending callbacks are deleted
> {
> {
> - std::unique_lock<std::mutex> locker(lock_);
> - calls_.push_back(std::move(func));
> + std::lock_guard locker(lock_);
> + calls_.emplace_back(std::move(func), cookie);
> }
>
> event_active(callsTrigger_, 0, 0);
> }
>
> +void EventLoop::cancelLater(std::optional<std::uintptr_t> cookie)
> +{
> + std::lock_guard locker(lock_);
> +
> + calls_.erase(std::remove_if(calls_.begin(), calls_.end(),
> + [&](const auto &x) { return !cookie || x.second == *cookie; }),
Can x.second be invalid ?
I guess so looking at the call of
src/apps/cam/camera_session.cpp:
EventLoop::instance()->callLater([this, request]() { processRequest(request); });
Making the cookie (which is a reference to the caller, that's it)
mandatory would make the code simpler ?
Also why do you need to dereference cookie here ? Can't you just
compare the two optional<> ?
Thanks
j
> + calls_.end());
> +}
> +
> void EventLoop::addFdEvent(int fd, EventType type,
> std::function<void()> &&callback)
> {
> diff --git a/src/apps/common/event_loop.h b/src/apps/common/event_loop.h
> index 507023996..6d7d0497a 100644
> --- a/src/apps/common/event_loop.h
> +++ b/src/apps/common/event_loop.h
> @@ -13,6 +13,7 @@
> #include <list>
> #include <memory>
> #include <mutex>
> +#include <optional>
>
> #include <libcamera/base/class.h>
>
> @@ -36,7 +37,8 @@ public:
> int exec();
> void exit(int code = 0);
>
> - void callLater(std::function<void()> &&func);
> + void callLater(std::function<void()> &&func, std::optional<std::uintptr_t> cookie = {});
> + void cancelLater(std::optional<std::uintptr_t> cookie = {});
>
> void addFdEvent(int fd, EventType type,
> std::function<void()> &&handler);
> @@ -63,7 +65,7 @@ private:
> struct event_base *base_;
> int exitCode_;
>
> - std::deque<std::function<void()>> calls_;
> + std::deque<std::pair<std::function<void()>, std::optional<std::uintptr_t>>> calls_;
> ::event *callsTrigger_ = nullptr;
>
> std::list<std::unique_ptr<Event>> events_;
> --
> 2.48.1
>
>
More information about the libcamera-devel
mailing list