GRPC C++  1.26.0
exec_ctx.h
Go to the documentation of this file.
1 /*
2  *
3  * Copyright 2015 gRPC authors.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * 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, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18 
19 #ifndef GRPC_CORE_LIB_IOMGR_EXEC_CTX_H
20 #define GRPC_CORE_LIB_IOMGR_EXEC_CTX_H
21 
23 
25 #include <grpc/support/atm.h>
26 #include <grpc/support/cpu.h>
27 #include <grpc/support/log.h>
28 
30 #include "src/core/lib/gpr/tls.h"
34 
35 typedef int64_t grpc_millis;
36 
37 #define GRPC_MILLIS_INF_FUTURE INT64_MAX
38 #define GRPC_MILLIS_INF_PAST INT64_MIN
39 
42 typedef struct grpc_combiner grpc_combiner;
43 
44 /* This exec_ctx is ready to return: either pre-populated, or cached as soon as
45  the finish_check returns true */
46 #define GRPC_EXEC_CTX_FLAG_IS_FINISHED 1
47 /* The exec_ctx's thread is (potentially) owned by a call or channel: care
48  should be given to not delete said call/channel from this exec_ctx */
49 #define GRPC_EXEC_CTX_FLAG_THREAD_RESOURCE_LOOP 2
50 /* This exec ctx was initialized by an internal thread, and should not
51  be counted by fork handlers */
52 #define GRPC_EXEC_CTX_FLAG_IS_INTERNAL_THREAD 4
53 
54 /* This application callback exec ctx was initialized by an internal thread, and
55  should not be counted by fork handlers */
56 #define GRPC_APP_CALLBACK_EXEC_CTX_FLAG_IS_INTERNAL_THREAD 1
57 
63 
64 namespace grpc_core {
65 class Combiner;
104 class ExecCtx {
105  public:
110  Set(this);
111  }
112 
114  ExecCtx(uintptr_t fl) : flags_(fl) {
115  if (!(GRPC_EXEC_CTX_FLAG_IS_INTERNAL_THREAD & flags_)) {
117  }
118  Set(this);
119  }
120 
122  virtual ~ExecCtx() {
124  Flush();
125  Set(last_exec_ctx_);
126  if (!(GRPC_EXEC_CTX_FLAG_IS_INTERNAL_THREAD & flags_)) {
128  }
129  }
130 
132  ExecCtx(const ExecCtx&) = delete;
133  ExecCtx& operator=(const ExecCtx&) = delete;
134 
135  unsigned starting_cpu() const { return starting_cpu_; }
136 
137  struct CombinerData {
138  /* currently active combiner: updated only via combiner.c */
140  /* last active combiner in the active combiner list */
142  };
143 
145  CombinerData* combiner_data() { return &combiner_data_; }
146 
148  grpc_closure_list* closure_list() { return &closure_list_; }
149 
151  uintptr_t flags() { return flags_; }
152 
154  bool HasWork() {
155  return combiner_data_.active_combiner != nullptr ||
156  !grpc_closure_list_empty(closure_list_);
157  }
158 
163  bool Flush();
164 
170  if ((flags_ & GRPC_EXEC_CTX_FLAG_IS_FINISHED) == 0) {
171  if (CheckReadyToFinish()) {
173  return true;
174  }
175  return false;
176  } else {
177  return true;
178  }
179  }
180 
186 
190  void InvalidateNow() { now_is_valid_ = false; }
191 
194  now_ = GRPC_MILLIS_INF_FUTURE;
195  now_is_valid_ = true;
196  }
197 
201  void TestOnlySetNow(grpc_millis new_val) {
202  now_ = new_val;
203  now_is_valid_ = true;
204  }
205 
206  static void TestOnlyGlobalInit(gpr_timespec new_val);
207 
209  static void GlobalInit(void);
210 
212  static void GlobalShutdown(void) { gpr_tls_destroy(&exec_ctx_); }
213 
215  static ExecCtx* Get() {
216  return reinterpret_cast<ExecCtx*>(gpr_tls_get(&exec_ctx_));
217  }
218 
219  static void Set(ExecCtx* exec_ctx) {
220  gpr_tls_set(&exec_ctx_, reinterpret_cast<intptr_t>(exec_ctx));
221  }
222 
223  static void Run(const DebugLocation& location, grpc_closure* closure,
224  grpc_error* error);
225 
226  static void RunList(const DebugLocation& location, grpc_closure_list* list);
227 
228  protected:
230  virtual bool CheckReadyToFinish() { return false; }
231 
233  static void operator delete(void* /* p */) { abort(); }
234 
235  private:
239  CombinerData combiner_data_ = {nullptr, nullptr};
240  uintptr_t flags_;
241 
242  unsigned starting_cpu_ = gpr_cpu_current_cpu();
243 
244  bool now_is_valid_ = false;
245  grpc_millis now_ = 0;
246 
247  GPR_TLS_CLASS_DECL(exec_ctx_);
248  ExecCtx* last_exec_ctx_ = Get();
249 };
250 
299  public:
301  ApplicationCallbackExecCtx() { Set(this, flags_); }
302 
304  ApplicationCallbackExecCtx(uintptr_t fl) : flags_(fl) { Set(this, flags_); }
305 
307  if (reinterpret_cast<ApplicationCallbackExecCtx*>(
308  gpr_tls_get(&callback_exec_ctx_)) == this) {
309  while (head_ != nullptr) {
310  auto* f = head_;
311  head_ = f->internal_next;
312  if (f->internal_next == nullptr) {
313  tail_ = nullptr;
314  }
315  (*f->functor_run)(f, f->internal_success);
316  }
317  gpr_tls_set(&callback_exec_ctx_, reinterpret_cast<intptr_t>(nullptr));
320  }
321  } else {
322  GPR_DEBUG_ASSERT(head_ == nullptr);
323  GPR_DEBUG_ASSERT(tail_ == nullptr);
324  }
325  }
326 
327  static void Set(ApplicationCallbackExecCtx* exec_ctx, uintptr_t flags) {
328  if (reinterpret_cast<ApplicationCallbackExecCtx*>(
329  gpr_tls_get(&callback_exec_ctx_)) == nullptr) {
332  }
333  gpr_tls_set(&callback_exec_ctx_, reinterpret_cast<intptr_t>(exec_ctx));
334  }
335  }
336 
338  int is_success) {
339  functor->internal_success = is_success;
340  functor->internal_next = nullptr;
341 
342  auto* ctx = reinterpret_cast<ApplicationCallbackExecCtx*>(
343  gpr_tls_get(&callback_exec_ctx_));
344 
345  if (ctx->head_ == nullptr) {
346  ctx->head_ = functor;
347  }
348  if (ctx->tail_ != nullptr) {
349  ctx->tail_->internal_next = functor;
350  }
351  ctx->tail_ = functor;
352  }
353 
355  static void GlobalInit(void) { gpr_tls_init(&callback_exec_ctx_); }
356 
358  static void GlobalShutdown(void) { gpr_tls_destroy(&callback_exec_ctx_); }
359 
360  private:
361  uintptr_t flags_{0u};
364  GPR_TLS_CLASS_DECL(callback_exec_ctx_);
365 };
366 } // namespace grpc_core
367 
368 #endif /* GRPC_CORE_LIB_IOMGR_EXEC_CTX_H */
Application-callback execution context.
Definition: exec_ctx.h:298
~ApplicationCallbackExecCtx()
Definition: exec_ctx.h:306
ApplicationCallbackExecCtx(uintptr_t fl)
Parameterised Constructor.
Definition: exec_ctx.h:304
static void Set(ApplicationCallbackExecCtx *exec_ctx, uintptr_t flags)
Definition: exec_ctx.h:327
ApplicationCallbackExecCtx()
Default Constructor.
Definition: exec_ctx.h:301
static void Enqueue(grpc_experimental_completion_queue_functor *functor, int is_success)
Definition: exec_ctx.h:337
static void GlobalShutdown(void)
Global shutdown for ApplicationCallbackExecCtx.
Definition: exec_ctx.h:358
static void GlobalInit(void)
Global initialization for ApplicationCallbackExecCtx.
Definition: exec_ctx.h:355
Definition: combiner.h:33
Definition: debug_location.h:31
Execution context.
Definition: exec_ctx.h:104
bool Flush()
Flush any work that has been enqueued onto this grpc_exec_ctx.
static ExecCtx * Get()
Gets pointer to current exec_ctx.
Definition: exec_ctx.h:215
ExecCtx(uintptr_t fl)
Parameterised Constructor.
Definition: exec_ctx.h:114
static void TestOnlyGlobalInit(gpr_timespec new_val)
ExecCtx & operator=(const ExecCtx &)=delete
static void Run(const DebugLocation &location, grpc_closure *closure, grpc_error *error)
bool HasWork()
Checks if there is work to be done.
Definition: exec_ctx.h:154
ExecCtx(const ExecCtx &)=delete
Disallow copy and assignment operators.
void InvalidateNow()
Invalidates the stored time value.
Definition: exec_ctx.h:190
bool IsReadyToFinish()
Returns true if we'd like to leave this execution context as soon as possible: useful for deciding wh...
Definition: exec_ctx.h:169
virtual bool CheckReadyToFinish()
Check if ready to finish.
Definition: exec_ctx.h:230
static void RunList(const DebugLocation &location, grpc_closure_list *list)
grpc_millis Now()
Returns the stored current time relative to start if valid, otherwise refreshes the stored time,...
virtual ~ExecCtx()
Destructor.
Definition: exec_ctx.h:122
static void Set(ExecCtx *exec_ctx)
Definition: exec_ctx.h:219
uintptr_t flags()
Return flags.
Definition: exec_ctx.h:151
static void GlobalInit(void)
Global initialization for ExecCtx.
grpc_closure_list * closure_list()
Return pointer to grpc_closure_list.
Definition: exec_ctx.h:148
static void GlobalShutdown(void)
Global shutdown for ExecCtx.
Definition: exec_ctx.h:212
CombinerData * combiner_data()
Only to be used by grpc-combiner code.
Definition: exec_ctx.h:145
unsigned starting_cpu() const
Definition: exec_ctx.h:135
void SetNowIomgrShutdown()
To be used only by shutdown code in iomgr.
Definition: exec_ctx.h:193
void TestOnlySetNow(grpc_millis new_val)
To be used only for testing.
Definition: exec_ctx.h:201
ExecCtx()
Default Constructor.
Definition: exec_ctx.h:108
static void DecExecCtxCount()
Definition: fork.h:57
static void IncExecCtxCount()
Definition: fork.h:50
bool grpc_closure_list_empty(grpc_closure_list closure_list)
return whether list is empty.
Definition: closure.h:223
#define GRPC_CLOSURE_LIST_INIT
Definition: closure.h:168
GPRAPI unsigned gpr_cpu_current_cpu(void)
Return the CPU on which the current thread is executing; N.B.
int64_t grpc_millis
Definition: exec_ctx.h:35
#define GRPC_EXEC_CTX_FLAG_IS_INTERNAL_THREAD
Definition: exec_ctx.h:52
#define GRPC_APP_CALLBACK_EXEC_CTX_FLAG_IS_INTERNAL_THREAD
Definition: exec_ctx.h:56
grpc_millis grpc_cycle_counter_to_millis_round_down(gpr_cycle_counter cycles)
#define GRPC_EXEC_CTX_FLAG_IS_FINISHED
Definition: exec_ctx.h:46
gpr_timespec grpc_millis_to_timespec(grpc_millis millis, gpr_clock_type clock)
grpc_millis grpc_cycle_counter_to_millis_round_up(gpr_cycle_counter cycles)
grpc_millis grpc_timespec_to_millis_round_down(gpr_timespec timespec)
struct grpc_combiner grpc_combiner
A combiner represents a list of work to be executed later.
Definition: exec_ctx.h:42
#define GRPC_MILLIS_INF_FUTURE
Definition: exec_ctx.h:37
grpc_millis grpc_timespec_to_millis_round_up(gpr_timespec timespec)
gpr_clock_type
The clocks we support.
Definition: gpr_types.h:31
#define GPR_DEBUG_ASSERT(x)
Definition: log.h:103
Internal thread interface.
Definition: backoff.h:26
Analogous to struct timespec.
Definition: gpr_types.h:47
Definition: closure.h:41
A closure over a grpc_iomgr_cb_func.
Definition: closure.h:56
Definition: exec_ctx.h:137
Combiner * last_combiner
Definition: exec_ctx.h:141
Combiner * active_combiner
Definition: exec_ctx.h:139
Definition: error_internal.h:39
EXPERIMENTAL: Specifies an interface class to be used as a tag for callback-based completion queues.
Definition: grpc_types.h:722
int internal_success
The following fields are not API.
Definition: grpc_types.h:734
struct grpc_experimental_completion_queue_functor * internal_next
Definition: grpc_types.h:735
#define gpr_tls_destroy(tls)
Definition: tls_gcc.h:46
#define gpr_tls_init(tls)
Definition: tls_gcc.h:43
#define gpr_tls_get(tls)
Definition: tls_gcc.h:50
intptr_t gpr_tls_set(struct gpr_pthread_thread_local *tls, intptr_t value)