aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/lib/iomgr/exec_ctx.h
diff options
context:
space:
mode:
authorGravatar Yash Tibrewal <yashkt@google.com>2017-10-13 16:07:13 -0700
committerGravatar Yash Tibrewal <yashkt@google.com>2017-10-18 17:12:19 -0700
commit0ee7574732a06e8cace4e099a678f4bd5dbff679 (patch)
treee43d5de442fdcc3d39cd5af687f319fa39612d3f /src/core/lib/iomgr/exec_ctx.h
parent6bf5f833efe2cb9e2ecc14358dd9699cd5d05263 (diff)
Removing instances of exec_ctx being passed around in functions in
src/core. exec_ctx is now a thread_local pointer of type ExecCtx instead of grpc_exec_ctx which is initialized whenever ExecCtx is instantiated. ExecCtx also keeps track of the previous exec_ctx so that nesting of exec_ctx is allowed. This means that there is only one exec_ctx being used at any time. Also, grpc_exec_ctx_finish is called in the destructor of the object, and the previous exec_ctx is restored to avoid breaking current functionality. The code still explicitly calls grpc_exec_ctx_finish because removing all such instances causes the code to break.
Diffstat (limited to 'src/core/lib/iomgr/exec_ctx.h')
-rw-r--r--src/core/lib/iomgr/exec_ctx.h76
1 files changed, 54 insertions, 22 deletions
diff --git a/src/core/lib/iomgr/exec_ctx.h b/src/core/lib/iomgr/exec_ctx.h
index 44b9be7aa9..f79c7ae89a 100644
--- a/src/core/lib/iomgr/exec_ctx.h
+++ b/src/core/lib/iomgr/exec_ctx.h
@@ -21,6 +21,7 @@
#include <grpc/support/atm.h>
#include <grpc/support/cpu.h>
+#include <grpc/support/log.h>
#include "src/core/lib/iomgr/closure.h"
@@ -74,56 +75,87 @@ struct grpc_exec_ctx {
uintptr_t flags;
unsigned starting_cpu;
void *check_ready_to_finish_arg;
- bool (*check_ready_to_finish)(grpc_exec_ctx *exec_ctx, void *arg);
+ bool (*check_ready_to_finish)(void *arg);
bool now_is_valid;
grpc_millis now;
+ const char *creator;
};
-/* initializer for grpc_exec_ctx:
- prefer to use GRPC_EXEC_CTX_INIT whenever possible */
-#define GRPC_EXEC_CTX_INITIALIZER(flags, finish_check, finish_check_arg) \
- { \
- GRPC_CLOSURE_LIST_INIT, NULL, NULL, flags, gpr_cpu_current_cpu(), \
- finish_check_arg, finish_check, false, 0 \
- }
-
-/* initialize an execution context at the top level of an API call into grpc
- (this is safe to use elsewhere, though possibly not as efficient) */
-#define GRPC_EXEC_CTX_INIT \
- GRPC_EXEC_CTX_INITIALIZER(GRPC_EXEC_CTX_FLAG_IS_FINISHED, NULL, NULL)
-
extern grpc_closure_scheduler *grpc_schedule_on_exec_ctx;
-bool grpc_exec_ctx_has_work(grpc_exec_ctx *exec_ctx);
+bool grpc_exec_ctx_has_work();
/** Flush any work that has been enqueued onto this grpc_exec_ctx.
* Caller must guarantee that no interfering locks are held.
* Returns true if work was performed, false otherwise. */
-bool grpc_exec_ctx_flush(grpc_exec_ctx *exec_ctx);
+bool grpc_exec_ctx_flush();
/** Finish any pending work for a grpc_exec_ctx. Must be called before
* the instance is destroyed, or work may be lost. */
-void grpc_exec_ctx_finish(grpc_exec_ctx *exec_ctx);
+void grpc_exec_ctx_finish();
/** Returns true if we'd like to leave this execution context as soon as
possible: useful for deciding whether to do something more or not depending
on outside context */
-bool grpc_exec_ctx_ready_to_finish(grpc_exec_ctx *exec_ctx);
+bool grpc_exec_ctx_ready_to_finish();
/** A finish check that is never ready to finish */
-bool grpc_never_ready_to_finish(grpc_exec_ctx *exec_ctx, void *arg_ignored);
+bool grpc_never_ready_to_finish(void *arg_ignored);
/** A finish check that is always ready to finish */
-bool grpc_always_ready_to_finish(grpc_exec_ctx *exec_ctx, void *arg_ignored);
+bool grpc_always_ready_to_finish(void *arg_ignored);
void grpc_exec_ctx_global_init(void);
void grpc_exec_ctx_global_init(void);
void grpc_exec_ctx_global_shutdown(void);
-grpc_millis grpc_exec_ctx_now(grpc_exec_ctx *exec_ctx);
-void grpc_exec_ctx_invalidate_now(grpc_exec_ctx *exec_ctx);
+grpc_millis grpc_exec_ctx_now();
+void grpc_exec_ctx_invalidate_now();
gpr_timespec grpc_millis_to_timespec(grpc_millis millis, gpr_clock_type clock);
grpc_millis grpc_timespec_to_millis_round_down(gpr_timespec timespec);
grpc_millis grpc_timespec_to_millis_round_up(gpr_timespec timespec);
+inline grpc_exec_ctx make_exec_ctx(grpc_exec_ctx r) {
+ grpc_exec_ctx_flush();
+ return r;
+}
+
+class ExecCtx {
+ public:
+ ExecCtx();
+ ExecCtx(uintptr_t fl, bool (*finish_check)(void *arg),
+ void *finish_check_arg);
+ ~ExecCtx();
+
+ grpc_closure_list closure_list;
+ /** currently active combiner: updated only via combiner.c */
+ grpc_combiner *active_combiner;
+ /** last active combiner in the active combiner list */
+ grpc_combiner *last_combiner;
+ uintptr_t flags;
+ unsigned starting_cpu;
+ void *check_ready_to_finish_arg;
+ bool (*check_ready_to_finish)(void *arg);
+
+ bool now_is_valid;
+ grpc_millis now;
+
+ private:
+ ExecCtx *last_exec_ctx;
+};
+
+extern thread_local ExecCtx *exec_ctx;
+
+/* initializer for grpc_exec_ctx:
+ * prefer to use GRPC_EXEC_CTX_INIT whenever possible */
+#define GRPC_EXEC_CTX_INITIALIZER(flags, finish_check, finish_check_arg) \
+ make_exec_ctx(grpc_exec_ctx{GRPC_CLOSURE_LIST_INIT, NULL, NULL, flags, \
+ gpr_cpu_current_cpu(), finish_check_arg, \
+ finish_check, false, 0, __PRETTY_FUNCTION__})
+
+/* initialize an execution context at the top level of an API call into grpc
+ (this is safe to use elsewhere, though possibly not as efficient) */
+#define GRPC_EXEC_CTX_INIT \
+ GRPC_EXEC_CTX_INITIALIZER(GRPC_EXEC_CTX_FLAG_IS_FINISHED, NULL, NULL)
+
#ifdef __cplusplus
}
#endif