message_loop_thread.h 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. /*
  2. * Copyright 2018 The Android Open Source Project
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #pragma once
  17. #include <unistd.h>
  18. #include <future>
  19. #include <memory>
  20. #include <string>
  21. #include <thread>
  22. #include <base/bind.h>
  23. #include <base/location.h>
  24. #include <base/message_loop/message_loop.h>
  25. #include <base/run_loop.h>
  26. #include <base/threading/platform_thread.h>
  27. namespace bluetooth {
  28. namespace common {
  29. /**
  30. * An interface to various thread related functionality
  31. */
  32. class MessageLoopThread final {
  33. public:
  34. /**
  35. * Create a message loop thread with name. Thread won't be running until
  36. * StartUp is called.
  37. *
  38. * @param thread_name name of this worker thread
  39. */
  40. explicit MessageLoopThread(const std::string& thread_name);
  41. /**
  42. * Destroys the message loop thread automatically when it goes out of scope
  43. */
  44. ~MessageLoopThread();
  45. /**
  46. * Start the underlying thread. Blocks until all thread infrastructure is
  47. * setup. IsRunning() and DoInThread() should return true after this call.
  48. * Blocks until the thread is successfully started.
  49. *
  50. * Repeated call to this method will only start this thread once
  51. */
  52. void StartUp();
  53. /**
  54. * Post a task to run on this thread
  55. *
  56. * @param from_here location where this task is originated
  57. * @param task task created through base::Bind()
  58. * @return true if task is successfully scheduled, false if task cannot be
  59. * scheduled
  60. */
  61. bool DoInThread(const base::Location& from_here, base::OnceClosure task);
  62. /**
  63. * Shutdown the current thread as if it is never started. IsRunning() and
  64. * DoInThread() will return false after this call. Blocks until the thread is
  65. * joined and freed. This thread can be re-started again using StartUp()
  66. *
  67. * Repeated call to this method will only stop this thread once
  68. *
  69. * NOTE: Should never be called on the thread itself to avoid deadlock
  70. */
  71. void ShutDown();
  72. /**
  73. * Get the current thread ID returned by PlatformThread::CurrentId()
  74. *
  75. * On Android platform, this value should be the same as the tid logged by
  76. * logcat, which is returned by gettid(). On other platform, this thread id
  77. * may have different meanings. Therefore, this ID is only good for logging
  78. * and thread comparison purpose
  79. *
  80. * @return this thread's ID
  81. */
  82. base::PlatformThreadId GetThreadId() const;
  83. /**
  84. * Get this thread's name set in constructor
  85. *
  86. * @return this thread's name set in constructor
  87. */
  88. std::string GetName() const;
  89. /**
  90. * Get a string representation of this thread
  91. *
  92. * @return a string representation of this thread
  93. */
  94. std::string ToString() const;
  95. /**
  96. * Check if this thread is running
  97. *
  98. * @return true iff this thread is running and is able to do task
  99. */
  100. bool IsRunning() const;
  101. /**
  102. * Attempt to make scheduling for this thread real time
  103. *
  104. * @return true on success, false otherwise
  105. */
  106. bool EnableRealTimeScheduling();
  107. /**
  108. * Return the weak pointer to this object. This can be useful when posting
  109. * delayed tasks to this MessageLoopThread using Timer.
  110. */
  111. base::WeakPtr<MessageLoopThread> GetWeakPtr();
  112. /**
  113. * Return the message loop for this thread. Accessing raw message loop is not
  114. * recommended as message loop can be freed internally.
  115. *
  116. * @return message loop associated with this thread, nullptr if thread is not
  117. * running
  118. */
  119. base::MessageLoop* message_loop() const;
  120. private:
  121. /**
  122. * Static method to run the thread
  123. *
  124. * This is used instead of a C++ lambda because of the use of std::shared_ptr
  125. *
  126. * @param context needs to be a pointer to an instance of MessageLoopThread
  127. * @param start_up_promise a std::promise that is used to notify calling
  128. * thread the completion of message loop start-up
  129. */
  130. static void RunThread(MessageLoopThread* context,
  131. std::promise<void> start_up_promise);
  132. /**
  133. * Post a task to run on this thread after a specified delay. If the task
  134. * needs to be cancelable before it's run, use base::CancelableClosure type
  135. * for task closure. For example:
  136. * <code>
  137. * base::CancelableClosure cancelable_task;
  138. * cancelable_task.Reset(base::Bind(...)); // bind the task
  139. * same_thread->DoInThreadDelayed(FROM_HERE,
  140. * cancelable_task.callback(), delay);
  141. * ...
  142. * // Cancel the task closure
  143. * same_thread->DoInThread(FROM_HERE,
  144. * base::Bind(&base::CancelableClosure::Cancel,
  145. * base::Unretained(&cancelable_task)));
  146. * </code>
  147. *
  148. * Warning: base::CancelableClosure objects must be created on, posted to,
  149. * cancelled on, and destroyed on the same thread.
  150. *
  151. * @param from_here location where this task is originated
  152. * @param task task created through base::Bind()
  153. * @param delay delay for the task to be executed
  154. * @return true if task is successfully scheduled, false if task cannot be
  155. * scheduled
  156. */
  157. bool DoInThreadDelayed(const base::Location& from_here,
  158. base::OnceClosure task, const base::TimeDelta& delay);
  159. friend class RepeatingTimer; // allow Timer to use DoInThreadDelayed()
  160. friend class OnceTimer; // allow OnceTimer to use DoInThreadDelayed()
  161. /**
  162. * Actual method to run the thread, blocking until ShutDown() is called
  163. *
  164. * @param start_up_promise a std::promise that is used to notify calling
  165. * thread the completion of message loop start-up
  166. */
  167. void Run(std::promise<void> start_up_promise);
  168. mutable std::recursive_mutex api_mutex_;
  169. const std::string thread_name_;
  170. base::MessageLoop* message_loop_;
  171. base::RunLoop* run_loop_;
  172. std::thread* thread_;
  173. base::PlatformThreadId thread_id_;
  174. // Linux specific abstractions
  175. pid_t linux_tid_;
  176. base::WeakPtrFactory<MessageLoopThread> weak_ptr_factory_;
  177. bool shutting_down_;
  178. DISALLOW_COPY_AND_ASSIGN(MessageLoopThread);
  179. };
  180. inline std::ostream& operator<<(std::ostream& os,
  181. const bluetooth::common::MessageLoopThread& a) {
  182. os << a.ToString();
  183. return os;
  184. }
  185. } // namespace common
  186. } // namespace bluetooth