GRPC Core  18.0.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 
24 #include <limits>
25 
27 #include <grpc/support/atm.h>
28 #include <grpc/support/cpu.h>
29 #include <grpc/support/log.h>
30 
32 #include "src/core/lib/gpr/tls.h"
36 
37 typedef int64_t grpc_millis;
38 
39 #define GRPC_MILLIS_INF_FUTURE INT64_MAX
40 #define GRPC_MILLIS_INF_PAST INT64_MIN
41 
44 typedef struct grpc_combiner grpc_combiner;
45 
46 /* This exec_ctx is ready to return: either pre-populated, or cached as soon as
47  the finish_check returns true */
48 #define GRPC_EXEC_CTX_FLAG_IS_FINISHED 1
49 /* The exec_ctx's thread is (potentially) owned by a call or channel: care
50  should be given to not delete said call/channel from this exec_ctx */
51 #define GRPC_EXEC_CTX_FLAG_THREAD_RESOURCE_LOOP 2
52 /* This exec ctx was initialized by an internal thread, and should not
53  be counted by fork handlers */
54 #define GRPC_EXEC_CTX_FLAG_IS_INTERNAL_THREAD 4
55 
56 /* This application callback exec ctx was initialized by an internal thread, and
57  should not be counted by fork handlers */
58 #define GRPC_APP_CALLBACK_EXEC_CTX_FLAG_IS_INTERNAL_THREAD 1
59 
64 grpc_millis grpc_cycle_counter_to_millis_round_up(gpr_cycle_counter cycles);
65 
66 namespace grpc_core {
67 class Combiner;
106 class ExecCtx {
107  public:
112  Set(this);
113  }
114 
116  explicit ExecCtx(uintptr_t fl) : flags_(fl) {
117  if (!(GRPC_EXEC_CTX_FLAG_IS_INTERNAL_THREAD & flags_)) {
119  }
120  Set(this);
121  }
122 
124  virtual ~ExecCtx() {
126  Flush();
127  Set(last_exec_ctx_);
128  if (!(GRPC_EXEC_CTX_FLAG_IS_INTERNAL_THREAD & flags_)) {
130  }
131  }
132 
134  ExecCtx(const ExecCtx&) = delete;
135  ExecCtx& operator=(const ExecCtx&) = delete;
136 
137  unsigned starting_cpu() {
138  if (starting_cpu_ == std::numeric_limits<unsigned>::max()) {
139  starting_cpu_ = gpr_cpu_current_cpu();
140  }
141  return starting_cpu_;
142  }
143 
144  struct CombinerData {
145  /* currently active combiner: updated only via combiner.c */
147  /* last active combiner in the active combiner list */
149  };
150 
152  CombinerData* combiner_data() { return &combiner_data_; }
153 
155  grpc_closure_list* closure_list() { return &closure_list_; }
156 
158  uintptr_t flags() { return flags_; }
159 
161  bool HasWork() {
162  return combiner_data_.active_combiner != nullptr ||
163  !grpc_closure_list_empty(closure_list_);
164  }
165 
170  bool Flush();
171 
177  if ((flags_ & GRPC_EXEC_CTX_FLAG_IS_FINISHED) == 0) {
178  if (CheckReadyToFinish()) {
180  return true;
181  }
182  return false;
183  } else {
184  return true;
185  }
186  }
187 
192  grpc_millis Now();
193 
197  void InvalidateNow() { now_is_valid_ = false; }
198 
201  now_ = GRPC_MILLIS_INF_FUTURE;
202  now_is_valid_ = true;
203  }
204 
208  void TestOnlySetNow(grpc_millis new_val) {
209  now_ = new_val;
210  now_is_valid_ = true;
211  }
212 
213  static void TestOnlyGlobalInit(gpr_timespec new_val);
214 
216  static void GlobalInit(void);
217 
219  static void GlobalShutdown(void) { gpr_tls_destroy(&exec_ctx_); }
220 
222  static ExecCtx* Get() {
223  return reinterpret_cast<ExecCtx*>(gpr_tls_get(&exec_ctx_));
224  }
225 
226  static void Set(ExecCtx* exec_ctx) {
227  gpr_tls_set(&exec_ctx_, reinterpret_cast<intptr_t>(exec_ctx));
228  }
229 
230  static void Run(const DebugLocation& location, grpc_closure* closure,
232 
233  static void RunList(const DebugLocation& location, grpc_closure_list* list);
234 
235  protected:
237  virtual bool CheckReadyToFinish() { return false; }
238 
240  static void operator delete(void* /* p */) { abort(); }
241 
242  private:
246  CombinerData combiner_data_ = {nullptr, nullptr};
247  uintptr_t flags_;
248 
249  unsigned starting_cpu_ = std::numeric_limits<unsigned>::max();
250 
251  bool now_is_valid_ = false;
252  grpc_millis now_ = 0;
253 
254  GPR_TLS_CLASS_DECL(exec_ctx_);
255  ExecCtx* last_exec_ctx_ = Get();
256 };
257 
306  public:
308  ApplicationCallbackExecCtx() { Set(this, flags_); }
309 
311  explicit ApplicationCallbackExecCtx(uintptr_t fl) : flags_(fl) {
312  Set(this, flags_);
313  }
314 
316  if (reinterpret_cast<ApplicationCallbackExecCtx*>(
317  gpr_tls_get(&callback_exec_ctx_)) == this) {
318  while (head_ != nullptr) {
319  auto* f = head_;
320  head_ = f->internal_next;
321  if (f->internal_next == nullptr) {
322  tail_ = nullptr;
323  }
324  (*f->functor_run)(f, f->internal_success);
325  }
326  gpr_tls_set(&callback_exec_ctx_, reinterpret_cast<intptr_t>(nullptr));
329  }
330  } else {
331  GPR_DEBUG_ASSERT(head_ == nullptr);
332  GPR_DEBUG_ASSERT(tail_ == nullptr);
333  }
334  }
335 
336  uintptr_t Flags() { return flags_; }
337 
339  return reinterpret_cast<ApplicationCallbackExecCtx*>(
340  gpr_tls_get(&callback_exec_ctx_));
341  }
342 
343  static void Set(ApplicationCallbackExecCtx* exec_ctx, uintptr_t flags) {
344  if (Get() == nullptr) {
347  }
348  gpr_tls_set(&callback_exec_ctx_, reinterpret_cast<intptr_t>(exec_ctx));
349  }
350  }
351 
352  static void Enqueue(grpc_completion_queue_functor* functor, int is_success) {
353  functor->internal_success = is_success;
354  functor->internal_next = nullptr;
355 
357 
358  if (ctx->head_ == nullptr) {
359  ctx->head_ = functor;
360  }
361  if (ctx->tail_ != nullptr) {
362  ctx->tail_->internal_next = functor;
363  }
364  ctx->tail_ = functor;
365  }
366 
368  static void GlobalInit(void) { gpr_tls_init(&callback_exec_ctx_); }
369 
371  static void GlobalShutdown(void) { gpr_tls_destroy(&callback_exec_ctx_); }
372 
373  static bool Available() { return Get() != nullptr; }
374 
375  private:
376  uintptr_t flags_{0u};
377  grpc_completion_queue_functor* head_{nullptr};
378  grpc_completion_queue_functor* tail_{nullptr};
379  GPR_TLS_CLASS_DECL(callback_exec_ctx_);
380 };
381 } // namespace grpc_core
382 
383 #endif /* GRPC_CORE_LIB_IOMGR_EXEC_CTX_H */
Application-callback execution context.
Definition: exec_ctx.h:305
~ApplicationCallbackExecCtx()
Definition: exec_ctx.h:315
static void Enqueue(grpc_completion_queue_functor *functor, int is_success)
Definition: exec_ctx.h:352
static bool Available()
Definition: exec_ctx.h:373
ApplicationCallbackExecCtx(uintptr_t fl)
Parameterised Constructor.
Definition: exec_ctx.h:311
static void Set(ApplicationCallbackExecCtx *exec_ctx, uintptr_t flags)
Definition: exec_ctx.h:343
ApplicationCallbackExecCtx()
Default Constructor.
Definition: exec_ctx.h:308
uintptr_t Flags()
Definition: exec_ctx.h:336
static void GlobalShutdown(void)
Global shutdown for ApplicationCallbackExecCtx.
Definition: exec_ctx.h:371
static ApplicationCallbackExecCtx * Get()
Definition: exec_ctx.h:338
static void GlobalInit(void)
Global initialization for ApplicationCallbackExecCtx.
Definition: exec_ctx.h:368
Definition: combiner.h:33
Definition: debug_location.h:31
Execution context.
Definition: exec_ctx.h:106
bool Flush()
Flush any work that has been enqueued onto this grpc_exec_ctx.
Definition: exec_ctx.cc:154
static void Run(const DebugLocation &location, grpc_closure *closure, grpc_error_handle error)
Definition: exec_ctx.cc:184
static ExecCtx * Get()
Gets pointer to current exec_ctx.
Definition: exec_ctx.h:222
ExecCtx(uintptr_t fl)
Parameterised Constructor.
Definition: exec_ctx.h:116
ExecCtx & operator=(const ExecCtx &)=delete
bool HasWork()
Checks if there is work to be done.
Definition: exec_ctx.h:161
static void RunList(const DebugLocation &location, grpc_closure_list *list)
Definition: exec_ctx.cc:210
ExecCtx(const ExecCtx &)=delete
Disallow copy and assignment operators.
unsigned starting_cpu()
Definition: exec_ctx.h:137
void InvalidateNow()
Invalidates the stored time value.
Definition: exec_ctx.h:197
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:176
virtual bool CheckReadyToFinish()
Check if ready to finish.
Definition: exec_ctx.h:237
grpc_millis Now()
Returns the stored current time relative to start if valid, otherwise refreshes the stored time,...
Definition: exec_ctx.cc:176
virtual ~ExecCtx()
Destructor.
Definition: exec_ctx.h:124
static void Set(ExecCtx *exec_ctx)
Definition: exec_ctx.h:226
static void GlobalInit(void)
Global initialization for ExecCtx.
Definition: exec_ctx.cc:143
uintptr_t flags()
Return flags.
Definition: exec_ctx.h:158
grpc_closure_list * closure_list()
Return pointer to grpc_closure_list.
Definition: exec_ctx.h:155
static void TestOnlyGlobalInit(gpr_timespec new_val)
Definition: exec_ctx.cc:138
static void GlobalShutdown(void)
Global shutdown for ExecCtx.
Definition: exec_ctx.h:219
CombinerData * combiner_data()
Only to be used by grpc-combiner code.
Definition: exec_ctx.h:152
void SetNowIomgrShutdown()
To be used only by shutdown code in iomgr.
Definition: exec_ctx.h:200
void TestOnlySetNow(grpc_millis new_val)
To be used only for testing.
Definition: exec_ctx.h:208
ExecCtx()
Default Constructor.
Definition: exec_ctx.h:110
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:167
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:37
#define GRPC_EXEC_CTX_FLAG_IS_INTERNAL_THREAD
Definition: exec_ctx.h:54
#define GRPC_APP_CALLBACK_EXEC_CTX_FLAG_IS_INTERNAL_THREAD
Definition: exec_ctx.h:58
grpc_millis grpc_cycle_counter_to_millis_round_down(gpr_cycle_counter cycles)
Definition: exec_ctx.cc:123
#define GRPC_EXEC_CTX_FLAG_IS_FINISHED
Definition: exec_ctx.h:48
gpr_timespec grpc_millis_to_timespec(grpc_millis millis, gpr_clock_type clock)
Definition: exec_ctx.cc:95
grpc_millis grpc_cycle_counter_to_millis_round_up(gpr_cycle_counter cycles)
Definition: exec_ctx.cc:128
struct grpc_combiner grpc_combiner
A combiner represents a list of work to be executed later.
Definition: exec_ctx.h:44
#define GRPC_MILLIS_INF_FUTURE
Definition: exec_ctx.h:39
grpc_millis grpc_timespec_to_millis_round_up(gpr_timespec ts)
Definition: exec_ctx.cc:118
grpc_millis grpc_timespec_to_millis_round_down(gpr_timespec ts)
Definition: exec_ctx.cc:113
gpr_clock_type
The clocks we support.
Definition: gpr_types.h:31
#define GPR_DEBUG_ASSERT(x)
Definition: log.h:101
grpc_error_handle error
Definition: lame_client.cc:54
Round Robin Policy.
Definition: backend_metric.cc:26
grpc_closure closure
Definition: server.cc:460
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
Specifies an interface class to be used as a tag for callback-based completion queues.
Definition: grpc_types.h:757
int internal_success
The following fields are not API.
Definition: grpc_types.h:769
struct grpc_completion_queue_functor * internal_next
Definition: grpc_types.h:770
Definition: exec_ctx.h:144
Combiner * last_combiner
Definition: exec_ctx.h:148
Combiner * active_combiner
Definition: exec_ctx.h:146
Definition: error_internal.h:41
#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)