blob: 659b838d02011cece55da0b4c42906e6ce662a9b [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 Wiberg01a36f32020-11-11 11:48:04 +010018#include "rtc_base/checks.h"
Karl Wiberg3d452cf2020-09-11 16:09:46 +020019#include "rtc_base/system/assume.h"
Karl Wibergd2c69672020-09-29 13:55:13 +020020#include "rtc_base/system/inline.h"
Karl Wiberg70026f92020-09-18 10:03:16 +020021#include "rtc_base/untyped_function.h"
Karl Wiberg3d452cf2020-09-11 16:09:46 +020022
23namespace webrtc {
Mirko Bonadei3d259352020-10-23 12:04:40 +020024namespace callback_list_impl {
Karl Wiberg3d452cf2020-09-11 16:09:46 +020025
Mirko Bonadei3d259352020-10-23 12:04:40 +020026class CallbackListReceivers {
Karl Wiberg3d452cf2020-09-11 16:09:46 +020027 public:
Mirko Bonadei3d259352020-10-23 12:04:40 +020028 CallbackListReceivers();
29 CallbackListReceivers(const CallbackListReceivers&) = delete;
30 CallbackListReceivers& operator=(const CallbackListReceivers&) = delete;
31 CallbackListReceivers(CallbackListReceivers&&) = delete;
32 CallbackListReceivers& operator=(CallbackListReceivers&&) = delete;
33 ~CallbackListReceivers();
Karl Wiberg8d875582020-09-18 09:59:50 +020034
Karl Wibergd2c69672020-09-29 13:55:13 +020035 template <typename UntypedFunctionArgsT>
36 RTC_NO_INLINE void AddReceiver(UntypedFunctionArgsT args) {
Karl Wiberg01a36f32020-11-11 11:48:04 +010037 RTC_CHECK(!send_in_progress_);
Karl Wibergd2c69672020-09-29 13:55:13 +020038 receivers_.push_back(UntypedFunction::Create(args));
Karl Wiberg3d452cf2020-09-11 16:09:46 +020039 }
Karl Wiberg8d875582020-09-18 09:59:50 +020040
Karl Wiberg3d452cf2020-09-11 16:09:46 +020041 void Foreach(rtc::FunctionView<void(UntypedFunction&)> fv);
42
43 private:
Karl Wiberg3d452cf2020-09-11 16:09:46 +020044 std::vector<UntypedFunction> receivers_;
Karl Wiberg01a36f32020-11-11 11:48:04 +010045 bool send_in_progress_ = false;
Karl Wiberg3d452cf2020-09-11 16:09:46 +020046};
47
Mirko Bonadei3d259352020-10-23 12:04:40 +020048extern template void CallbackListReceivers::AddReceiver(
Karl Wibergd2c69672020-09-29 13:55:13 +020049 UntypedFunction::TrivialUntypedFunctionArgs<1>);
Mirko Bonadei3d259352020-10-23 12:04:40 +020050extern template void CallbackListReceivers::AddReceiver(
Karl Wibergd2c69672020-09-29 13:55:13 +020051 UntypedFunction::TrivialUntypedFunctionArgs<2>);
Mirko Bonadei3d259352020-10-23 12:04:40 +020052extern template void CallbackListReceivers::AddReceiver(
Karl Wibergd2c69672020-09-29 13:55:13 +020053 UntypedFunction::TrivialUntypedFunctionArgs<3>);
Mirko Bonadei3d259352020-10-23 12:04:40 +020054extern template void CallbackListReceivers::AddReceiver(
Karl Wibergd2c69672020-09-29 13:55:13 +020055 UntypedFunction::TrivialUntypedFunctionArgs<4>);
Mirko Bonadei3d259352020-10-23 12:04:40 +020056extern template void CallbackListReceivers::AddReceiver(
Karl Wibergd2c69672020-09-29 13:55:13 +020057 UntypedFunction::NontrivialUntypedFunctionArgs);
Mirko Bonadei3d259352020-10-23 12:04:40 +020058extern template void CallbackListReceivers::AddReceiver(
Karl Wibergd2c69672020-09-29 13:55:13 +020059 UntypedFunction::FunctionPointerUntypedFunctionArgs);
60
Mirko Bonadei3d259352020-10-23 12:04:40 +020061} // namespace callback_list_impl
Karl Wiberg3d452cf2020-09-11 16:09:46 +020062
63// A collection of receivers (callable objects) that can be called all at once.
Karl Wiberg1a88ea12020-11-09 10:36:32 +010064// Optimized for minimal binary size. The template arguments dictate what
65// signature the callbacks must have; for example, a CallbackList<int, float>
66// will require callbacks with signature void(int, float).
Karl Wiberg3d452cf2020-09-11 16:09:46 +020067//
Karl Wiberg1a88ea12020-11-09 10:36:32 +010068// CallbackList is neither copyable nor movable (could easily be made movable if
69// necessary). Callbacks must be movable, but need not be copyable.
Karl Wiberg8d875582020-09-18 09:59:50 +020070//
Karl Wiberg1a88ea12020-11-09 10:36:32 +010071// Usage example:
72//
73// // Declaration (usually a member variable).
74// CallbackList<int, float> foo_;
75//
76// // Register callbacks. This can be done zero or more times. The
77// // callbacks must accept the arguments types listed in the CallbackList's
78// // template argument list, and must return void.
79// foo_.AddReceiver([...](int a, float b) {...}); // Lambda.
80// foo_.AddReceiver(SomeFunction); // Function pointer.
81//
82// // Call the zero or more receivers, one after the other.
83// foo_.Send(17, 3.14);
84//
85// Callback lifetime considerations
86// --------------------------------
87//
88// CallbackList::AddReceiver() takes ownership of the given callback by moving
89// it in place. The callback can be any callable object; in particular, it may
90// have a nontrivial destructor, which will be run when the CallbackList is
91// destroyed. The callback may thus access data via any type of smart pointer,
92// expressing e.g. unique, shared, or weak ownership. Of course, if the data is
93// guaranteed to outlive the callback, a plain raw pointer can be used.
94//
95// Take care when trying to have the callback own reference-counted data. The
96// CallbackList will keep the callback alive, and the callback will keep its
97// data alive, so as usual with reference-counted ownership, keep an eye out for
98// cycles!
99//
100// Thread safety
101// -------------
102//
103// Like most C++ types, CallbackList is thread compatible: it's not safe to
104// access it concurrently from multiple threads, but it can be made safe if it
105// is protected by a mutex, for example.
106//
107// Excercise some care when deciding what mutexes to hold when you call
108// CallbackList::Send(). In particular, do not hold mutexes that callbacks may
109// need to grab. If a larger object has a CallbackList member and a single mutex
110// that protects all of its data members, this may e.g. make it necessary to
111// protect its CallbackList with a separate mutex; otherwise, there will be a
112// deadlock if the callbacks try to access the object.
113//
114// CallbackList as a class data member
115// -----------------------------------
116//
117// CallbackList is a normal C++ data type, and should be private when it is a
118// data member of a class. For thread safety reasons (see above), it is likely
119// best to not have an accessor for the entire CallbackList, and instead only
120// allow callers to add callbacks:
121//
122// template <typename F>
123// void AddFooCallback(F&& callback) {
124// // Maybe grab a mutex here?
125// foo_callbacks_.AddReceiver(std::forward<F>(callback));
126// }
127//
128// Removing callbacks
129// ------------------
130//
131// TODO(kwiberg): The current design doesn’t support removing callbacks, only
132// adding them, but removal support can easily be added.
Karl Wiberg3d452cf2020-09-11 16:09:46 +0200133template <typename... ArgT>
Mirko Bonadei3d259352020-10-23 12:04:40 +0200134class CallbackList {
Karl Wiberg3d452cf2020-09-11 16:09:46 +0200135 public:
Mirko Bonadei3d259352020-10-23 12:04:40 +0200136 CallbackList() = default;
137 CallbackList(const CallbackList&) = delete;
138 CallbackList& operator=(const CallbackList&) = delete;
139 CallbackList(CallbackList&&) = delete;
140 CallbackList& operator=(CallbackList&&) = delete;
Karl Wiberg8d875582020-09-18 09:59:50 +0200141
142 // Adds a new receiver. The receiver (a callable object or a function pointer)
143 // must be movable, but need not be copyable. Its call signature should be
144 // `void(ArgT...)`.
Karl Wiberg3d452cf2020-09-11 16:09:46 +0200145 template <typename F>
146 void AddReceiver(F&& f) {
147 receivers_.AddReceiver(
Karl Wibergd2c69672020-09-29 13:55:13 +0200148 UntypedFunction::PrepareArgs<void(ArgT...)>(std::forward<F>(f)));
Karl Wiberg3d452cf2020-09-11 16:09:46 +0200149 }
Karl Wiberg8d875582020-09-18 09:59:50 +0200150
Karl Wiberg01a36f32020-11-11 11:48:04 +0100151 // Calls all receivers with the given arguments. While the Send is in
152 // progress, no method calls are allowed; specifically, this means that the
153 // callbacks may not do anything with this CallbackList instance.
Karl Wibergd88b1692020-09-25 06:16:12 +0200154 template <typename... ArgU>
155 void Send(ArgU&&... args) {
Karl Wiberg3d452cf2020-09-11 16:09:46 +0200156 receivers_.Foreach([&](UntypedFunction& f) {
Karl Wibergd88b1692020-09-25 06:16:12 +0200157 f.Call<void(ArgT...)>(std::forward<ArgU>(args)...);
Karl Wiberg3d452cf2020-09-11 16:09:46 +0200158 });
159 }
160
161 private:
Mirko Bonadei3d259352020-10-23 12:04:40 +0200162 callback_list_impl::CallbackListReceivers receivers_;
Karl Wiberg3d452cf2020-09-11 16:09:46 +0200163};
164
165} // namespace webrtc
166
Mirko Bonadei3d259352020-10-23 12:04:40 +0200167#endif // RTC_BASE_CALLBACK_LIST_H_