skia2/src/core/SkMessageBus.h
commit-bot@chromium.org f71e8fd0c5 Revert of Port most uses of SkOnce to SkLazyPtr. (https://codereview.chromium.org/304383005/)
Reason for revert:
linux x86-64 release segfault in src/ports/SkFontHost_fontconfig.cpp:107

http://108.170.220.120:10117/builders/Test-Ubuntu12-ShuttleA-GTX660-x86_64-Release/builds/905/steps/RunTests/logs/stdio

Original issue's description:
> Port most uses of SkOnce to SkLazyPtr.
>
> BUG=skia:
>
> Committed: http://code.google.com/p/skia/source/detail?r=15006
>
> Committed: http://code.google.com/p/skia/source/detail?r=15014

R=reed@google.com, mtklein@chromium.org
TBR=mtklein@chromium.org, reed@google.com
NOTREECHECKS=true
NOTRY=true
BUG=skia:

Author: mtklein@google.com

Review URL: https://codereview.chromium.org/306063004

git-svn-id: http://skia.googlecode.com/svn/trunk@15015 2bbb7eff-a529-9590-31e7-b0007b416f81
2014-05-31 00:15:22 +00:00

117 lines
3.5 KiB
C++

/*
* 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;
};
// This must go in a single .cpp file, not some .h, or we risk creating more than one global
// SkMessageBus per type when using shared libraries.
#define DECLARE_SKMESSAGEBUS_MESSAGE(Message) \
template <> \
SkMessageBus<Message>* SkMessageBus<Message>::Get() { \
static SkMessageBus<Message>* bus = NULL; \
SK_DECLARE_STATIC_ONCE(once); \
SkOnce(&once, &New, &bus); \
SkASSERT(bus != NULL); \
return bus; \
}
// ----------------------- 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*/ 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