Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / skia / src / core / SkMessageBus.h
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 "SkLazyPtr.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.  Threadsafe.
20     static void Post(const Message& m);
21
22     class Inbox {
23     public:
24         Inbox();
25         ~Inbox();
26
27         // Overwrite out with all the messages we've received since the last call.  Threadsafe.
28         void poll(SkTDArray<Message>* out);
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 call this.
36     };
37
38 private:
39     SkMessageBus();
40     static SkMessageBus* Get();
41     static SkMessageBus* New();
42
43     SkTDArray<Inbox*> fInboxes;
44     SkMutex           fInboxesMutex;
45 };
46
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)                        \
50     template <>                                                      \
51     SkMessageBus<Message>* SkMessageBus<Message>::Get() {            \
52         SK_DECLARE_STATIC_LAZY_PTR(SkMessageBus<Message>, bus, New); \
53         return bus.get();                                            \
54     }
55
56 //   ----------------------- Implementation of SkMessageBus::Inbox -----------------------
57
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);
64 }
65
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);
75             break;
76         }
77     }
78 }
79
80 template<typename Message>
81 void SkMessageBus<Message>::Inbox::receive(const Message& m) {
82     SkAutoMutexAcquire lock(fMessagesMutex);
83     fMessages.push(m);
84 }
85
86 template<typename Message>
87 void SkMessageBus<Message>::Inbox::poll(SkTDArray<Message>* messages) {
88     SkASSERT(messages);
89     messages->reset();
90     SkAutoMutexAcquire lock(fMessagesMutex);
91     messages->swap(fMessages);
92 }
93
94 //   ----------------------- Implementation of SkMessageBus -----------------------
95
96 template <typename Message>
97 SkMessageBus<Message>::SkMessageBus() {}
98
99 template <typename Message>
100 /*static*/ SkMessageBus<Message>* SkMessageBus<Message>::New() {
101     return SkNEW(SkMessageBus<Message>);
102 }
103
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);
110     }
111 }
112
113 #endif  // SkMessageBus_DEFINED