• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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