Networking Changes Pt 1
This is the first set of changes making up CL:
https://chromium-review.googlesource.com/c/openscreen/+/1654330
Note that EventWaiter contains both the new and old implementations in this
change, allowing for a smaller patch set.
Primary changes are:
1) Rework EventWaiter to only be platform-specific methods
2) Add NetworkLoop class to handle non-platform-specific parts of network calls
and handle callbacks
3) Add NetworkRunner to handle interactions between NetworkLoop and TaskRunner
Change-Id: Ied65cc5e5c6d1f1c013f1e2d0999f5c29ca7d9ac
Reviewed-on: https://chromium-review.googlesource.com/c/openscreen/+/1655955
Commit-Queue: Ryan Keane <rwkeane@google.com>
Reviewed-by: mark a. foltz <mfoltz@chromium.org>
Reviewed-by: Brandon Tolsch <btolsch@chromium.org>
Reviewed-by: Peter Thatcher <pthatcher@google.com>
diff --git a/platform/api/task_runner.h b/platform/api/task_runner.h
index 611b2b5..3f67ec4 100644
--- a/platform/api/task_runner.h
+++ b/platform/api/task_runner.h
@@ -7,6 +7,7 @@
#include <future>
+#include "absl/types/optional.h"
#include "platform/api/time.h"
namespace openscreen {
@@ -14,13 +15,11 @@
// A thread-safe API surface that allows for posting tasks. The underlying
// implementation may be single or multi-threaded, and all complication should
-// be handled by either the implementation class or the TaskRunnerFactory
-// method. It is the expectation of this API that the underlying impl gives
-// the following guarantees:
+// be handled by the implementation class. It is the expectation of this API
+// that the underlying impl gives the following guarantees:
// (1) Tasks shall not overlap in time/CPU.
// (2) Tasks shall run sequentially, e.g. posting task A then B implies
// that A shall run before B.
-// NOTE: we do not make any assumptions about what thread tasks shall run on.
class TaskRunner {
public:
using Task = std::packaged_task<void() noexcept>;
@@ -50,6 +49,44 @@
virtual void PostPackagedTaskWithDelay(Task task, Clock::duration delay) = 0;
};
+// Class used to post the same task repeatedly to the task runner, with the
+// frequency of repetition determined by the result of the underlying function.
+// TODO(rwkeane): Move to separate file in util directory.
+class RepeatingFunction {
+ public:
+ // Posts a delayed task that will run repeatedly. The result of the function
+ // object will determine if the task should be reposted, in that it will be
+ // reposted if and only if the result is not absl::nullopt.
+ static inline void Post(
+ TaskRunner* task_runner,
+ std::function<absl::optional<Clock::duration>()> function,
+ Clock::duration delay = Clock::duration(0)) {
+ task_runner->PostTaskWithDelay(RepeatingFunction(task_runner, function),
+ delay);
+ }
+
+ // Executes the underlying task and re-posts it to the task runner.
+ void operator()() {
+ absl::optional<Clock::duration> delay = function_();
+ if (delay.has_value()) {
+ RepeatingFunction::Post(task_runner_, function_, delay.value());
+ }
+ }
+
+ private:
+ // Creates a new task that will be posted repeatedly to the task runner. If
+ // the function returns a valid Clock::duration, it will be reposted with
+ // that delay, and will not be reposted if absl::nullopt is instead
+ // returned.
+ // TODO(rwkeane): Should use a weak pointer once we support those.
+ RepeatingFunction(TaskRunner* task_runner,
+ std::function<absl::optional<Clock::duration>()> function)
+ : task_runner_(task_runner), function_(function){};
+
+ TaskRunner* task_runner_;
+ std::function<absl::optional<Clock::duration>()> function_;
+};
+
} // namespace platform
} // namespace openscreen