Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
SkMessageBus.h
Go to the documentation of this file.
1/*
2 * Copyright 2013 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#ifndef SkMessageBus_DEFINED
9#define SkMessageBus_DEFINED
10
11#include <type_traits>
12
20
21/**
22 * The following method must have a specialization for type 'Message':
23 *
24 * bool SkShouldPostMessageToBus(const Message&, IDType msgBusUniqueID)
25 *
26 * We may want to consider providing a default template implementation, to avoid this requirement by
27 * sending to all inboxes when the specialization for type 'Message' is not present.
28 */
29template <typename Message, typename IDType, bool AllowCopyableMessage = true>
31public:
32 template <typename T> struct is_sk_sp : std::false_type {};
33 template <typename T> struct is_sk_sp<sk_sp<T>> : std::true_type {};
34
35 // We want to make sure the caller of Post() method will not keep a ref or copy of the message,
36 // so the message type must be sk_sp or non copyable.
37 static_assert(AllowCopyableMessage || is_sk_sp<Message>::value ||
38 !std::is_copy_constructible<Message>::value,
39 "The message type must be sk_sp or non copyable.");
40
41 // Post a message to be received by Inboxes for this Message type. Checks
42 // SkShouldPostMessageToBus() for each inbox. Threadsafe.
43 static void Post(Message m);
44
45 class Inbox {
46 public:
47 Inbox(IDType uniqueID);
49
50 IDType uniqueID() const { return fUniqueID; }
51
52 // Overwrite out with all the messages we've received since the last call. Threadsafe.
54
55 private:
57 SkMutex fMessagesMutex;
58 const IDType fUniqueID;
59
60 friend class SkMessageBus;
61 void receive(Message m); // SkMessageBus is a friend only to call this.
62 };
63
64private:
66 static SkMessageBus* Get();
67
68 SkTDArray<Inbox*> fInboxes;
69 SkMutex fInboxesMutex;
70};
71
72// This must go in a single .cpp file, not some .h, or we risk creating more than one global
73// SkMessageBus per type when using shared libraries. NOTE: at most one per file will compile.
74#define DECLARE_SKMESSAGEBUS_MESSAGE(Message, IDType, AllowCopyableMessage) \
75 template <> \
76 SkMessageBus<Message, IDType, AllowCopyableMessage>* \
77 SkMessageBus<Message, IDType, AllowCopyableMessage>::Get() { \
78 static SkOnce once; \
79 static SkMessageBus<Message, IDType, AllowCopyableMessage>* bus; \
80 once([] { bus = new SkMessageBus<Message, IDType, AllowCopyableMessage>(); }); \
81 return bus; \
82 }
83
84// ----------------------- Implementation of SkMessageBus::Inbox -----------------------
85
86template <typename Message, typename IDType, bool AllowCopyableMessage>
88 : fUniqueID(uniqueID) {
89 // Register ourselves with the corresponding message bus.
91 SkAutoMutexExclusive lock(bus->fInboxesMutex);
92 bus->fInboxes.push_back(this);
93}
94
95template <typename Message, typename IDType, bool AllowCopyableMessage>
97 // Remove ourselves from the corresponding message bus.
99 SkAutoMutexExclusive lock(bus->fInboxesMutex);
100 // This is a cheaper fInboxes.remove(fInboxes.find(this)) when order doesn't matter.
101 for (int i = 0; i < bus->fInboxes.size(); i++) {
102 if (this == bus->fInboxes[i]) {
103 bus->fInboxes.removeShuffle(i);
104 break;
105 }
106 }
107}
108
109template <typename Message, typename IDType, bool AllowCopyableMessage>
111 SkAutoMutexExclusive lock(fMessagesMutex);
112 fMessages.push_back(std::move(m));
113}
114
115template <typename Message, typename IDType, bool AllowCopyableMessage>
118 SkASSERT(messages);
119 messages->clear();
120 SkAutoMutexExclusive lock(fMessagesMutex);
121 fMessages.swap(*messages);
122}
123
124// ----------------------- Implementation of SkMessageBus -----------------------
125
126template <typename Message, typename IDType, bool AllowCopyableMessage>
128
129template <typename Message, typename IDType, bool AllowCopyableMessage>
132 SkAutoMutexExclusive lock(bus->fInboxesMutex);
133 for (int i = 0; i < bus->fInboxes.size(); i++) {
134 if (SkShouldPostMessageToBus(m, bus->fInboxes[i]->fUniqueID)) {
135 if constexpr (AllowCopyableMessage) {
136 bus->fInboxes[i]->receive(m);
137 } else {
138 if constexpr (is_sk_sp<Message>::value) {
139 SkASSERT(m->unique());
140 }
141 bus->fInboxes[i]->receive(std::move(m));
142 break;
143 }
144 }
145 }
146
147 if constexpr (is_sk_sp<Message>::value && !AllowCopyableMessage) {
148 // Make sure sk_sp has been sent to an inbox.
149 SkASSERT(!m); // NOLINT(bugprone-use-after-move)
150 }
151}
152
153#endif // SkMessageBus_DEFINED
#define SkASSERT(cond)
Definition SkAssert.h:116
static bool SkShouldPostMessageToBus(const SkResourceCache::PurgeSharedIDMessage &, uint32_t)
void poll(skia_private::TArray< Message > *out)
IDType uniqueID() const
Inbox(IDType uniqueID)
static void Post(Message m)
#define T