| Index: src/core/SkMessageBus.h
|
| diff --git a/src/core/SkMessageBus.h b/src/core/SkMessageBus.h
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..0a408319c15ef197c4cfbf02398d7168e1cae813
|
| --- /dev/null
|
| +++ b/src/core/SkMessageBus.h
|
| @@ -0,0 +1,115 @@
|
| +/*
|
| + * Copyright 2013 Google Inc.
|
| + *
|
| + * Use of this source code is governed by a BSD-style license that can be
|
| + * found in the LICENSE file.
|
| + */
|
| +
|
| +#ifndef SkMessageBus_DEFINED
|
| +#define SkMessageBus_DEFINED
|
| +
|
| +#include "SkOnce.h"
|
| +#include "SkTDArray.h"
|
| +#include "SkThread.h"
|
| +#include "SkTypes.h"
|
| +
|
| +template <typename Message>
|
| +class SkMessageBus : SkNoncopyable {
|
| +public:
|
| + // Post a message to be received by all Inboxes for this Message type. Threadsafe.
|
| + static void Post(const Message& m);
|
| +
|
| + class Inbox {
|
| + public:
|
| + Inbox();
|
| + ~Inbox();
|
| +
|
| + // Overwrite out with all the messages we've received since the last call. Threadsafe.
|
| + void poll(SkTDArray<Message>* out);
|
| +
|
| + private:
|
| + SkTDArray<Message> fMessages;
|
| + SkMutex fMessagesMutex;
|
| +
|
| + friend class SkMessageBus;
|
| + void receive(const Message& m); // SkMessageBus is a friend only to call this.
|
| + };
|
| +
|
| +private:
|
| + SkMessageBus();
|
| + static SkMessageBus* Get();
|
| + static void New(SkMessageBus**);
|
| +
|
| + SkTDArray<Inbox*> fInboxes;
|
| + SkMutex fInboxesMutex;
|
| +};
|
| +
|
| +// ----------------------- Implementation of SkMessageBus::Inbox -----------------------
|
| +
|
| +template<typename Message>
|
| +SkMessageBus<Message>::Inbox::Inbox() {
|
| + // Register ourselves with the corresponding message bus.
|
| + SkMessageBus<Message>* bus = SkMessageBus<Message>::Get();
|
| + SkAutoMutexAcquire lock(bus->fInboxesMutex);
|
| + bus->fInboxes.push(this);
|
| +}
|
| +
|
| +template<typename Message>
|
| +SkMessageBus<Message>::Inbox::~Inbox() {
|
| + // Remove ourselves from the corresponding message bus.
|
| + SkMessageBus<Message>* bus = SkMessageBus<Message>::Get();
|
| + SkAutoMutexAcquire lock(bus->fInboxesMutex);
|
| + // This is a cheaper fInboxes.remove(fInboxes.find(this)) when order doesn't matter.
|
| + for (int i = 0; i < bus->fInboxes.count(); i++) {
|
| + if (this == bus->fInboxes[i]) {
|
| + bus->fInboxes.removeShuffle(i);
|
| + break;
|
| + }
|
| + }
|
| +}
|
| +
|
| +template<typename Message>
|
| +void SkMessageBus<Message>::Inbox::receive(const Message& m) {
|
| + SkAutoMutexAcquire lock(fMessagesMutex);
|
| + fMessages.push(m);
|
| +}
|
| +
|
| +template<typename Message>
|
| +void SkMessageBus<Message>::Inbox::poll(SkTDArray<Message>* messages) {
|
| + SkASSERT(NULL != messages);
|
| + messages->reset();
|
| + SkAutoMutexAcquire lock(fMessagesMutex);
|
| + messages->swap(fMessages);
|
| +}
|
| +
|
| +// ----------------------- Implementation of SkMessageBus -----------------------
|
| +
|
| +template <typename Message>
|
| +SkMessageBus<Message>::SkMessageBus() {}
|
| +
|
| +template <typename Message>
|
| +/*static*/ void SkMessageBus<Message>::New(SkMessageBus<Message>** bus) {
|
| + *bus = new SkMessageBus<Message>();
|
| +}
|
| +
|
| +template <typename Message>
|
| +/*static*/ SkMessageBus<Message>* SkMessageBus<Message>::Get() {
|
| + // The first time this method is called, create the singleton bus for this message type.
|
| + static SkMessageBus<Message>* bus = NULL;
|
| + SK_DECLARE_STATIC_ONCE(once);
|
| + SkOnce(&once, &New, &bus);
|
| +
|
| + SkASSERT(bus != NULL);
|
| + return bus;
|
| +}
|
| +
|
| +template <typename Message>
|
| +/*static*/ void SkMessageBus<Message>::Post(const Message& m) {
|
| + SkMessageBus<Message>* bus = SkMessageBus<Message>::Get();
|
| + SkAutoMutexAcquire lock(bus->fInboxesMutex);
|
| + for (int i = 0; i < bus->fInboxes.count(); i++) {
|
| + bus->fInboxes[i]->receive(m);
|
| + }
|
| +}
|
| +
|
| +#endif // SkMessageBus_DEFINED
|
|
|