Add TaskWaiter interface to TaskRunnerImpl
This change adds the option to use a TaskWaiter in TaskRunnerImpl
instead of a condition variable. This allows for a more cooperative
wait than a condition variable in the case where you may only want to
wait on something like a select/poll/epoll call. This is not currently
going to be used but is part of one of our design alternatives for
integrating network polling into TaskRunner.
Bug: openscreen:46
Change-Id: I041117588c293230a138b45bb846db8526104c32
Reviewed-on: https://chromium-review.googlesource.com/c/openscreen/+/1593094
Reviewed-by: Peter Thatcher <pthatcher@google.com>
Commit-Queue: Brandon Tolsch <btolsch@chromium.org>
diff --git a/platform/base/task_runner_impl.h b/platform/base/task_runner_impl.h
index 3041dee..8425eed 100644
--- a/platform/base/task_runner_impl.h
+++ b/platform/base/task_runner_impl.h
@@ -18,6 +18,7 @@
#include "absl/base/thread_annotations.h"
#include "absl/types/optional.h"
+#include "osp_base/error.h"
#include "platform/api/task_runner.h"
#include "platform/api/time.h"
@@ -26,7 +27,30 @@
class TaskRunnerImpl : public TaskRunner {
public:
- explicit TaskRunnerImpl(platform::ClockNowFunctionPtr now_function);
+ class TaskWaiter {
+ public:
+ virtual ~TaskWaiter() = default;
+
+ // These calls should be thread-safe. The absolute minimum is that
+ // OnTaskPosted must be safe to call from another thread while this is
+ // inside WaitForTaskToBePosted. NOTE: There may be spurious wakeups from
+ // WaitForTaskToBePosted depending on whether the specific implementation
+ // chooses to clear queued WakeUps before entering WaitForTaskToBePosted.
+
+ // Blocks until some event occurs, which means new tasks may have been
+ // posted. Wait may only block up to |timeout| where 0 means don't block at
+ // all (not block forever).
+ virtual Error WaitForTaskToBePosted(Clock::duration timeout) = 0;
+
+ // If a WaitForTaskToBePosted call is currently blocking, unblock it
+ // immediately.
+ virtual void OnTaskPosted() = 0;
+ };
+
+ explicit TaskRunnerImpl(
+ platform::ClockNowFunctionPtr now_function,
+ TaskWaiter* event_waiter = nullptr,
+ Clock::duration waiter_timeout = std::chrono::milliseconds(100));
// TaskRunner overrides
~TaskRunnerImpl() override;
@@ -102,7 +126,12 @@
std::greater<DelayedTask>>
delayed_tasks_ GUARDED_BY(task_mutex_);
+ // When |task_waiter_| is nullptr, |run_loop_wakeup_| is used for sleeping the
+ // task runner. Otherwise, |run_loop_wakeup_| isn't used and |task_waiter_|
+ // is used instead (along with |waiter_timeout_|).
std::condition_variable run_loop_wakeup_;
+ TaskWaiter* const task_waiter_;
+ Clock::duration waiter_timeout_;
std::deque<Task> tasks_ GUARDED_BY(task_mutex_);
};
} // namespace platform