bind_post_task_internal.h 3.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  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. #ifndef BASE_TASK_BIND_POST_TASK_INTERNAL_H_
  5. #define BASE_TASK_BIND_POST_TASK_INTERNAL_H_
  6. #include <utility>
  7. #include "base/bind.h"
  8. #include "base/callback.h"
  9. #include "base/check.h"
  10. #include "base/location.h"
  11. #include "base/task/task_runner.h"
  12. namespace base {
  13. namespace internal {
  14. // Helper class to ensure that the input callback is always invoked and
  15. // destroyed on the provided task runner.
  16. template <typename CallbackType>
  17. class BindPostTaskTrampoline {
  18. public:
  19. BindPostTaskTrampoline(scoped_refptr<TaskRunner> task_runner,
  20. const Location& location,
  21. CallbackType callback)
  22. : task_runner_(std::move(task_runner)),
  23. location_(location),
  24. callback_(std::move(callback)) {
  25. DCHECK(task_runner_);
  26. // Crash immediately instead of when trying to Run() `callback_` on the
  27. // destination `task_runner_`.
  28. CHECK(callback_);
  29. }
  30. BindPostTaskTrampoline(const BindPostTaskTrampoline& other) = delete;
  31. BindPostTaskTrampoline& operator=(const BindPostTaskTrampoline& other) =
  32. delete;
  33. ~BindPostTaskTrampoline() {
  34. if (callback_) {
  35. // Post a task to ensure that `callback_` is destroyed on `task_runner_`.
  36. // The callback's BindState may own an object that isn't threadsafe and is
  37. // unsafe to destroy on a different task runner.
  38. //
  39. // Note that while this guarantees `callback_` will be destroyed when the
  40. // posted task runs, it doesn't guarantee the ref-counted BindState is
  41. // destroyed at the same time. If the callback was copied before being
  42. // passed to BindPostTaskTrampoline then the BindState can outlive
  43. // `callback_`, so the user must ensure any other copies of the callback
  44. // are also destroyed on the correct task runner.
  45. task_runner_->PostTask(location_, BindOnce(&DestroyCallbackOnTaskRunner,
  46. std::move(callback_)));
  47. }
  48. }
  49. template <typename... Args>
  50. void Run(Args... args) {
  51. // If CallbackType is a OnceCallback then GetClosure() consumes `callback_`.
  52. task_runner_->PostTask(location_,
  53. GetClosure(&callback_, std::forward<Args>(args)...));
  54. }
  55. private:
  56. static OnceClosure GetClosure(OnceClosure* callback) {
  57. // `callback` is already a closure, no need to call BindOnce().
  58. return std::move(*callback);
  59. }
  60. template <typename... Args>
  61. static OnceClosure GetClosure(OnceCallback<void(Args...)>* callback,
  62. Args&&... args) {
  63. return BindOnce(std::move(*callback), std::forward<Args>(args)...);
  64. }
  65. static OnceClosure GetClosure(RepeatingClosure* callback) {
  66. // `callback` is already a closure, no need to call BindOnce().
  67. return *callback;
  68. }
  69. template <typename... Args>
  70. static OnceClosure GetClosure(RepeatingCallback<void(Args...)>* callback,
  71. Args&&... args) {
  72. return BindOnce(*callback, std::forward<Args>(args)...);
  73. }
  74. static void DestroyCallbackOnTaskRunner(CallbackType callback) {}
  75. const scoped_refptr<TaskRunner> task_runner_;
  76. const Location location_;
  77. CallbackType callback_;
  78. };
  79. } // namespace internal
  80. } // namespace base
  81. #endif // BASE_TASK_BIND_POST_TASK_INTERNAL_H_