[M94 Dev][Tizen] Fix for errors for generating ninja files
[platform/framework/web/chromium-efl.git] / base / bind_post_task_internal.h
1 // Copyright 2020 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifndef BASE_BIND_POST_TASK_INTERNAL_H_
6 #define BASE_BIND_POST_TASK_INTERNAL_H_
7
8 #include <utility>
9
10 #include "base/bind.h"
11 #include "base/callback.h"
12 #include "base/location.h"
13 #include "base/memory/ref_counted.h"
14 #include "base/task_runner.h"
15
16 namespace base {
17 namespace internal {
18
19 // Helper class to ensure that the input callback is always invoked and
20 // destroyed on the provided task runner.
21 template <typename CallbackType>
22 class BindPostTaskTrampoline {
23  public:
24   BindPostTaskTrampoline(scoped_refptr<TaskRunner> task_runner,
25                          const Location& location,
26                          CallbackType callback)
27       : task_runner_(std::move(task_runner)),
28         location_(location),
29         callback_(std::move(callback)) {
30     DCHECK(task_runner_);
31     // Crash immediately instead of when trying to Run() `callback_` on the
32     // destination `task_runner_`.
33     CHECK(callback_);
34   }
35
36   BindPostTaskTrampoline(const BindPostTaskTrampoline& other) = delete;
37   BindPostTaskTrampoline& operator=(const BindPostTaskTrampoline& other) =
38       delete;
39
40   ~BindPostTaskTrampoline() {
41     if (callback_) {
42       // Post a task to ensure that `callback_` is destroyed on `task_runner_`.
43       // The callback's BindState may own an object that isn't threadsafe and is
44       // unsafe to destroy on a different task runner.
45       //
46       // Note that while this guarantees `callback_` will be destroyed when the
47       // posted task runs, it doesn't guarantee the ref-counted BindState is
48       // destroyed at the same time. If the callback was copied before being
49       // passed to BindPostTaskTrampoline then the BindState can outlive
50       // `callback_`, so the user must ensure any other copies of the callback
51       // are also destroyed on the correct task runner.
52       task_runner_->PostTask(location_, BindOnce(&DestroyCallbackOnTaskRunner,
53                                                  std::move(callback_)));
54     }
55   }
56
57   template <typename... Args>
58   void Run(Args... args) {
59     // If CallbackType is a OnceCallback then GetClosure() consumes `callback_`.
60     task_runner_->PostTask(location_,
61                            GetClosure(&callback_, std::forward<Args>(args)...));
62   }
63
64  private:
65   static OnceClosure GetClosure(OnceClosure* callback) {
66     // `callback` is already a closure, no need to call BindOnce().
67     return std::move(*callback);
68   }
69
70   template <typename... Args>
71   static OnceClosure GetClosure(OnceCallback<void(Args...)>* callback,
72                                 Args&&... args) {
73     return BindOnce(std::move(*callback), std::forward<Args>(args)...);
74   }
75
76   static OnceClosure GetClosure(RepeatingClosure* callback) {
77     // `callback` is already a closure, no need to call BindOnce().
78     return *callback;
79   }
80
81   template <typename... Args>
82   static OnceClosure GetClosure(RepeatingCallback<void(Args...)>* callback,
83                                 Args&&... args) {
84     return BindOnce(*callback, std::forward<Args>(args)...);
85   }
86
87   static void DestroyCallbackOnTaskRunner(CallbackType callback) {}
88
89   const scoped_refptr<TaskRunner> task_runner_;
90   const Location location_;
91   CallbackType callback_;
92 };
93
94 }  // namespace internal
95 }  // namespace base
96
97 #endif  // BASE_BIND_POST_TASK_INTERNAL_H_