// 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/libjingle/source/talk/base/thread.h" namespace jingle_glue { // JingleThreadWrapper implements talk_base::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 talk_base::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(); // Returns thread wrapper for the current thread. NULL is returned // if EnsureForCurrentMessageLoop() has never been called for this // thread. static JingleThreadWrapper* current(); explicit JingleThreadWrapper( scoped_refptr task_runner); virtual ~JingleThreadWrapper(); // 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. virtual void WillDestroyCurrentMessageLoop() OVERRIDE; // talk_base::MessageQueue overrides. virtual void Post(talk_base::MessageHandler *phandler, uint32 id, talk_base::MessageData *pdata, bool time_sensitive) OVERRIDE; virtual void PostDelayed(int delay_ms, talk_base::MessageHandler* handler, uint32 id, talk_base::MessageData* data) OVERRIDE; virtual void Clear(talk_base::MessageHandler* handler, uint32 id, talk_base::MessageList* removed) OVERRIDE; virtual void Send(talk_base::MessageHandler *handler, uint32 id, talk_base::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. virtual void Quit() OVERRIDE; virtual bool IsQuitting() OVERRIDE; virtual void Restart() OVERRIDE; virtual bool Get(talk_base::Message* message, int delay_ms, bool process_io) OVERRIDE; virtual bool Peek(talk_base::Message* message, int delay_ms) OVERRIDE; virtual void PostAt(uint32 timestamp, talk_base::MessageHandler* handler, uint32 id, talk_base::MessageData* data) OVERRIDE; virtual void Dispatch(talk_base::Message* message) OVERRIDE; virtual void ReceiveSends() OVERRIDE; virtual int GetDelay() OVERRIDE; // talk_base::Thread overrides. virtual void Stop() OVERRIDE; virtual void Run() OVERRIDE; private: typedef std::map MessagesQueue; struct PendingSend; void PostTaskInternal( int delay_ms, talk_base::MessageHandler* handler, uint32 message_id, talk_base::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_