base: Add WeakRunner

This is a wrapper around a TaskRunner that allows safely capturing
`this`.

It is going to be used in future commits in TracingServiceImpl. It might
be also nice to use in HeapprofdProducer.

Change-Id: I526128c7f0f91d729b17a7c7c92f1b0e07a52da6
diff --git a/Android.bp b/Android.bp
index 3792d85..12e2e61 100644
--- a/Android.bp
+++ b/Android.bp
@@ -10898,6 +10898,7 @@
         "src/base/virtual_destructors.cc",
         "src/base/waitable_event.cc",
         "src/base/watchdog_posix.cc",
+        "src/base/weak_runner.cc",
     ],
 }
 
diff --git a/BUILD b/BUILD
index 5384b7b..fd521e9 100644
--- a/BUILD
+++ b/BUILD
@@ -1278,6 +1278,8 @@
         "src/base/virtual_destructors.cc",
         "src/base/waitable_event.cc",
         "src/base/watchdog_posix.cc",
+        "src/base/weak_runner.cc",
+        "src/base/weak_runner.h",
     ],
     hdrs = [
         ":include_perfetto_base_base",
diff --git a/src/base/BUILD.gn b/src/base/BUILD.gn
index ace0ac6..a5edbac 100644
--- a/src/base/BUILD.gn
+++ b/src/base/BUILD.gn
@@ -60,6 +60,8 @@
     "virtual_destructors.cc",
     "waitable_event.cc",
     "watchdog_posix.cc",
+    "weak_runner.cc",
+    "weak_runner.h",
   ]
 
   if (!is_nacl) {
diff --git a/src/base/weak_runner.cc b/src/base/weak_runner.cc
new file mode 100644
index 0000000..ba63b67
--- /dev/null
+++ b/src/base/weak_runner.cc
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "src/base/weak_runner.h"
+
+#include "perfetto/base/task_runner.h"
+
+namespace perfetto::base {
+
+WeakRunner::WeakRunner(base::TaskRunner* task_runner)
+    : task_runner_(task_runner), destroyed_(std::make_shared<bool>(false)) {}
+
+WeakRunner::~WeakRunner() {
+  *destroyed_ = true;
+}
+
+void WeakRunner::PostTask(std::function<void()> f) const {
+  task_runner_->PostTask([destroyed = destroyed_, f = std::move(f)]() {
+    if (*destroyed) {
+      return;
+    }
+    f();
+  });
+}
+
+void WeakRunner::PostDelayedTask(std::function<void()> f,
+                                 uint32_t delay_ms) const {
+  task_runner_->PostDelayedTask(
+      [destroyed = destroyed_, f = std::move(f)]() {
+        if (*destroyed) {
+          return;
+        }
+        f();
+      },
+      delay_ms);
+}
+
+}  // namespace perfetto::base
diff --git a/src/base/weak_runner.h b/src/base/weak_runner.h
new file mode 100644
index 0000000..e9959a3
--- /dev/null
+++ b/src/base/weak_runner.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SRC_BASE_WEAK_RUNNER_H_
+#define SRC_BASE_WEAK_RUNNER_H_
+
+#include <functional>
+#include <memory>
+
+namespace perfetto::base {
+
+class TaskRunner;
+
+// This is a wrapper around a `base::TaskRunner*`. It is intended to be used by
+// classes that want to post tasks on themselves. When the object is destroyed,
+// all posted tasks become noops.
+//
+// A class that embeds a WeakRunner can safely capture `this` on the posted
+// tasks.
+class WeakRunner {
+ public:
+  explicit WeakRunner(base::TaskRunner* task_runner);
+  ~WeakRunner();
+  base::TaskRunner* task_runner() const { return task_runner_; }
+
+  // Schedules `f` for immediate execution. `f` will not be executed is `*this`
+  // is destroyed.
+  //
+  // Can be called from any thread, but the caller needs to make sure that
+  // `*this` is alive while `PostTask` is running: this is not obvious when
+  // multiple threads are involved.
+  void PostTask(std::function<void()> f) const;
+
+  // Schedules `f` for execution after |delay_ms|.
+  // Can be called from any thread, but the caller needs to make sure that
+  // `*this` is alive while `PostDelayedTask` is running: this is not obvious
+  // when multiple threads are involved.
+  void PostDelayedTask(std::function<void()> f, uint32_t delay_ms) const;
+
+ private:
+  base::TaskRunner* const task_runner_;
+  std::shared_ptr<bool> destroyed_;
+};
+
+}  // namespace perfetto::base
+
+#endif  // SRC_BASE_WEAK_RUNNER_H_