1 /*
2 * Copyright 2019 The WebRTC Project Authors. All rights reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #ifndef RTC_BASE_TASK_UTILS_TO_QUEUED_TASK_H_
12 #define RTC_BASE_TASK_UTILS_TO_QUEUED_TASK_H_
13
14 #include <memory>
15 #include <type_traits>
16 #include <utility>
17
18 #include "api/task_queue/queued_task.h"
19 #include "rtc_base/task_utils/pending_task_safety_flag.h"
20
21 namespace webrtc {
22 namespace webrtc_new_closure_impl {
23 // Simple implementation of QueuedTask for use with rtc::Bind and lambdas.
24 template <typename Closure>
25 class ClosureTask : public QueuedTask {
26 public:
ClosureTask(Closure && closure)27 explicit ClosureTask(Closure&& closure)
28 : closure_(std::forward<Closure>(closure)) {}
29
30 private:
Run()31 bool Run() override {
32 closure_();
33 return true;
34 }
35
36 typename std::decay<Closure>::type closure_;
37 };
38
39 template <typename Closure>
40 class SafetyClosureTask : public QueuedTask {
41 public:
SafetyClosureTask(rtc::scoped_refptr<PendingTaskSafetyFlag> safety,Closure && closure)42 explicit SafetyClosureTask(rtc::scoped_refptr<PendingTaskSafetyFlag> safety,
43 Closure&& closure)
44 : closure_(std::forward<Closure>(closure)),
45 safety_flag_(std::move(safety)) {}
46
47 private:
Run()48 bool Run() override {
49 if (safety_flag_->alive())
50 closure_();
51 return true;
52 }
53
54 typename std::decay<Closure>::type closure_;
55 rtc::scoped_refptr<PendingTaskSafetyFlag> safety_flag_;
56 };
57
58 // Extends ClosureTask to also allow specifying cleanup code.
59 // This is useful when using lambdas if guaranteeing cleanup, even if a task
60 // was dropped (queue is too full), is required.
61 template <typename Closure, typename Cleanup>
62 class ClosureTaskWithCleanup : public ClosureTask<Closure> {
63 public:
ClosureTaskWithCleanup(Closure && closure,Cleanup && cleanup)64 ClosureTaskWithCleanup(Closure&& closure, Cleanup&& cleanup)
65 : ClosureTask<Closure>(std::forward<Closure>(closure)),
66 cleanup_(std::forward<Cleanup>(cleanup)) {}
~ClosureTaskWithCleanup()67 ~ClosureTaskWithCleanup() override { cleanup_(); }
68
69 private:
70 typename std::decay<Cleanup>::type cleanup_;
71 };
72 } // namespace webrtc_new_closure_impl
73
74 // Convenience function to construct closures that can be passed directly
75 // to methods that support std::unique_ptr<QueuedTask> but not template
76 // based parameters.
77 template <typename Closure>
ToQueuedTask(Closure && closure)78 std::unique_ptr<QueuedTask> ToQueuedTask(Closure&& closure) {
79 return std::make_unique<webrtc_new_closure_impl::ClosureTask<Closure>>(
80 std::forward<Closure>(closure));
81 }
82
83 template <typename Closure>
ToQueuedTask(rtc::scoped_refptr<PendingTaskSafetyFlag> safety,Closure && closure)84 std::unique_ptr<QueuedTask> ToQueuedTask(
85 rtc::scoped_refptr<PendingTaskSafetyFlag> safety,
86 Closure&& closure) {
87 return std::make_unique<webrtc_new_closure_impl::SafetyClosureTask<Closure>>(
88 std::move(safety), std::forward<Closure>(closure));
89 }
90
91 template <typename Closure>
ToQueuedTask(const ScopedTaskSafety & safety,Closure && closure)92 std::unique_ptr<QueuedTask> ToQueuedTask(const ScopedTaskSafety& safety,
93 Closure&& closure) {
94 return ToQueuedTask(safety.flag(), std::forward<Closure>(closure));
95 }
96
97 template <typename Closure,
98 typename Cleanup,
99 typename std::enable_if<!std::is_same<
100 typename std::remove_const<
101 typename std::remove_reference<Closure>::type>::type,
102 ScopedTaskSafety>::value>::type* = nullptr>
ToQueuedTask(Closure && closure,Cleanup && cleanup)103 std::unique_ptr<QueuedTask> ToQueuedTask(Closure&& closure, Cleanup&& cleanup) {
104 return std::make_unique<
105 webrtc_new_closure_impl::ClosureTaskWithCleanup<Closure, Cleanup>>(
106 std::forward<Closure>(closure), std::forward<Cleanup>(cleanup));
107 }
108
109 } // namespace webrtc
110
111 #endif // RTC_BASE_TASK_UTILS_TO_QUEUED_TASK_H_
112