gfx/skia/trunk/src/core/SkMessageBus.h

changeset 0
6474c204b198
     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

mercurial