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 #include "base/message_loop/work_id_provider.h" 6 7 #include <memory> 8 9 #include "base/memory/ptr_util.h" 10 #include "base/no_destructor.h" 11 #include "base/threading/thread_local.h" 12 13 namespace base { 14 15 // static GetForCurrentThread()16WorkIdProvider* WorkIdProvider::GetForCurrentThread() { 17 static NoDestructor<ThreadLocalOwnedPointer<WorkIdProvider>> instance; 18 if (!instance->Get()) 19 instance->Set(WrapUnique(new WorkIdProvider)); 20 return instance->Get(); 21 } 22 23 // This function must support being invoked while other threads are suspended so 24 // must not take any locks, including indirectly through use of heap allocation, 25 // LOG, CHECK, or DCHECK. GetWorkId()26unsigned int WorkIdProvider::GetWorkId() { 27 return work_id_.load(std::memory_order_acquire); 28 } 29 30 WorkIdProvider::~WorkIdProvider() = default; 31 SetCurrentWorkIdForTesting(unsigned int id)32void WorkIdProvider::SetCurrentWorkIdForTesting(unsigned int id) { 33 work_id_.store(id, std::memory_order_relaxed); 34 } 35 IncrementWorkIdForTesting()36void WorkIdProvider::IncrementWorkIdForTesting() { 37 IncrementWorkId(); 38 } 39 WorkIdProvider()40WorkIdProvider::WorkIdProvider() : work_id_(0) {} 41 IncrementWorkId()42void WorkIdProvider::IncrementWorkId() { 43 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); 44 45 unsigned int next_id = work_id_.load(std::memory_order_relaxed) + 1; 46 // Reserve 0 to mean no work items have been executed. 47 if (next_id == 0) 48 ++next_id; 49 // Release order ensures this state is visible to other threads prior to the 50 // following task/event execution. 51 work_id_.store(next_id, std::memory_order_release); 52 } 53 54 } // namespace base 55