2 * Copyright 2013 Google Inc.
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
8 #ifndef SkMessageBus_DEFINED
9 #define SkMessageBus_DEFINED
11 #include "SkLazyPtr.h"
12 #include "SkTDArray.h"
16 template <typename Message>
17 class SkMessageBus : SkNoncopyable {
19 // Post a message to be received by all Inboxes for this Message type. Threadsafe.
20 static void Post(const Message& m);
27 // Overwrite out with all the messages we've received since the last call. Threadsafe.
28 void poll(SkTDArray<Message>* out);
31 SkTDArray<Message> fMessages;
32 SkMutex fMessagesMutex;
34 friend class SkMessageBus;
35 void receive(const Message& m); // SkMessageBus is a friend only to call this.
40 static SkMessageBus* Get();
41 static SkMessageBus* New();
43 SkTDArray<Inbox*> fInboxes;
44 SkMutex fInboxesMutex;
47 // This must go in a single .cpp file, not some .h, or we risk creating more than one global
48 // SkMessageBus per type when using shared libraries.
49 #define DECLARE_SKMESSAGEBUS_MESSAGE(Message) \
51 SkMessageBus<Message>* SkMessageBus<Message>::Get() { \
52 SK_DECLARE_STATIC_LAZY_PTR(SkMessageBus<Message>, bus, New); \
56 // ----------------------- Implementation of SkMessageBus::Inbox -----------------------
58 template<typename Message>
59 SkMessageBus<Message>::Inbox::Inbox() {
60 // Register ourselves with the corresponding message bus.
61 SkMessageBus<Message>* bus = SkMessageBus<Message>::Get();
62 SkAutoMutexAcquire lock(bus->fInboxesMutex);
63 bus->fInboxes.push(this);
66 template<typename Message>
67 SkMessageBus<Message>::Inbox::~Inbox() {
68 // Remove ourselves from the corresponding message bus.
69 SkMessageBus<Message>* bus = SkMessageBus<Message>::Get();
70 SkAutoMutexAcquire lock(bus->fInboxesMutex);
71 // This is a cheaper fInboxes.remove(fInboxes.find(this)) when order doesn't matter.
72 for (int i = 0; i < bus->fInboxes.count(); i++) {
73 if (this == bus->fInboxes[i]) {
74 bus->fInboxes.removeShuffle(i);
80 template<typename Message>
81 void SkMessageBus<Message>::Inbox::receive(const Message& m) {
82 SkAutoMutexAcquire lock(fMessagesMutex);
86 template<typename Message>
87 void SkMessageBus<Message>::Inbox::poll(SkTDArray<Message>* messages) {
90 SkAutoMutexAcquire lock(fMessagesMutex);
91 messages->swap(fMessages);
94 // ----------------------- Implementation of SkMessageBus -----------------------
96 template <typename Message>
97 SkMessageBus<Message>::SkMessageBus() {}
99 template <typename Message>
100 /*static*/ SkMessageBus<Message>* SkMessageBus<Message>::New() {
101 return SkNEW(SkMessageBus<Message>);
104 template <typename Message>
105 /*static*/ void SkMessageBus<Message>::Post(const Message& m) {
106 SkMessageBus<Message>* bus = SkMessageBus<Message>::Get();
107 SkAutoMutexAcquire lock(bus->fInboxesMutex);
108 for (int i = 0; i < bus->fInboxes.count(); i++) {
109 bus->fInboxes[i]->receive(m);
113 #endif // SkMessageBus_DEFINED