Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 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 "SkOnce.h" | |
| 12 #include "SkTDArray.h" | |
| 13 #include "SkThread.h" | |
| 14 #include "SkTypes.h" | |
| 15 | |
| 16 template <typename Message> | |
| 17 class SkMessageBus : SkNoncopyable { | |
| 18 public: | |
| 19 // Post a message to be received by all Inboxes for this Message type. Thre adsafe. | |
| 20 static void post(const Message& m); | |
| 21 | |
| 22 class Inbox { | |
| 23 public: | |
| 24 Inbox(); | |
| 25 ~Inbox(); | |
|
scroggo
2013/10/22 21:04:02
Should this be virtual?
mtklein
2013/10/23 15:28:10
Nope. No virtual methods on Inbox (or SkMessageBu
| |
| 26 | |
| 27 // Make messages contain all the messages we've received since the last call. Threadsafe. | |
|
scroggo
2013/10/22 21:04:02
I find this comment hard to read - it would help t
bsalomon
2013/10/23 13:52:57
"The array messages"?
mtklein
2013/10/23 15:28:10
Better?
bsalomon
2013/10/23 15:32:27
ok by me
scroggo
2013/10/23 15:39:19
Yes.
| |
| 28 void poll(SkTDArray<Message>* messages); | |
| 29 | |
| 30 private: | |
| 31 SkTDArray<Message> fMessages; | |
| 32 SkMutex fMessagesMutex; | |
| 33 | |
| 34 friend class SkMessageBus; | |
| 35 void receive(const Message& m); // SkMessageBus is a friend only to cal l this. | |
| 36 }; | |
| 37 | |
| 38 private: | |
| 39 SkMessageBus(); | |
| 40 static SkMessageBus* Get(); | |
| 41 static void New(SkMessageBus**); | |
| 42 | |
| 43 SkTDArray<Inbox*> fInboxes; | |
| 44 SkMutex fInboxesMutex; | |
| 45 }; | |
| 46 | |
| 47 // ----------------------- Implementation of SkMessageBus::Inbox ------------- ---------- | |
| 48 | |
| 49 template<typename Message> | |
| 50 SkMessageBus<Message>::Inbox::Inbox() { | |
| 51 // Register ourselves with the corresponding message bus. | |
| 52 SkMessageBus<Message>* bus = SkMessageBus<Message>::Get(); | |
| 53 SkAutoMutexAcquire lock(bus->fInboxesMutex); | |
| 54 bus->fInboxes.push(this); | |
| 55 } | |
| 56 | |
| 57 template<typename Message> | |
| 58 SkMessageBus<Message>::Inbox::~Inbox() { | |
| 59 // Remove ourselves from the corresponding message bus. | |
| 60 SkMessageBus<Message>* bus = SkMessageBus<Message>::Get(); | |
| 61 SkAutoMutexAcquire lock(bus->fInboxesMutex); | |
| 62 // This is a cheaper fInboxes.remove(fInboxes.find(this)) when order doesn't matter. | |
|
scroggo
2013/10/22 21:04:02
Clever. Should this be an option on SkTDArray?
bsalomon
2013/10/23 13:52:57
It already is: removeShuffle
mtklein
2013/10/23 15:28:10
Ah! Missed that. Updated.
| |
| 63 for (int i = 0; i < bus->fInboxes.count(); i++) { | |
| 64 if (this == bus->fInboxes[i]) { | |
| 65 bus->fInboxes[i] = bus->fInboxes.top(); | |
| 66 bus->fInboxes.pop(); | |
| 67 break; | |
| 68 } | |
| 69 } | |
| 70 } | |
| 71 | |
| 72 template<typename Message> | |
| 73 void SkMessageBus<Message>::Inbox::receive(const Message& m) { | |
| 74 SkAutoMutexAcquire lock(fMessagesMutex); | |
| 75 fMessages.push(m); | |
| 76 } | |
| 77 | |
| 78 template<typename Message> | |
| 79 void SkMessageBus<Message>::Inbox::poll(SkTDArray<Message>* messages) { | |
| 80 messages->reset(); | |
|
scroggo
2013/10/22 21:04:02
Should we check for NULL or assert non NULL?
mtklein
2013/10/23 15:28:10
Yes. Added an assert.
| |
| 81 SkAutoMutexAcquire lock(fMessagesMutex); | |
| 82 messages->swap(fMessages); | |
| 83 } | |
| 84 | |
| 85 // ----------------------- Implementation of SkMessageBus -------------------- --- | |
| 86 | |
| 87 template <typename Message> | |
| 88 SkMessageBus<Message>::SkMessageBus() {} | |
| 89 | |
| 90 template <typename Message> | |
| 91 /*static*/ void SkMessageBus<Message>::New(SkMessageBus<Message>** bus) { | |
| 92 *bus = new SkMessageBus<Message>(); | |
| 93 } | |
| 94 | |
| 95 template <typename Message> | |
| 96 /*static*/ SkMessageBus<Message>* SkMessageBus<Message>::Get() { | |
| 97 // The first time this method is called, create the singleton bus for this m essage type. | |
| 98 static SkMessageBus<Message>* bus = NULL; | |
| 99 static bool initialized = false; | |
| 100 SK_DECLARE_STATIC_MUTEX(mutex); | |
| 101 | |
| 102 sk_once(&initialized, &mutex, &New, &bus); | |
| 103 | |
| 104 SkASSERT(bus != NULL); | |
| 105 return bus; | |
| 106 } | |
| 107 | |
| 108 template <typename Message> | |
| 109 /*static*/ void SkMessageBus<Message>::post(const Message& m) { | |
|
bsalomon
2013/10/23 13:52:57
Is the Get()/post() pattern useful? Could we just
mtklein
2013/10/23 15:28:10
Ah, this may just be an issue with my tenuous gras
bsalomon
2013/10/23 15:32:27
Ha... I should have realized that from the impl.
| |
| 110 SkMessageBus<Message>* bus = SkMessageBus<Message>::Get(); | |
| 111 SkAutoMutexAcquire lock(bus->fInboxesMutex); | |
| 112 for (int i = 0; i < bus->fInboxes.count(); i++) { | |
| 113 bus->fInboxes[i]->receive(m); | |
| 114 } | |
| 115 } | |
| 116 | |
| 117 #endif // SkMessageBus_DEFINED | |
| OLD | NEW |