chromium/third_party/grpc/src/src/core/lib/iomgr/exec_ctx.h

//
//
// Copyright 2015 gRPC authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
//

#ifndef GRPC_SRC_CORE_LIB_IOMGR_EXEC_CTX_H
#define GRPC_SRC_CORE_LIB_IOMGR_EXEC_CTX_H

#include <grpc/support/port_platform.h>

#include <limits>

#include <grpc/impl/grpc_types.h>
#include <grpc/support/atm.h>
#include <grpc/support/cpu.h>
#include <grpc/support/log.h>
#include <grpc/support/time.h>

#include "src/core/lib/gpr/time_precise.h"
#include "src/core/lib/gprpp/crash.h"
#include "src/core/lib/gprpp/debug_location.h"
#include "src/core/lib/gprpp/fork.h"
#include "src/core/lib/gprpp/time.h"
#include "src/core/lib/iomgr/closure.h"

/// A combiner represents a list of work to be executed later.
/// Forward declared here to avoid a circular dependency with combiner.h.
grpc_combiner;

// This exec_ctx is ready to return: either pre-populated, or cached as soon as
// the finish_check returns true
#define GRPC_EXEC_CTX_FLAG_IS_FINISHED
// The exec_ctx's thread is (potentially) owned by a call or channel: care
// should be given to not delete said call/channel from this exec_ctx
#define GRPC_EXEC_CTX_FLAG_THREAD_RESOURCE_LOOP
// This exec ctx was initialized by an internal thread, and should not
// be counted by fork handlers
#define GRPC_EXEC_CTX_FLAG_IS_INTERNAL_THREAD

// This application callback exec ctx was initialized by an internal thread, and
// should not be counted by fork handlers
#define GRPC_APP_CALLBACK_EXEC_CTX_FLAG_IS_INTERNAL_THREAD

namespace grpc_core {
class Combiner;
/// Execution context.
/// A bag of data that collects information along a callstack.
/// It is created on the stack at core entry points (public API or iomgr), and
/// stored internally as a thread-local variable.
///
/// Generally, to create an exec_ctx instance, add the following line at the top
/// of the public API entry point or at the start of a thread's work function :
///
/// ExecCtx exec_ctx;
///
/// Access the created ExecCtx instance using :
/// ExecCtx::Get()
///
/// Specific responsibilities (this may grow in the future):
/// - track a list of core work that needs to be delayed until the base of the
///   call stack (this provides a convenient mechanism to run callbacks
///   without worrying about locking issues)
/// - provide a decision maker (via IsReadyToFinish) that provides a
///   signal as to whether a borrowed thread should continue to do work or
///   should actively try to finish up and get this thread back to its owner
///
/// CONVENTIONS:
/// - Instance of this must ALWAYS be constructed on the stack, never
///   heap allocated.
/// - Do not pass exec_ctx as a parameter to a function. Always access it using
///   ExecCtx::Get().
/// - NOTE: In the future, the convention is likely to change to allow only one
///         ExecCtx on a thread's stack at the same time. The TODO below
///         discusses this plan in more detail.
///
/// TODO(yashykt): Only allow one "active" ExecCtx on a thread at the same time.
///               Stage 1: If a new one is created on the stack, it should just
///               pass-through to the underlying ExecCtx deeper in the thread's
///               stack.
///               Stage 2: Assert if a 2nd one is ever created on the stack
///               since that implies a core re-entry outside of application
///               callbacks.
///
class ExecCtx {};

/// Application-callback execution context.
/// A bag of data that collects information along a callstack.
/// It is created on the stack at core entry points, and stored internally
/// as a thread-local variable.
///
/// There are three key differences between this structure and ExecCtx:
///   1. ApplicationCallbackExecCtx builds a list of application-level
///      callbacks, but ExecCtx builds a list of internal callbacks to invoke.
///   2. ApplicationCallbackExecCtx invokes its callbacks only at destruction;
///      there is no explicit Flush method.
///   3. If more than one ApplicationCallbackExecCtx is created on the thread's
///      stack, only the one closest to the base of the stack is actually
///      active and this is the only one that enqueues application callbacks.
///      (Unlike ExecCtx, it is not feasible to prevent multiple of these on the
///      stack since the executing application callback may itself enter core.
///      However, the new one created will just pass callbacks through to the
///      base one and those will not be executed until the return to the
///      destructor of the base one, preventing unlimited stack growth.)
///
/// This structure exists because application callbacks may themselves cause a
/// core re-entry (e.g., through a public API call) and if that call in turn
/// causes another application-callback, there could be arbitrarily growing
/// stacks of core re-entries. Instead, any application callbacks instead should
/// not be invoked until other core work is done and other application callbacks
/// have completed. To accomplish this, any application callback should be
/// enqueued using ApplicationCallbackExecCtx::Enqueue .
///
/// CONVENTIONS:
/// - Instances of this must ALWAYS be constructed on the stack, never
///   heap allocated.
/// - Instances of this are generally constructed before ExecCtx when needed.
///   The only exception is for ExecCtx's that are explicitly flushed and
///   that survive beyond the scope of the function that can cause application
///   callbacks to be invoked (e.g., in the timer thread).
///
/// Generally, core entry points that may trigger application-level callbacks
/// will have the following declarations:
///
/// ApplicationCallbackExecCtx callback_exec_ctx;
/// ExecCtx exec_ctx;
///
/// This ordering is important to make sure that the ApplicationCallbackExecCtx
/// is destroyed after the ExecCtx (to prevent the re-entry problem described
/// above, as well as making sure that ExecCtx core callbacks are invoked first)
///
///

class ApplicationCallbackExecCtx {};

}  // namespace grpc_core

#endif  // GRPC_SRC_CORE_LIB_IOMGR_EXEC_CTX_H