12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091 |
- // 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 <atomic>
- #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 if no other
- // thread has completed the current scope already (multiple threads can racily
- // begin the initialization and will all be boosted for it). 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() \
- static std::atomic_bool INTERNAL_SCOPED_THREAD_PRIORITY_APPEND_LINE( \
- already_loaded){false}; \
- base::internal::ScopedMayLoadLibraryAtBackgroundPriority \
- INTERNAL_SCOPED_THREAD_PRIORITY_APPEND_LINE( \
- scoped_may_load_library_at_background_priority)( \
- FROM_HERE, \
- &INTERNAL_SCOPED_THREAD_PRIORITY_APPEND_LINE(already_loaded));
- // Like SCOPED_MAY_LOAD_LIBRARY_AT_BACKGROUND_PRIORITY, but raises the thread
- // priority every time the scope is entered. Use this around code that may
- // conditionally load a DLL each time it is executed, or which repeatedly loads
- // and unloads DLLs.
- #define SCOPED_MAY_LOAD_LIBRARY_AT_BACKGROUND_PRIORITY_REPEATEDLY() \
- base::internal::ScopedMayLoadLibraryAtBackgroundPriority \
- INTERNAL_SCOPED_THREAD_PRIORITY_APPEND_LINE( \
- scoped_may_load_library_at_background_priority)(FROM_HERE, nullptr);
- namespace internal {
- class BASE_EXPORT ScopedMayLoadLibraryAtBackgroundPriority {
- public:
- // Boosts thread priority to NORMAL within its scope if |already_loaded| is
- // nullptr or set to false.
- explicit ScopedMayLoadLibraryAtBackgroundPriority(
- const Location& from_here,
- std::atomic_bool* already_loaded);
- ~ScopedMayLoadLibraryAtBackgroundPriority();
- private:
- #if defined(OS_WIN)
- // The original priority when invoking entering the scope().
- base::Optional<ThreadPriority> original_thread_priority_;
- std::atomic_bool* const already_loaded_;
- #endif
- DISALLOW_COPY_AND_ASSIGN(ScopedMayLoadLibraryAtBackgroundPriority);
- };
- } // namespace internal
- } // namespace base
- #endif // BASE_THREADING_SCOPED_THREAD_PRIORITY_H_
|