associated_thread_id.h 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. // Copyright 2018 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. #ifndef BASE_TASK_SEQUENCE_MANAGER_ASSOCIATED_THREAD_ID_H_
  5. #define BASE_TASK_SEQUENCE_MANAGER_ASSOCIATED_THREAD_ID_H_
  6. #include <atomic>
  7. #include <memory>
  8. #include "base/macros.h"
  9. #include "base/memory/ref_counted.h"
  10. #include "base/optional.h"
  11. #include "base/sequence_checker.h"
  12. #include "base/threading/platform_thread.h"
  13. #include "base/threading/thread_checker.h"
  14. namespace base {
  15. namespace sequence_manager {
  16. namespace internal {
  17. // TODO(eseckler): Make this owned by SequenceManager once the TaskQueue
  18. // refactor has happened (https://crbug.com/865411).
  19. //
  20. // This class is thread-safe. But see notes about memory ordering guarantees for
  21. // the various methods.
  22. class BASE_EXPORT AssociatedThreadId
  23. : public base::RefCountedThreadSafe<AssociatedThreadId> {
  24. public:
  25. AssociatedThreadId();
  26. // TODO(eseckler): Replace thread_checker with sequence_checker everywhere.
  27. THREAD_CHECKER(thread_checker);
  28. SEQUENCE_CHECKER(sequence_checker);
  29. static scoped_refptr<AssociatedThreadId> CreateUnbound() {
  30. return MakeRefCounted<AssociatedThreadId>();
  31. }
  32. static scoped_refptr<AssociatedThreadId> CreateBound() {
  33. auto associated_thread = MakeRefCounted<AssociatedThreadId>();
  34. associated_thread->BindToCurrentThread();
  35. return associated_thread;
  36. }
  37. // Rebind the associated thread to the current thread. This allows creating
  38. // the SequenceManager and TaskQueues on a different thread/sequence than the
  39. // one it will manage.
  40. //
  41. // Can only be called once.
  42. void BindToCurrentThread();
  43. // Returns the id of the thread bound to this object via a previous call to
  44. // BindToCurrentThread(), nullopt if no thread was bound yet.
  45. //
  46. // This method guarantees a happens-before ordering with
  47. // BindToCurrentThread(), that is all memory writes that happened-before the
  48. // call to BindToCurrentThread() will become visible side-effects in the
  49. // current thread.
  50. //
  51. // Attention: The result might be stale by the time this method returns.
  52. Optional<PlatformThreadId> GetBoundThreadId() const {
  53. auto thread_id = thread_id_.load(std::memory_order_acquire);
  54. if (thread_id == kInvalidThreadId) {
  55. return nullopt;
  56. } else {
  57. return thread_id;
  58. }
  59. }
  60. // Checks whether this object has already been bound to a thread.
  61. //
  62. // This method guarantees a happens-before ordering with
  63. // BindToCurrentThread(), that is all memory writes that happened-before the
  64. // call to BindToCurrentThread() will become visible side-effects in the
  65. // current thread.
  66. //
  67. // Attention: The result might be stale by the time this method returns.
  68. bool IsBound() const {
  69. return thread_id_.load(std::memory_order_acquire) != kInvalidThreadId;
  70. }
  71. // Checks whether this object is bound to the current thread. Returns false if
  72. // this object is not bound to any thread.
  73. //
  74. // Note that this method provides no memory ordering guarantees but those are
  75. // not really needed. If this method returns true we are on the same thread
  76. // that called BindToCurrentThread(). If the method returns false this object
  77. // could be unbound, so there is no possible ordering.
  78. //
  79. // Attention:: The result might be stale by the time this method returns.
  80. bool IsBoundToCurrentThread() const {
  81. return thread_id_.load(std::memory_order_relaxed) ==
  82. PlatformThread::CurrentId();
  83. }
  84. // TODO(eseckler): Add a method that checks that we are either bound already
  85. // or on the thread which created us and use it in any_thread() accessors.
  86. private:
  87. friend class base::RefCountedThreadSafe<AssociatedThreadId>;
  88. ~AssociatedThreadId();
  89. // All access to this member can be std::memory_order_relaxed as this class
  90. // provides no ordering guarantees.
  91. std::atomic<PlatformThreadId> thread_id_{kInvalidThreadId};
  92. };
  93. } // namespace internal
  94. } // namespace sequence_manager
  95. } // namespace base
  96. #endif // BASE_TASK_SEQUENCE_MANAGER_ASSOCIATED_THREAD_ID_H_