diff options
Diffstat (limited to 'media/cast/logging/log_event_dispatcher.cc')
-rw-r--r-- | media/cast/logging/log_event_dispatcher.cc | 137 |
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 |