blob: 59da8eeb81ddbb81a5a86330e668751d6447f465 [file] [log] [blame]
Karl Wiberg3d452cf2020-09-11 16:09:46 +02001/*
2 * Copyright 2020 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
Mirko Bonadei3d259352020-10-23 12:04:40 +020011#ifndef RTC_BASE_CALLBACK_LIST_H_
12#define RTC_BASE_CALLBACK_LIST_H_
Karl Wiberg3d452cf2020-09-11 16:09:46 +020013
14#include <utility>
15#include <vector>
16
17#include "api/function_view.h"
Karl Wiberg3d452cf2020-09-11 16:09:46 +020018#include "rtc_base/system/assume.h"
Karl Wibergd2c69672020-09-29 13:55:13 +020019#include "rtc_base/system/inline.h"
Karl Wiberg70026f92020-09-18 10:03:16 +020020#include "rtc_base/untyped_function.h"
Karl Wiberg3d452cf2020-09-11 16:09:46 +020021
22namespace webrtc {
Mirko Bonadei3d259352020-10-23 12:04:40 +020023namespace callback_list_impl {
Karl Wiberg3d452cf2020-09-11 16:09:46 +020024
Mirko Bonadei3d259352020-10-23 12:04:40 +020025class CallbackListReceivers {
Karl Wiberg3d452cf2020-09-11 16:09:46 +020026 public:
Mirko Bonadei3d259352020-10-23 12:04:40 +020027 CallbackListReceivers();
28 CallbackListReceivers(const CallbackListReceivers&) = delete;
29 CallbackListReceivers& operator=(const CallbackListReceivers&) = delete;
30 CallbackListReceivers(CallbackListReceivers&&) = delete;
31 CallbackListReceivers& operator=(CallbackListReceivers&&) = delete;
32 ~CallbackListReceivers();
Karl Wiberg8d875582020-09-18 09:59:50 +020033
Karl Wibergd2c69672020-09-29 13:55:13 +020034 template <typename UntypedFunctionArgsT>
35 RTC_NO_INLINE void AddReceiver(UntypedFunctionArgsT args) {
36 receivers_.push_back(UntypedFunction::Create(args));
Karl Wiberg3d452cf2020-09-11 16:09:46 +020037 }
Karl Wiberg8d875582020-09-18 09:59:50 +020038
Karl Wiberg3d452cf2020-09-11 16:09:46 +020039 void Foreach(rtc::FunctionView<void(UntypedFunction&)> fv);
40
41 private:
Karl Wiberg3d452cf2020-09-11 16:09:46 +020042 std::vector<UntypedFunction> receivers_;
43};
44
Mirko Bonadei3d259352020-10-23 12:04:40 +020045extern template void CallbackListReceivers::AddReceiver(
Karl Wibergd2c69672020-09-29 13:55:13 +020046 UntypedFunction::TrivialUntypedFunctionArgs<1>);
Mirko Bonadei3d259352020-10-23 12:04:40 +020047extern template void CallbackListReceivers::AddReceiver(
Karl Wibergd2c69672020-09-29 13:55:13 +020048 UntypedFunction::TrivialUntypedFunctionArgs<2>);
Mirko Bonadei3d259352020-10-23 12:04:40 +020049extern template void CallbackListReceivers::AddReceiver(
Karl Wibergd2c69672020-09-29 13:55:13 +020050 UntypedFunction::TrivialUntypedFunctionArgs<3>);
Mirko Bonadei3d259352020-10-23 12:04:40 +020051extern template void CallbackListReceivers::AddReceiver(
Karl Wibergd2c69672020-09-29 13:55:13 +020052 UntypedFunction::TrivialUntypedFunctionArgs<4>);
Mirko Bonadei3d259352020-10-23 12:04:40 +020053extern template void CallbackListReceivers::AddReceiver(
Karl Wibergd2c69672020-09-29 13:55:13 +020054 UntypedFunction::NontrivialUntypedFunctionArgs);
Mirko Bonadei3d259352020-10-23 12:04:40 +020055extern template void CallbackListReceivers::AddReceiver(
Karl Wibergd2c69672020-09-29 13:55:13 +020056 UntypedFunction::FunctionPointerUntypedFunctionArgs);
57
Mirko Bonadei3d259352020-10-23 12:04:40 +020058} // namespace callback_list_impl
Karl Wiberg3d452cf2020-09-11 16:09:46 +020059
60// A collection of receivers (callable objects) that can be called all at once.
Karl Wiberg1a88ea12020-11-09 10:36:32 +010061// Optimized for minimal binary size. The template arguments dictate what
62// signature the callbacks must have; for example, a CallbackList<int, float>
63// will require callbacks with signature void(int, float).
Karl Wiberg3d452cf2020-09-11 16:09:46 +020064//
Karl Wiberg1a88ea12020-11-09 10:36:32 +010065// CallbackList is neither copyable nor movable (could easily be made movable if
66// necessary). Callbacks must be movable, but need not be copyable.
Karl Wiberg8d875582020-09-18 09:59:50 +020067//
Karl Wiberg1a88ea12020-11-09 10:36:32 +010068// Usage example:
69//
70// // Declaration (usually a member variable).
71// CallbackList<int, float> foo_;
72//
73// // Register callbacks. This can be done zero or more times. The
74// // callbacks must accept the arguments types listed in the CallbackList's
75// // template argument list, and must return void.
76// foo_.AddReceiver([...](int a, float b) {...}); // Lambda.
77// foo_.AddReceiver(SomeFunction); // Function pointer.
78//
79// // Call the zero or more receivers, one after the other.
80// foo_.Send(17, 3.14);
81//
82// Callback lifetime considerations
83// --------------------------------
84//
85// CallbackList::AddReceiver() takes ownership of the given callback by moving
86// it in place. The callback can be any callable object; in particular, it may
87// have a nontrivial destructor, which will be run when the CallbackList is
88// destroyed. The callback may thus access data via any type of smart pointer,
89// expressing e.g. unique, shared, or weak ownership. Of course, if the data is
90// guaranteed to outlive the callback, a plain raw pointer can be used.
91//
92// Take care when trying to have the callback own reference-counted data. The
93// CallbackList will keep the callback alive, and the callback will keep its
94// data alive, so as usual with reference-counted ownership, keep an eye out for
95// cycles!
96//
97// Thread safety
98// -------------
99//
100// Like most C++ types, CallbackList is thread compatible: it's not safe to
101// access it concurrently from multiple threads, but it can be made safe if it
102// is protected by a mutex, for example.
103//
104// Excercise some care when deciding what mutexes to hold when you call
105// CallbackList::Send(). In particular, do not hold mutexes that callbacks may
106// need to grab. If a larger object has a CallbackList member and a single mutex
107// that protects all of its data members, this may e.g. make it necessary to
108// protect its CallbackList with a separate mutex; otherwise, there will be a
109// deadlock if the callbacks try to access the object.
110//
111// CallbackList as a class data member
112// -----------------------------------
113//
114// CallbackList is a normal C++ data type, and should be private when it is a
115// data member of a class. For thread safety reasons (see above), it is likely
116// best to not have an accessor for the entire CallbackList, and instead only
117// allow callers to add callbacks:
118//
119// template <typename F>
120// void AddFooCallback(F&& callback) {
121// // Maybe grab a mutex here?
122// foo_callbacks_.AddReceiver(std::forward<F>(callback));
123// }
124//
125// Removing callbacks
126// ------------------
127//
128// TODO(kwiberg): The current design doesn’t support removing callbacks, only
129// adding them, but removal support can easily be added.
Karl Wiberg3d452cf2020-09-11 16:09:46 +0200130template <typename... ArgT>
Mirko Bonadei3d259352020-10-23 12:04:40 +0200131class CallbackList {
Karl Wiberg3d452cf2020-09-11 16:09:46 +0200132 public:
Mirko Bonadei3d259352020-10-23 12:04:40 +0200133 CallbackList() = default;
134 CallbackList(const CallbackList&) = delete;
135 CallbackList& operator=(const CallbackList&) = delete;
136 CallbackList(CallbackList&&) = delete;
137 CallbackList& operator=(CallbackList&&) = delete;
Karl Wiberg8d875582020-09-18 09:59:50 +0200138
139 // Adds a new receiver. The receiver (a callable object or a function pointer)
140 // must be movable, but need not be copyable. Its call signature should be
141 // `void(ArgT...)`.
Karl Wiberg3d452cf2020-09-11 16:09:46 +0200142 template <typename F>
143 void AddReceiver(F&& f) {
144 receivers_.AddReceiver(
Karl Wibergd2c69672020-09-29 13:55:13 +0200145 UntypedFunction::PrepareArgs<void(ArgT...)>(std::forward<F>(f)));
Karl Wiberg3d452cf2020-09-11 16:09:46 +0200146 }
Karl Wiberg8d875582020-09-18 09:59:50 +0200147
148 // Calls all receivers with the given arguments.
Karl Wibergd88b1692020-09-25 06:16:12 +0200149 template <typename... ArgU>
150 void Send(ArgU&&... args) {
Karl Wiberg3d452cf2020-09-11 16:09:46 +0200151 receivers_.Foreach([&](UntypedFunction& f) {
Karl Wibergd88b1692020-09-25 06:16:12 +0200152 f.Call<void(ArgT...)>(std::forward<ArgU>(args)...);
Karl Wiberg3d452cf2020-09-11 16:09:46 +0200153 });
154 }
155
156 private:
Mirko Bonadei3d259352020-10-23 12:04:40 +0200157 callback_list_impl::CallbackListReceivers receivers_;
Karl Wiberg3d452cf2020-09-11 16:09:46 +0200158};
159
160} // namespace webrtc
161
Mirko Bonadei3d259352020-10-23 12:04:40 +0200162#endif // RTC_BASE_CALLBACK_LIST_H_