YugabyteDB (2.13.1.0-b60, 21121d69985fbf76aa6958d8f04a9bfa936293b5)

Coverage Report

Created: 2022-03-22 16:43

/Users/deen/code/yugabyte-db/src/yb/util/thread_restrictions.h
Line
Count
Source
1
// Licensed to the Apache Software Foundation (ASF) under one
2
// or more contributor license agreements.  See the NOTICE file
3
// distributed with this work for additional information
4
// regarding copyright ownership.  The ASF licenses this file
5
// to you under the Apache License, Version 2.0 (the
6
// "License"); you may not use this file except in compliance
7
// with the License.  You may obtain a copy of the License at
8
//
9
//   http://www.apache.org/licenses/LICENSE-2.0
10
//
11
// Unless required by applicable law or agreed to in writing,
12
// software distributed under the License is distributed on an
13
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
// KIND, either express or implied.  See the License for the
15
// specific language governing permissions and limitations
16
// under the License.
17
//
18
// The following only applies to changes made to this file as part of YugaByte development.
19
//
20
// Portions Copyright (c) YugaByte, Inc.
21
//
22
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
23
// in compliance with the License.  You may obtain a copy of the License at
24
//
25
// http://www.apache.org/licenses/LICENSE-2.0
26
//
27
// Unless required by applicable law or agreed to in writing, software distributed under the License
28
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
29
// or implied.  See the License for the specific language governing permissions and limitations
30
// under the License.
31
//
32
// Some portions: Copyright (c) 2012, The Chromium Authors.
33
#ifndef YB_UTIL_THREAD_RESTRICTIONS_H
34
#define YB_UTIL_THREAD_RESTRICTIONS_H
35
36
#include "yb/gutil/macros.h"
37
38
#ifndef NDEBUG
39
#define ENABLE_THREAD_RESTRICTIONS 1
40
#endif
41
42
namespace yb {
43
44
// Certain behavior is disallowed on certain threads.  ThreadRestrictions helps
45
// enforce these rules.  Examples of such rules:
46
//
47
// * Do not do blocking IO
48
// * Do not wait on synchronization variables or sleep
49
//
50
// Here's more about how the protection works:
51
//
52
// 1) If a thread should not be allowed to make IO calls, mark it:
53
//      ThreadRestrictions::SetIOAllowed(false);
54
//    By default, threads *are* allowed to make IO calls.
55
//    In particular, threads like RPC reactors should never do blocking IO
56
//    because it may stall other unrelated requests.
57
//
58
// 2) If a function makes a call that will go out to disk, check whether the
59
//    current thread is allowed:
60
//      ThreadRestrictions::AssertIOAllowed();
61
//
62
//
63
// Style tip: where should you put AssertIOAllowed checks?  It's best
64
// if you put them as close to the disk access as possible, at the
65
// lowest level.  This rule is simple to follow and helps catch all
66
// callers.  For example, if your function GoDoSomeBlockingDiskCall()
67
// only calls other functions in YB and doesn't access the underlying
68
// disk, you should go add the AssertIOAllowed checks in the helper functions.
69
class ThreadRestrictions {
70
 public:
71
  // Constructing a ScopedAllowIO temporarily allows IO for the current
72
  // thread.  Doing this is almost certainly always incorrect, but sometimes
73
  // it makes more sense to allow an exception and file a bug in the backlog
74
  // to improve it later.
75
  class ScopedAllowIO {
76
   public:
77
    ScopedAllowIO() { previous_value_ = SetIOAllowed(true); }
78
    ~ScopedAllowIO() { SetIOAllowed(previous_value_); }
79
   private:
80
    // Whether IO is allowed when the ScopedAllowIO was constructed.
81
    bool previous_value_;
82
83
    DISALLOW_COPY_AND_ASSIGN(ScopedAllowIO);
84
  };
85
86
  // Constructing a ScopedAllowWait temporarily allows waiting on the current
87
  // thread.  Doing this is almost always incorrect: consider carefully whether
88
  // you should instead be deferring work to a different thread.
89
  class ScopedAllowWait {
90
   public:
91
8.97k
    ScopedAllowWait() { previous_value_ = SetWaitAllowed(true); }
92
9.00k
    ~ScopedAllowWait() { SetWaitAllowed(previous_value_); }
93
   private:
94
    // Whether singleton use is allowed when the ScopedAllowWait was
95
    // constructed.
96
    bool previous_value_;
97
98
    DISALLOW_COPY_AND_ASSIGN(ScopedAllowWait);
99
  };
100
101
102
#if ENABLE_THREAD_RESTRICTIONS
103
  // Set whether the current thread to make IO calls.
104
  // Threads start out in the *allowed* state.
105
  // Returns the previous value.
106
  static bool SetIOAllowed(bool allowed);
107
108
  // Check whether the current thread is allowed to make IO calls,
109
  // and FATALs if not.  See the block comment above the class for
110
  // a discussion of where to add these checks.
111
  static void AssertIOAllowed();
112
113
  // Set whether the current thread may wait/block.  Returns the previous
114
  // value.
115
  static bool SetWaitAllowed(bool allowed);
116
117
  static bool IsWaitAllowed();
118
119
  // Check whether the current thread is allowed to wait/block.
120
  // FATALs if not.
121
  static void AssertWaitAllowed();
122
#else
123
  // Inline the empty definitions of these functions so that they can be
124
  // compiled out.
125
  static bool SetIOAllowed(bool allowed) { return true; }
126
  static void AssertIOAllowed() {}
127
  static bool SetWaitAllowed(bool allowed) { return true; }
128
  static void AssertWaitAllowed() {}
129
  static bool IsWaitAllowed() { return true; }
130
#endif
131
132
 private:
133
  DISALLOW_IMPLICIT_CONSTRUCTORS(ThreadRestrictions);
134
};
135
136
} // namespace yb
137
138
#endif /* YB_UTIL_THREAD_RESTRICTIONS_H */