1 // Copyright 2021 The Android Open Source Project 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // Copyright 2016 The Fuchsia Authors. All rights reserved. 16 // Use of this source code is governed by a BSD-style license that can be 17 // found in the LICENSE file. 18 19 // A class for checking that the current thread is/isn't the same as an initial 20 // thread. 21 22 #pragma once 23 24 #include <assert.h> 25 26 #include <thread> 27 28 #include "ThreadSafety.h" 29 30 namespace gfxstream::guest { 31 namespace fit { 32 33 // A simple class that records the identity of the thread that it was created 34 // on, and at later points can tell if the current thread is the same as its 35 // creation thread. This class is thread-safe. 36 // 37 // In addition to providing an explicit check of the current thread, 38 // |thread_checker| complies with BasicLockable, checking the current thread 39 // when |lock| is called. This allows static thread safety analysis to be used 40 // to ensure that resources are accessed in a context that is checked (at debug 41 // runtime) to ensure that it's running on the correct thread: 42 // 43 // class MyClass { 44 // public: 45 // void Foo() { 46 // std::lock_guard<fit::thread_checker> locker(thread_checker_); 47 // resource_ = 0; 48 // } 49 // private: 50 // fit::thread_checker thread_checker_; 51 // int resource_ GUARDED_BY(thread_checker_); 52 // } 53 // 54 // Note: |lock| checks the thread in debug builds only. 55 // 56 class CAPABILITY("mutex") ThreadChecker final { 57 public: 58 // Default constructor. Constructs a thread checker bound to the currently 59 // running thread. ThreadChecker()60 ThreadChecker() : self_(std::this_thread::get_id()) {} 61 // Constructs a thread checker bound to an explicit other thread. ThreadChecker(std::thread::id self)62 explicit ThreadChecker(std::thread::id self) : self_(self) {} 63 ~ThreadChecker() = default; 64 65 // Returns true if the current thread is the thread this object was created 66 // on and false otherwise. isThreadValid()67 bool isThreadValid() const { return std::this_thread::get_id() == self_; } 68 69 // Implementation of the BaseLockable requirement lock()70 void lock() ACQUIRE() { assert(isThreadValid()); } 71 unlock()72 void unlock() RELEASE() {} 73 74 private: 75 const std::thread::id self_; 76 }; 77 78 #ifndef NDEBUG 79 #define DECLARE_THREAD_CHECKER(c) gfxstream::guest::fit::ThreadChecker c 80 #define DCHECK_IS_THREAD_VALID(c) assert((c).isThreadValid()) 81 #else 82 #define DECLARE_THREAD_CHECKER(c) 83 #define DCHECK_IS_THREAD_VALID(c) ((void)0) 84 #endif 85 86 } // namespace fit 87 } // namespace gfxstream::guest 88