with one click
cpp-static-thread-safety
Enforce C++ static thread safety annotations and correct synchronization primitives. Use this skill when designing multi-threaded classes or editing guarded member fields.
Enforce C++ static thread safety annotations and correct synchronization primitives. Use this skill when designing multi-threaded classes or editing guarded member fields.
Enforce the strict topological header inclusion layering and reordering rules in Filament. Use this skill when adding or modifying `#include` directives in C++ source or header files.
Build, deploy, run, and benchmark Filament binaries on connected Android devices or emulators. Use this skill for compiling, pushing, and executing Android tests or benchmarks.
Clean and build Filament targets for development, debugging, and production. Use this skill whenever you need to clean the workspace or compile desktop targets.
Execute unit tests and performance benchmarks for Filament on desktop platforms. Use this skill to run and filter tests or benchmarks locally.
Enforce strict header self-containment so that every header file compiles independently. Use this skill when creating or modifying C++ header files.
Enforce preprocessor guard rules and macro-dependent inclusion hygiene in C++. Use this skill when modifying conditional imports or preprocessor directives.
| name | cpp-static-thread-safety |
| description | Enforce C++ static thread safety annotations and correct synchronization primitives. Use this skill when designing multi-threaded classes or editing guarded member fields. |
Filament leverages Clang's static thread safety analysis to verify lock holding requirements at compile-time. All multi-threaded classes must use explicit capability annotations to guarantee race-free state access.
std::mutex & std::condition_variable):
wait()).utils::Mutex & utils::Condition):
LockGuard const as the default for all standard synchronized blocks to guarantee scope-bound read-only lock scopes.
// Correct
utils::LockGuard const lock(mLock);
UniqueLock (non-const) strictly when passing locks to condition variables (wait(lock)) or when explicit .unlock() / .lock() boundaries are required for performance or deadlock prevention..cpp) that instantiates LockGuard or UniqueLock must explicitly include the matching utility header:
#include <utils/Mutex.h>
Clang evaluates C++ anonymous closures (lambdas) as separate context boundaries. Because lambdas lack capability attributes, standard condition variable waits passing local predicates (e.g., using std::ranges::all_of) will trigger false-positive thread safety errors.
To resolve this, use one of the following approved patterns:
Decorate only the CV wait predicate lambda operator with UTILS_NO_THREAD_SAFETY_ANALYSIS to ignore nested boundaries while preserving outer compile-time checks:
UniqueLock lock(mQueueLock);
mQueueCondition.wait(lock, [this]() UTILS_NO_THREAD_SAFETY_ANALYSIS {
return mExitRequested ||
(!std::ranges::all_of(mQueues, [](auto&& q) { return q.empty(); }));
});
If the check is flat, completely inline the CV predicate as a standard while loop to bring the member variables directly into the parent function's locked scope:
UniqueLock lock(mLock);
while (mFreeSpace < requiredSize) {
mCondition.wait(lock);
}
UTILS_GUARDED_BY) are conditionally compiled out on single-threaded configurations. To prevent compile crashes when FILAMENT_SINGLE_THREADED is defined, standard annotations are gated by UTILS_HAS_THREADING in compiler.h.