summaryrefslogtreecommitdiffstats
path: root/media/cast/logging/log_event_dispatcher.cc
diff options
context:
space:
mode:
Diffstat (limited to 'media/cast/logging/log_event_dispatcher.cc')
-rw-r--r--media/cast/logging/log_event_dispatcher.cc137
1 files changed, 137 insertions, 0 deletions
diff --git a/media/cast/logging/log_event_dispatcher.cc b/media/cast/logging/log_event_dispatcher.cc
new file mode 100644
index 0000000..ac0e9ab
--- /dev/null
+++ b/media/cast/logging/log_event_dispatcher.cc
@@ -0,0 +1,137 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "media/cast/logging/log_event_dispatcher.h"
+
+#include <algorithm>
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/location.h"
+#include "base/synchronization/waitable_event.h"
+#include "media/cast/cast_environment.h"
+
+namespace media {
+namespace cast {
+
+LogEventDispatcher::LogEventDispatcher(CastEnvironment* env)
+ : env_(env), impl_(new Impl()) {
+ DCHECK(env_);
+}
+
+LogEventDispatcher::~LogEventDispatcher() {}
+
+void LogEventDispatcher::DispatchFrameEvent(
+ scoped_ptr<FrameEvent> event) const {
+ if (env_->CurrentlyOn(CastEnvironment::MAIN)) {
+ impl_->DispatchFrameEvent(event.Pass());
+ } else {
+ env_->PostTask(CastEnvironment::MAIN, FROM_HERE,
+ base::Bind(&LogEventDispatcher::Impl::DispatchFrameEvent,
+ impl_, base::Passed(&event)));
+ }
+}
+
+void LogEventDispatcher::DispatchPacketEvent(
+ scoped_ptr<PacketEvent> event) const {
+ if (env_->CurrentlyOn(CastEnvironment::MAIN)) {
+ impl_->DispatchPacketEvent(event.Pass());
+ } else {
+ env_->PostTask(CastEnvironment::MAIN, FROM_HERE,
+ base::Bind(&LogEventDispatcher::Impl::DispatchPacketEvent,
+ impl_, base::Passed(&event)));
+ }
+}
+
+void LogEventDispatcher::DispatchBatchOfEvents(
+ scoped_ptr<std::vector<FrameEvent>> frame_events,
+ scoped_ptr<std::vector<PacketEvent>> packet_events) const {
+ if (env_->CurrentlyOn(CastEnvironment::MAIN)) {
+ impl_->DispatchBatchOfEvents(frame_events.Pass(), packet_events.Pass());
+ } else {
+ env_->PostTask(
+ CastEnvironment::MAIN, FROM_HERE,
+ base::Bind(&LogEventDispatcher::Impl::DispatchBatchOfEvents, impl_,
+ base::Passed(&frame_events), base::Passed(&packet_events)));
+ }
+}
+
+void LogEventDispatcher::Subscribe(RawEventSubscriber* subscriber) {
+ if (env_->CurrentlyOn(CastEnvironment::MAIN)) {
+ impl_->Subscribe(subscriber);
+ } else {
+ env_->PostTask(
+ CastEnvironment::MAIN, FROM_HERE,
+ base::Bind(&LogEventDispatcher::Impl::Subscribe, impl_, subscriber));
+ }
+}
+
+void LogEventDispatcher::Unsubscribe(RawEventSubscriber* subscriber) {
+ if (env_->CurrentlyOn(CastEnvironment::MAIN)) {
+ impl_->Unsubscribe(subscriber);
+ } else {
+ // This method, once it returns, guarantees |subscriber| will not receive
+ // any more events. Therefore, when called on a thread other than the
+ // CastEnvironment's MAIN thread, block until the unsubscribe task
+ // completes.
+ struct Helper {
+ static void UnsubscribeAndSignal(const scoped_refptr<Impl>& impl,
+ RawEventSubscriber* subscriber,
+ base::WaitableEvent* done) {
+ impl->Unsubscribe(subscriber);
+ done->Signal();
+ }
+ };
+ base::WaitableEvent done(true, false);
+ CHECK(env_->PostTask(
+ CastEnvironment::MAIN, FROM_HERE,
+ base::Bind(&Helper::UnsubscribeAndSignal, impl_, subscriber, &done)));
+ done.Wait();
+ }
+}
+
+LogEventDispatcher::Impl::Impl() {}
+
+LogEventDispatcher::Impl::~Impl() {
+ DCHECK(subscribers_.empty());
+}
+
+void LogEventDispatcher::Impl::DispatchFrameEvent(
+ scoped_ptr<FrameEvent> event) const {
+ for (RawEventSubscriber* s : subscribers_)
+ s->OnReceiveFrameEvent(*event);
+}
+
+void LogEventDispatcher::Impl::DispatchPacketEvent(
+ scoped_ptr<PacketEvent> event) const {
+ for (RawEventSubscriber* s : subscribers_)
+ s->OnReceivePacketEvent(*event);
+}
+
+void LogEventDispatcher::Impl::DispatchBatchOfEvents(
+ scoped_ptr<std::vector<FrameEvent>> frame_events,
+ scoped_ptr<std::vector<PacketEvent>> packet_events) const {
+ for (RawEventSubscriber* s : subscribers_) {
+ for (const FrameEvent& e : *frame_events)
+ s->OnReceiveFrameEvent(e);
+ for (const PacketEvent& e : *packet_events)
+ s->OnReceivePacketEvent(e);
+ }
+}
+
+void LogEventDispatcher::Impl::Subscribe(RawEventSubscriber* subscriber) {
+ DCHECK(std::find(subscribers_.begin(), subscribers_.end(), subscriber) ==
+ subscribers_.end());
+ subscribers_.push_back(subscriber);
+}
+
+void LogEventDispatcher::Impl::Unsubscribe(RawEventSubscriber* subscriber) {
+ const auto it =
+ std::find(subscribers_.begin(), subscribers_.end(), subscriber);
+ DCHECK(it != subscribers_.end());
+ subscribers_.erase(it);
+}
+
+} // namespace cast
+} // namespace media