// Copyright 2019 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef BASE_THREADING_SCOPED_THREAD_PRIORITY_H_ #define BASE_THREADING_SCOPED_THREAD_PRIORITY_H_ #include "base/base_export.h" #include "base/compiler_specific.h" #include "base/location.h" #include "base/macros.h" #include "base/optional.h" #include "build/build_config.h" namespace base { class Location; enum class ThreadPriority : int; // INTERNAL_SCOPED_THREAD_PRIORITY_APPEND_LINE(name) produces an identifier by // appending the current line number to |name|. This is used to avoid name // collisions from variables defined inside a macro. #define INTERNAL_SCOPED_THREAD_PRIORITY_CONCAT(a, b) a##b // CONCAT1 provides extra level of indirection so that __LINE__ macro expands. #define INTERNAL_SCOPED_THREAD_PRIORITY_CONCAT1(a, b) \ INTERNAL_SCOPED_THREAD_PRIORITY_CONCAT(a, b) #define INTERNAL_SCOPED_THREAD_PRIORITY_APPEND_LINE(name) \ INTERNAL_SCOPED_THREAD_PRIORITY_CONCAT1(name, __LINE__) // All code that may load a DLL on a background thread must be surrounded by a // scope that starts with this macro. // // Example: // Foo(); // { // SCOPED_MAY_LOAD_LIBRARY_AT_BACKGROUND_PRIORITY(); // LoadMyDll(); // } // Bar(); // // The macro raises the thread priority to NORMAL for the scope when first // encountered. On Windows, loading a DLL on a background thread can lead to a // priority inversion on the loader lock and cause huge janks. #define SCOPED_MAY_LOAD_LIBRARY_AT_BACKGROUND_PRIORITY() \ base::internal::ScopedMayLoadLibraryAtBackgroundPriority \ INTERNAL_SCOPED_THREAD_PRIORITY_APPEND_LINE( \ scoped_may_load_library_at_background_priority)(FROM_HERE); \ { \ /* Thread-safe static local variable initialization ensures that */ \ /* OnScopeFirstEntered() is only invoked the first time that this is */ \ /* encountered. */ \ static bool INTERNAL_SCOPED_THREAD_PRIORITY_APPEND_LINE(invoke_once) = \ INTERNAL_SCOPED_THREAD_PRIORITY_APPEND_LINE( \ scoped_may_load_library_at_background_priority) \ .OnScopeFirstEntered(); \ ALLOW_UNUSED_LOCAL( \ INTERNAL_SCOPED_THREAD_PRIORITY_APPEND_LINE(invoke_once)); \ } namespace internal { class BASE_EXPORT ScopedMayLoadLibraryAtBackgroundPriority { public: explicit ScopedMayLoadLibraryAtBackgroundPriority(const Location& from_here); ~ScopedMayLoadLibraryAtBackgroundPriority(); // The SCOPED_MAY_LOAD_LIBRARY_AT_BACKGROUND_PRIORITY() macro invokes this the // first time that it is encountered. bool OnScopeFirstEntered(); private: #if defined(OS_WIN) // The original priority when invoking OnScopeFirstEntered(). base::Optional original_thread_priority_; #endif DISALLOW_COPY_AND_ASSIGN(ScopedMayLoadLibraryAtBackgroundPriority); }; } // namespace internal } // namespace base #endif // BASE_THREADING_SCOPED_THREAD_PRIORITY_H_