1 // Copyright 2019 The Chromium Authors 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 BASE_MESSAGE_LOOP_WORK_ID_PROVIDER_H_ 6 #define BASE_MESSAGE_LOOP_WORK_ID_PROVIDER_H_ 7 8 #include <atomic> 9 10 #include "base/base_export.h" 11 #include "base/threading/thread_checker.h" 12 13 namespace base { 14 namespace sequence_manager { 15 namespace internal { 16 class ThreadControllerWithMessagePumpImpl; 17 } 18 } // namespace sequence_manager 19 20 // WorkIdProvider associates with the current thread (via TLS) an id state 21 // reflecting the current work item being executed by the message loop. The item 22 // is accessed lock-free from other threads to provide a snapshot of the 23 // currently-executing work item. 24 // 25 // The expected user is the ThreadProfiler which samples the id along with the 26 // thread's stack to identify cases where the same task spans multiple 27 // samples. The state is stored in TLS rather than on the MessageLoop or the 28 // ThreadProfiler because the lifetime relationship between the two classes 29 // varies depending on which thread is being profiled, plus the fact that 30 // MessageLoop doesn't have a well-defined creation point/owner on some threads. 31 class BASE_EXPORT WorkIdProvider { 32 public: 33 // Returns the WorkIdProvider for the current thread. Allocates a 34 // WorkIdProvider in TLS if not already present. 35 static WorkIdProvider* GetForCurrentThread(); 36 37 // Returns the work id for the thread to which this WorkIdProvider 38 // belongs. The work id is 0 before calls to IncrementWorkId() and always 39 // non-zero after that point. The implementation supports being invoked while 40 // other threads are suspended, and thus is guaranteed to take no locks, 41 // directly or indirectly. May be called from any thread, as long as the 42 // owning thread hasn't been destroyed. 43 unsigned int GetWorkId(); 44 45 // Public to support unique_ptr<WorkIdProvider>. 46 ~WorkIdProvider(); 47 48 void SetCurrentWorkIdForTesting(unsigned int id); 49 void IncrementWorkIdForTesting(); 50 51 WorkIdProvider(const WorkIdProvider&) = delete; 52 WorkIdProvider& operator=(const WorkIdProvider&) = delete; 53 54 private: 55 // Friended to allow use of IncrementWorkId(). 56 friend class sequence_manager::internal::ThreadControllerWithMessagePumpImpl; 57 58 WorkIdProvider(); 59 60 void IncrementWorkId(); 61 62 std::atomic_uint work_id_; 63 64 THREAD_CHECKER(thread_checker_); 65 }; 66 67 } // namespace base 68 69 #endif // BASE_MESSAGE_LOOP_WORK_ID_PROVIDER_H_ 70