150a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org/* 250a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org * Copyright 2013 Google Inc. 350a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org * 450a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org * Use of this source code is governed by a BSD-style license that can be 550a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org * found in the LICENSE file. 650a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org */ 750a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org 850a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org#ifndef SkMessageBus_DEFINED 950a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org#define SkMessageBus_DEFINED 1050a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org 1178358bf624c7e7c09ffccf638c50870808d884d6mtklein#include "SkLazyPtr.h" 1250a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org#include "SkTDArray.h" 1350a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org#include "SkThread.h" 1450a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org#include "SkTypes.h" 1550a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org 1650a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.orgtemplate <typename Message> 1750a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.orgclass SkMessageBus : SkNoncopyable { 1850a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.orgpublic: 1950a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org // Post a message to be received by all Inboxes for this Message type. Threadsafe. 2050a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org static void Post(const Message& m); 2150a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org 2250a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org class Inbox { 2350a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org public: 2450a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org Inbox(); 2550a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org ~Inbox(); 2650a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org 2750a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org // Overwrite out with all the messages we've received since the last call. Threadsafe. 2850a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org void poll(SkTDArray<Message>* out); 2950a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org 3050a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org private: 3150a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org SkTDArray<Message> fMessages; 3250a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org SkMutex fMessagesMutex; 3350a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org 3450a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org friend class SkMessageBus; 3550a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org void receive(const Message& m); // SkMessageBus is a friend only to call this. 3650a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org }; 3750a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org 3850a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.orgprivate: 3950a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org SkMessageBus(); 4050a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org static SkMessageBus* Get(); 4178358bf624c7e7c09ffccf638c50870808d884d6mtklein static SkMessageBus* New(); 4250a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org 4350a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org SkTDArray<Inbox*> fInboxes; 4450a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org SkMutex fInboxesMutex; 4550a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org}; 4650a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org 47c665804300096c2e7617379835bb83d715538788commit-bot@chromium.org// This must go in a single .cpp file, not some .h, or we risk creating more than one global 48c665804300096c2e7617379835bb83d715538788commit-bot@chromium.org// SkMessageBus per type when using shared libraries. 4978358bf624c7e7c09ffccf638c50870808d884d6mtklein#define DECLARE_SKMESSAGEBUS_MESSAGE(Message) \ 5078358bf624c7e7c09ffccf638c50870808d884d6mtklein template <> \ 5178358bf624c7e7c09ffccf638c50870808d884d6mtklein SkMessageBus<Message>* SkMessageBus<Message>::Get() { \ 5278358bf624c7e7c09ffccf638c50870808d884d6mtklein SK_DECLARE_STATIC_LAZY_PTR(SkMessageBus<Message>, bus, New); \ 5378358bf624c7e7c09ffccf638c50870808d884d6mtklein return bus.get(); \ 54c665804300096c2e7617379835bb83d715538788commit-bot@chromium.org } 55c665804300096c2e7617379835bb83d715538788commit-bot@chromium.org 5650a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org// ----------------------- Implementation of SkMessageBus::Inbox ----------------------- 5750a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org 5850a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.orgtemplate<typename Message> 5950a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.orgSkMessageBus<Message>::Inbox::Inbox() { 6050a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org // Register ourselves with the corresponding message bus. 6150a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org SkMessageBus<Message>* bus = SkMessageBus<Message>::Get(); 6250a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org SkAutoMutexAcquire lock(bus->fInboxesMutex); 6350a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org bus->fInboxes.push(this); 6450a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org} 6550a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org 6650a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.orgtemplate<typename Message> 6750a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.orgSkMessageBus<Message>::Inbox::~Inbox() { 6850a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org // Remove ourselves from the corresponding message bus. 6950a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org SkMessageBus<Message>* bus = SkMessageBus<Message>::Get(); 7050a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org SkAutoMutexAcquire lock(bus->fInboxesMutex); 7150a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org // This is a cheaper fInboxes.remove(fInboxes.find(this)) when order doesn't matter. 7250a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org for (int i = 0; i < bus->fInboxes.count(); i++) { 7350a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org if (this == bus->fInboxes[i]) { 7450a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org bus->fInboxes.removeShuffle(i); 7550a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org break; 7650a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org } 7750a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org } 7850a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org} 7950a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org 8050a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.orgtemplate<typename Message> 8150a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.orgvoid SkMessageBus<Message>::Inbox::receive(const Message& m) { 8250a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org SkAutoMutexAcquire lock(fMessagesMutex); 8350a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org fMessages.push(m); 8450a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org} 8550a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org 8650a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.orgtemplate<typename Message> 8750a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.orgvoid SkMessageBus<Message>::Inbox::poll(SkTDArray<Message>* messages) { 8850a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org SkASSERT(NULL != messages); 8950a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org messages->reset(); 9050a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org SkAutoMutexAcquire lock(fMessagesMutex); 9150a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org messages->swap(fMessages); 9250a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org} 9350a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org 9450a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org// ----------------------- Implementation of SkMessageBus ----------------------- 9550a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org 9650a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.orgtemplate <typename Message> 9750a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.orgSkMessageBus<Message>::SkMessageBus() {} 9850a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org 9950a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.orgtemplate <typename Message> 10078358bf624c7e7c09ffccf638c50870808d884d6mtklein/*static*/ SkMessageBus<Message>* SkMessageBus<Message>::New() { 10178358bf624c7e7c09ffccf638c50870808d884d6mtklein return SkNEW(SkMessageBus<Message>); 10250a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org} 10350a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org 10450a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.orgtemplate <typename Message> 10550a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org/*static*/ void SkMessageBus<Message>::Post(const Message& m) { 10650a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org SkMessageBus<Message>* bus = SkMessageBus<Message>::Get(); 10750a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org SkAutoMutexAcquire lock(bus->fInboxesMutex); 10850a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org for (int i = 0; i < bus->fInboxes.count(); i++) { 10950a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org bus->fInboxes[i]->receive(m); 11050a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org } 11150a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org} 11250a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org 11350a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org#endif // SkMessageBus_DEFINED 114