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 |