// Copyright (c) 2012 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. #ifndef JINGLE_GLUE_THREAD_WRAPPER_H_ #define JINGLE_GLUE_THREAD_WRAPPER_H_ #include #include #include "base/compiler_specific.h" #include "base/message_loop/message_loop.h" #include "base/synchronization/lock.h" #include "base/synchronization/waitable_event.h" #include "third_party/webrtc/base/thread.h" namespace jingle_glue { // JingleThreadWrapper implements rtc::Thread interface on top of // Chromium's SingleThreadTaskRunner interface. Currently only the bare minimum // that is used by P2P part of libjingle is implemented. There are two ways to // create this object: // // - Call EnsureForCurrentMessageLoop(). This approach works only on threads // that have MessageLoop In this case JingleThreadWrapper deletes itself // automatically when MessageLoop is destroyed. // - Using JingleThreadWrapper() constructor. In this case the creating code // must pass a valid task runner for the current thread and also delete the // wrapper later. class JingleThreadWrapper : public base::MessageLoop::DestructionObserver, public rtc::Thread { public: // Create JingleThreadWrapper for the current thread if it hasn't been created // yet. The thread wrapper is destroyed automatically when the current // MessageLoop is destroyed. static void EnsureForCurrentMessageLoop(); // Creates JingleThreadWrapper for |task_runner| that runs tasks on the // current thread. static scoped_ptr WrapTaskRunner( scoped_refptr task_runner); // Returns thread wrapper for the current thread or nullptr if it doesn't // exist. static JingleThreadWrapper* current(); ~JingleThreadWrapper() override; // Sets whether the thread can be used to send messages // synchronously to another thread using Send() method. Set to false // by default to avoid potential jankiness when Send() used on // renderer thread. It should be set explicitly for threads that // need to call Send() for other threads. void set_send_allowed(bool allowed) { send_allowed_ = allowed; } // MessageLoop::DestructionObserver implementation. void WillDestroyCurrentMessageLoop() override; // rtc::MessageQueue overrides. void Post(rtc::MessageHandler* phandler, uint32 id, rtc::MessageData* pdata, bool time_sensitive) override; void PostDelayed(int delay_ms, rtc::MessageHandler* handler, uint32 id, rtc::MessageData* data) override; void Clear(rtc::MessageHandler* handler, uint32 id, rtc::MessageList* removed) override; void Send(rtc::MessageHandler* handler, uint32 id, rtc::MessageData* data) override; // Following methods are not supported.They are overriden just to // ensure that they are not called (each of them contain NOTREACHED // in the body). Some of this methods can be implemented if it // becomes neccessary to use libjingle code that calls them. void Quit() override; bool IsQuitting() override; void Restart() override; bool Get(rtc::Message* message, int delay_ms, bool process_io) override; bool Peek(rtc::Message* message, int delay_ms) override; void PostAt(uint32 timestamp, rtc::MessageHandler* handler, uint32 id, rtc::MessageData* data) override; void Dispatch(rtc::Message* message) override; void ReceiveSends() override; int GetDelay() override; // rtc::Thread overrides. void Stop() override; void Run() override; private: typedef std::map MessagesQueue; struct PendingSend; explicit JingleThreadWrapper( scoped_refptr task_runner); void PostTaskInternal( int delay_ms, rtc::MessageHandler* handler, uint32 message_id, rtc::MessageData* data); void RunTask(int task_id); void ProcessPendingSends(); // Task runner used to execute messages posted on this thread. scoped_refptr task_runner_; bool send_allowed_; // |lock_| must be locked when accessing |messages_|. base::Lock lock_; int last_task_id_; MessagesQueue messages_; std::list pending_send_messages_; base::WaitableEvent pending_send_event_; base::WeakPtr weak_ptr_; base::WeakPtrFactory weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(JingleThreadWrapper); }; } // namespace jingle_glue #endif // JINGLE_GLUE_THREAD_WRAPPER_H_