Flutter Engine
The Flutter Engine
thread_checker.h
Go to the documentation of this file.
1// Copyright 2013 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5// A class for checking that the current thread is/isn't the same as an initial
6// thread.
7
8#ifndef FLUTTER_FML_MEMORY_THREAD_CHECKER_H_
9#define FLUTTER_FML_MEMORY_THREAD_CHECKER_H_
10
11#include "flutter/fml/build_config.h"
12#include "flutter/fml/logging.h"
13#include "flutter/fml/macros.h"
14
15#if defined(FML_OS_WIN)
16#include <windows.h>
17#else
18#include <pthread.h>
19#endif
20
21namespace fml {
22
23// A simple class that records the identity of the thread that it was created
24// on, and at later points can tell if the current thread is the same as its
25// creation thread. This class is thread-safe.
26//
27// Note: Unlike Chromium's |base::ThreadChecker|, this is *not* Debug-only (so
28// #ifdef it out if you want something Debug-only). (Rationale: Having a
29// |CalledOnValidThread()| that lies in Release builds seems bad. Moreover,
30// there's a small space cost to having even an empty class. )
31class ThreadChecker final {
32 public:
33 static void DisableNextThreadCheckFailure() { disable_next_failure_ = true; }
34
35 private:
36 static thread_local bool disable_next_failure_;
37
38 public:
39#if defined(FML_OS_WIN)
40 ThreadChecker() : self_(GetCurrentThreadId()) {}
42
43 bool IsCreationThreadCurrent() const {
44 bool result = GetCurrentThreadId() == self_;
45 if (!result && disable_next_failure_) {
46 disable_next_failure_ = false;
47 return true;
48 }
49 return result;
50 }
51
52 private:
53 DWORD self_;
54
55#else
56 ThreadChecker() : self_(pthread_self()) {}
58
59 // Returns true if the current thread is the thread this object was created
60 // on and false otherwise.
62 pthread_t current_thread = pthread_self();
63 bool is_creation_thread_current = !!pthread_equal(current_thread, self_);
64 if (disable_next_failure_ && !is_creation_thread_current) {
65 disable_next_failure_ = false;
66 return true;
67 }
68#ifdef __APPLE__
69 // TODO(https://github.com/flutter/flutter/issues/45272): Implement for
70 // other platforms.
71 if (!is_creation_thread_current) {
72 static const int buffer_length = 128;
73 char expected_thread[buffer_length];
74 char actual_thread[buffer_length];
75 if (0 == pthread_getname_np(current_thread, actual_thread,
76 buffer_length) &&
77 0 == pthread_getname_np(self_, expected_thread, buffer_length)) {
78 FML_DLOG(ERROR) << "Object referenced on a thread other than the one "
79 "on which it was created. Expected thread: '"
80 << expected_thread << "'. Actual thread: '"
81 << actual_thread << "'.";
82 }
83 }
84#endif // __APPLE__
85 return is_creation_thread_current;
86 }
87
88 private:
89 pthread_t self_;
90#endif
91};
92
93#if !defined(NDEBUG)
94#define FML_DECLARE_THREAD_CHECKER(c) fml::ThreadChecker c
95#define FML_DCHECK_CREATION_THREAD_IS_CURRENT(c) \
96 FML_DCHECK((c).IsCreationThreadCurrent())
97#else
98#define FML_DECLARE_THREAD_CHECKER(c)
99#define FML_DCHECK_CREATION_THREAD_IS_CURRENT(c) ((void)0)
100#endif
101
102} // namespace fml
103
104#endif // FLUTTER_FML_MEMORY_THREAD_CHECKER_H_
bool IsCreationThreadCurrent() const
static void DisableNextThreadCheckFailure()
GAsyncResult * result
#define FML_DLOG(severity)
Definition: logging.h:102
Definition: ascii_trie.cc:9
#define ERROR(message)
Definition: elf_loader.cc:260
unsigned long DWORD
Definition: windows_types.h:22