Bug 1193117. Add an exclusive mode to allow at most one listener. r=kinetik.

This commit is contained in:
JW Wang 2015-08-14 13:01:03 +08:00
Родитель 56e8e38eb3
Коммит 003fc818b3
1 изменённых файлов: 15 добавлений и 5 удалений

Просмотреть файл

@ -47,6 +47,15 @@ private:
Atomic<bool> mRevoked;
};
enum class ListenerMode : int8_t {
// Allow at most one listener. Move will be used when possible
// to pass the event data to save copy.
Exclusive,
// This is the default. Event data will always be copied when passed
// to the listeners.
NonExclusive
};
namespace detail {
/**
@ -111,7 +120,7 @@ private:
} // namespace detail
template <typename T> class MediaEventSource;
template <typename T, ListenerMode> class MediaEventSource;
/**
* Not thread-safe since this is not meant to be shared and therefore only
@ -120,7 +129,7 @@ template <typename T> class MediaEventSource;
* listener from an event source.
*/
class MediaEventListener {
template <typename T>
template <typename T, ListenerMode>
friend class MediaEventSource;
public:
@ -154,7 +163,7 @@ private:
/**
* A generic and thread-safe class to implement the observer pattern.
*/
template <typename EventType>
template <typename EventType, ListenerMode Mode = ListenerMode::NonExclusive>
class MediaEventSource {
static_assert(!IsReference<EventType>::value, "Ref-type not supported!");
typedef typename detail::EventTypeTraits<EventType>::ArgType ArgType;
@ -246,6 +255,7 @@ class MediaEventSource {
MediaEventListener
ConnectInternal(Target* aTarget, const Function& aFunction) {
MutexAutoLock lock(mMutex);
MOZ_ASSERT(Mode == ListenerMode::NonExclusive || mListeners.IsEmpty());
auto l = mListeners.AppendElement();
l->reset(new ListenerImpl<Target, Function>(aTarget, aFunction));
return MediaEventListener((*l)->Token());
@ -346,8 +356,8 @@ private:
* and event publisher. Mostly used as a member variable to publish events
* to the listeners.
*/
template <typename EventType>
class MediaEventProducer : public MediaEventSource<EventType> {
template <typename EventType, ListenerMode Mode = ListenerMode::NonExclusive>
class MediaEventProducer : public MediaEventSource<EventType, Mode> {
public:
void Notify(const EventType& aEvent) {
this->NotifyInternal(aEvent);