1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef JINGLE_GLUE_THREAD_WRAPPER_H_
6#define JINGLE_GLUE_THREAD_WRAPPER_H_
7
8#include <list>
9#include <map>
10
11#include "base/compiler_specific.h"
12#include "base/message_loop/message_loop.h"
13#include "base/synchronization/lock.h"
14#include "base/synchronization/waitable_event.h"
15#include "third_party/libjingle/source/talk/base/thread.h"
16
17namespace jingle_glue {
18
19// JingleThreadWrapper implements talk_base::Thread interface on top of
20// Chromium's SingleThreadTaskRunner interface. Currently only the bare minimum
21// that is used by P2P part of libjingle is implemented. There are two ways to
22// create this object:
23//
24// - Call EnsureForCurrentMessageLoop(). This approach works only on threads
25//   that have MessageLoop In this case JingleThreadWrapper deletes itself
26//   automatically when MessageLoop is destroyed.
27// - Using JingleThreadWrapper() constructor. In this case the creating code
28//   must pass a valid task runner for the current thread and also delete the
29//   wrapper later.
30class JingleThreadWrapper : public base::MessageLoop::DestructionObserver,
31                            public talk_base::Thread {
32 public:
33  // Create JingleThreadWrapper for the current thread if it hasn't been created
34  // yet. The thread wrapper is destroyed automatically when the current
35  // MessageLoop is destroyed.
36  static void EnsureForCurrentMessageLoop();
37
38  // Returns thread wrapper for the current thread. NULL is returned
39  // if EnsureForCurrentMessageLoop() has never been called for this
40  // thread.
41  static JingleThreadWrapper* current();
42
43  explicit JingleThreadWrapper(
44     scoped_refptr<base::SingleThreadTaskRunner> task_runner);
45  virtual ~JingleThreadWrapper();
46
47  // Sets whether the thread can be used to send messages
48  // synchronously to another thread using Send() method. Set to false
49  // by default to avoid potential jankiness when Send() used on
50  // renderer thread. It should be set explicitly for threads that
51  // need to call Send() for other threads.
52  void set_send_allowed(bool allowed) { send_allowed_ = allowed; }
53
54  // MessageLoop::DestructionObserver implementation.
55  virtual void WillDestroyCurrentMessageLoop() OVERRIDE;
56
57  // talk_base::MessageQueue overrides.
58  virtual void Post(talk_base::MessageHandler *phandler,
59                    uint32 id,
60                    talk_base::MessageData *pdata,
61                    bool time_sensitive) OVERRIDE;
62  virtual void PostDelayed(int delay_ms,
63                           talk_base::MessageHandler* handler,
64                           uint32 id,
65                           talk_base::MessageData* data) OVERRIDE;
66  virtual void Clear(talk_base::MessageHandler* handler,
67                     uint32 id,
68                     talk_base::MessageList* removed) OVERRIDE;
69  virtual void Send(talk_base::MessageHandler *handler,
70                    uint32 id,
71                    talk_base::MessageData *data) OVERRIDE;
72
73  // Following methods are not supported.They are overriden just to
74  // ensure that they are not called (each of them contain NOTREACHED
75  // in the body). Some of this methods can be implemented if it
76  // becomes neccessary to use libjingle code that calls them.
77  virtual void Quit() OVERRIDE;
78  virtual bool IsQuitting() OVERRIDE;
79  virtual void Restart() OVERRIDE;
80  virtual bool Get(talk_base::Message* message,
81                   int delay_ms,
82                   bool process_io) OVERRIDE;
83  virtual bool Peek(talk_base::Message* message,
84                    int delay_ms) OVERRIDE;
85  virtual void PostAt(uint32 timestamp,
86                      talk_base::MessageHandler* handler,
87                      uint32 id,
88                      talk_base::MessageData* data) OVERRIDE;
89  virtual void Dispatch(talk_base::Message* message) OVERRIDE;
90  virtual void ReceiveSends() OVERRIDE;
91  virtual int GetDelay() OVERRIDE;
92
93  // talk_base::Thread overrides.
94  virtual void Stop() OVERRIDE;
95  virtual void Run() OVERRIDE;
96
97 private:
98  typedef std::map<int, talk_base::Message> MessagesQueue;
99  struct PendingSend;
100
101  void PostTaskInternal(
102      int delay_ms, talk_base::MessageHandler* handler,
103      uint32 message_id, talk_base::MessageData* data);
104  void RunTask(int task_id);
105  void ProcessPendingSends();
106
107  // Task runner used to execute messages posted on this thread.
108  scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
109
110  bool send_allowed_;
111
112  // |lock_| must be locked when accessing |messages_|.
113  base::Lock lock_;
114  int last_task_id_;
115  MessagesQueue messages_;
116  std::list<PendingSend*> pending_send_messages_;
117  base::WaitableEvent pending_send_event_;
118
119  base::WeakPtr<JingleThreadWrapper> weak_ptr_;
120  base::WeakPtrFactory<JingleThreadWrapper> weak_ptr_factory_;
121
122  DISALLOW_COPY_AND_ASSIGN(JingleThreadWrapper);
123};
124
125}  // namespace jingle_glue
126
127#endif  // JINGLE_GLUE_THREAD_WRAPPER_H_
128