1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/skia/trunk/src/core/SkMessageBus.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,116 @@ 1.4 +/* 1.5 + * Copyright 2013 Google Inc. 1.6 + * 1.7 + * Use of this source code is governed by a BSD-style license that can be 1.8 + * found in the LICENSE file. 1.9 + */ 1.10 + 1.11 +#ifndef SkMessageBus_DEFINED 1.12 +#define SkMessageBus_DEFINED 1.13 + 1.14 +#include "SkOnce.h" 1.15 +#include "SkTDArray.h" 1.16 +#include "SkThread.h" 1.17 +#include "SkTypes.h" 1.18 + 1.19 +template <typename Message> 1.20 +class SkMessageBus : SkNoncopyable { 1.21 +public: 1.22 + // Post a message to be received by all Inboxes for this Message type. Threadsafe. 1.23 + static void Post(const Message& m); 1.24 + 1.25 + class Inbox { 1.26 + public: 1.27 + Inbox(); 1.28 + ~Inbox(); 1.29 + 1.30 + // Overwrite out with all the messages we've received since the last call. Threadsafe. 1.31 + void poll(SkTDArray<Message>* out); 1.32 + 1.33 + private: 1.34 + SkTDArray<Message> fMessages; 1.35 + SkMutex fMessagesMutex; 1.36 + 1.37 + friend class SkMessageBus; 1.38 + void receive(const Message& m); // SkMessageBus is a friend only to call this. 1.39 + }; 1.40 + 1.41 +private: 1.42 + SkMessageBus(); 1.43 + static SkMessageBus* Get(); 1.44 + static void New(SkMessageBus**); 1.45 + 1.46 + SkTDArray<Inbox*> fInboxes; 1.47 + SkMutex fInboxesMutex; 1.48 +}; 1.49 + 1.50 +// This must go in a single .cpp file, not some .h, or we risk creating more than one global 1.51 +// SkMessageBus per type when using shared libraries. 1.52 +#define DECLARE_SKMESSAGEBUS_MESSAGE(Message) \ 1.53 + template <> \ 1.54 + SkMessageBus<Message>* SkMessageBus<Message>::Get() { \ 1.55 + static SkMessageBus<Message>* bus = NULL; \ 1.56 + SK_DECLARE_STATIC_ONCE(once); \ 1.57 + SkOnce(&once, &New, &bus); \ 1.58 + SkASSERT(bus != NULL); \ 1.59 + return bus; \ 1.60 + } 1.61 + 1.62 +// ----------------------- Implementation of SkMessageBus::Inbox ----------------------- 1.63 + 1.64 +template<typename Message> 1.65 +SkMessageBus<Message>::Inbox::Inbox() { 1.66 + // Register ourselves with the corresponding message bus. 1.67 + SkMessageBus<Message>* bus = SkMessageBus<Message>::Get(); 1.68 + SkAutoMutexAcquire lock(bus->fInboxesMutex); 1.69 + bus->fInboxes.push(this); 1.70 +} 1.71 + 1.72 +template<typename Message> 1.73 +SkMessageBus<Message>::Inbox::~Inbox() { 1.74 + // Remove ourselves from the corresponding message bus. 1.75 + SkMessageBus<Message>* bus = SkMessageBus<Message>::Get(); 1.76 + SkAutoMutexAcquire lock(bus->fInboxesMutex); 1.77 + // This is a cheaper fInboxes.remove(fInboxes.find(this)) when order doesn't matter. 1.78 + for (int i = 0; i < bus->fInboxes.count(); i++) { 1.79 + if (this == bus->fInboxes[i]) { 1.80 + bus->fInboxes.removeShuffle(i); 1.81 + break; 1.82 + } 1.83 + } 1.84 +} 1.85 + 1.86 +template<typename Message> 1.87 +void SkMessageBus<Message>::Inbox::receive(const Message& m) { 1.88 + SkAutoMutexAcquire lock(fMessagesMutex); 1.89 + fMessages.push(m); 1.90 +} 1.91 + 1.92 +template<typename Message> 1.93 +void SkMessageBus<Message>::Inbox::poll(SkTDArray<Message>* messages) { 1.94 + SkASSERT(NULL != messages); 1.95 + messages->reset(); 1.96 + SkAutoMutexAcquire lock(fMessagesMutex); 1.97 + messages->swap(fMessages); 1.98 +} 1.99 + 1.100 +// ----------------------- Implementation of SkMessageBus ----------------------- 1.101 + 1.102 +template <typename Message> 1.103 +SkMessageBus<Message>::SkMessageBus() {} 1.104 + 1.105 +template <typename Message> 1.106 +/*static*/ void SkMessageBus<Message>::New(SkMessageBus<Message>** bus) { 1.107 + *bus = new SkMessageBus<Message>(); 1.108 +} 1.109 + 1.110 +template <typename Message> 1.111 +/*static*/ void SkMessageBus<Message>::Post(const Message& m) { 1.112 + SkMessageBus<Message>* bus = SkMessageBus<Message>::Get(); 1.113 + SkAutoMutexAcquire lock(bus->fInboxesMutex); 1.114 + for (int i = 0; i < bus->fInboxes.count(); i++) { 1.115 + bus->fInboxes[i]->receive(m); 1.116 + } 1.117 +} 1.118 + 1.119 +#endif // SkMessageBus_DEFINED