chromium/mojo/public/c/system/trap.h

// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef MOJO_PUBLIC_C_SYSTEM_TRAP_H_
#define MOJO_PUBLIC_C_SYSTEM_TRAP_H_

#include <stdint.h>

#include "mojo/public/c/system/macros.h"
#include "mojo/public/c/system/system_export.h"
#include "mojo/public/c/system/types.h"

// Flags passed to trap event handlers within |MojoTrapEvent|.
MojoTrapEventFlags;

#ifdef __cplusplus
inline constexpr MojoTrapEventFlags MOJO_TRAP_EVENT_FLAG_NONE =;
inline constexpr MojoTrapEventFlags MOJO_TRAP_EVENT_FLAG_WITHIN_API_CALL =;
#else
#define MOJO_TRAP_EVENT_FLAG_NONE
#define MOJO_TRAP_EVENT_FLAG_WITHIN_API_CALL
#endif

// Structure passed to trap event handlers when invoked by a tripped trap.
struct MOJO_ALIGNAS(8) MojoTrapEvent {};
MOJO_STATIC_ASSERT();

// Value given to |MojoAddTrigger| to configure what condition should cause it
// to trip its trap. May be one of the following values:
//
//   |MOJO_TRIGGER_CONDITION_SIGNALS_UNSATISFIED| - A trigger added with this
//       condition will trip its trap when any of its observed signals
//       transition from being satisfied to being unsatisfied.
//   |MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED| - A triger added with this
//       condition will trip its trap  when any of its observed signals
//       transition from being unsatisfied to being satisfied, or when none of
//       the observed signals can ever be satisfied again.
MojoTriggerCondition;

#ifdef __cplusplus
inline constexpr MojoTriggerCondition
    MOJO_TRIGGER_CONDITION_SIGNALS_UNSATISFIED =;
inline constexpr MojoTriggerCondition MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED =;
#else
#define MOJO_TRIGGER_CONDITION_SIGNALS_UNSATISFIED
#define MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED
#endif

// Flags passed to |MojoCreateTrap()| via |MojoCreateTrapOptions|.
MojoCreateTrapFlags;

#ifdef __cplusplus
inline constexpr MojoCreateTrapFlags MOJO_CREATE_TRAP_FLAG_NONE =;
#else
#define MOJO_CREATE_TRAP_FLAG_NONE
#endif

// Options passed to |MojoCreateTrap()|.
struct MOJO_ALIGNAS(8) MojoCreateTrapOptions {};
MOJO_STATIC_ASSERT();

// Flags passed to |MojoAddTrigger()| via |MojoAddTriggerOptions|.
MojoAddTriggerFlags;

#ifdef __cplusplus
inline constexpr MojoAddTriggerFlags MOJO_ADD_TRIGGER_FLAG_NONE =;
#else
#define MOJO_ADD_TRIGGER_FLAG_NONE
#endif

// Options passed to |MojoAddTrigger()|.
struct MOJO_ALIGNAS(8) MojoAddTriggerOptions {};
MOJO_STATIC_ASSERT();

// Flags passed to |MojoRemoveTrigger()| via |MojoRemoveTriggerOptions|.
MojoRemoveTriggerFlags;

#ifdef __cplusplus
inline constexpr MojoRemoveTriggerFlags MOJO_REMOVE_TRIGGER_FLAG_NONE =;
#else
#define MOJO_REMOVE_TRIGGER_FLAG_NONE
#endif

// Options passed to |MojoRemoveTrigger()|.
struct MOJO_ALIGNAS(8) MojoRemoveTriggerOptions {};
MOJO_STATIC_ASSERT();

// Flags passed to |MojoArmTrap()| via |MojoArmTrapOptions|.
MojoArmTrapFlags;

#ifdef __cplusplus
inline constexpr MojoArmTrapFlags MOJO_ARM_TRAP_FLAG_NONE =;
#else
#define MOJO_ARM_TRAP_FLAG_NONE
#endif

// Options passed to |MojoArmTrap()|.
struct MOJO_ALIGNAS(8) MojoArmTrapOptions {};
MOJO_STATIC_ASSERT();

#ifdef __cplusplus
extern "C" {
#endif

// A user-provided callback to handle trap events. Passed to |MojoCreateTrap()|.
MojoTrapEventHandler;

// Creates a new trap which can be used to detect signal changes on a handle.
// Traps execute arbitrary user code when tripped.
//
// Traps can trip only while armed**, and new traps are created in a disarmed
// state. Traps may be armed using |MojoArmTrap()|.
//
// Arming a trap is only possible when the trap has one or more triggers
// attached to it. Triggers can be added or removed using |MojoAddTrigger()| and
// |MojoRemoveTrigger()|.
//
// If a trap is tripped by any of its triggers, it is disarmed immediately and
// the traps |MojoTrapEventHandler| is invoked once for every relevant trigger.
//
// |options| may be null.
//
// ** An unarmed trap will still fire an event when a trigger is removed. This
// event will always convey the result |MOJO_RESULT_CANCELLED|.
//
// Parameters:
//   |handler|: The |MojoTrapEventHandler| to invoke any time this trap is
//       tripped. Note that this may be called from any arbitrary thread.
//   |trap_handle|: The address at which to store the MojoHandle corresponding
//       to the new trap if successfully created.
//
// Returns:
//   |MOJO_RESULT_OK| if the trap has been successfully created.
//   |MOJO_RESULT_RESOURCE_EXHAUSTED| if a handle could not be allocated for
//       this trap.
MOJO_SYSTEM_EXPORT MojoResult
MojoCreateTrap(MojoTrapEventHandler handler,
               const struct MojoCreateTrapOptions* options,
               MojoHandle* trap_handle);

// Adds a trigger to a trap. This configures the trap to invoke its event
// handler if the specified conditions are met (or can no longer be met) while
// the trap is armed.
//
// Note that event handler invocations for a given trigger are mutually
// exclusive in execution: the handler will never be entered for a trigger while
// another thread is executing it for the same trigger. Similarly, event
// handlers are never re-entered. If an event handler changes the state of the
// system such that another event would fire, that event is deferred until the
// first handler returns.
//
// Parameters:
//   |trap_handle|: The trap to which this trigger is to be added.
//   |handle|: The handle whose signals this trigger will observe. Must be a
//       message pipe or data pipe handle.
//   |signals|: The specific signal(s) this trigger will observe on |handle|.
//   |condition|: The signaling condition this trigger will observe. i.e.
//       whether to trip the trap when |signals| become satisfied or when they
//       become unsatisfied.
//   |context|: An arbitrary context value to be passed to the trap's event
//       handler when this trigger was responsible for tripping the trap. See
//       the |trigger_context| field in |MojoTrapEvent|. This value must be
//       unique among all triggers on the trap.
//
//   |options| may be null.
//
// Returns:
//   |MOJO_RESULT_OK| if the handle is now being observed by the trigger.
//   |MOJO_RESULT_INVALID_ARGUMENT| if |trap_handle| is not a trap handle,
//       |handle| is not a valid message pipe or data pipe handle, or |signals|
//       or |condition| are an invalid value.
//   |MOJO_RESULT_ALREADY_EXISTS| if the trap already has a trigger associated
//       with |context| or |handle|.
MOJO_SYSTEM_EXPORT MojoResult
MojoAddTrigger(MojoHandle trap_handle,
               MojoHandle handle,
               MojoHandleSignals signals,
               MojoTriggerCondition condition,
               uintptr_t context,
               const struct MojoAddTriggerOptions* options);

// Removes a trigger from a trap.
//
// This ensures that the trigger is removed as soon as possible. Removal may
// block an arbitrarily long time if the trap is already executing its handler.
//
// When removal is complete, the trap's handler is invoked one final time for
// time for |context|, with the result |MOJO_RESULT_CANCELLED|.
//
// The same  behavior can be elicted by either closing the watched handle
// associated with this trigger, or by closing |trap_handle| itself.
//
// Parameters:
//   |trap_handle|: The handle of the trap from which to remove a trigger.
//   |context|: The context of the trigger to be removed.
//
// Returns:
//   |MOJO_RESULT_OK| if the trigger has been removed.
//   |MOJO_RESULT_INVALID_ARGUMENT| if |trap_handle| is not a trap handle.
//   |MOJO_RESULT_NOT_FOUND| if there is no trigger registered on this trap for
//       the given value of |context|.
MOJO_SYSTEM_EXPORT MojoResult
MojoRemoveTrigger(MojoHandle trap_handle,
                  uintptr_t context,
                  const struct MojoRemoveTriggerOptions* options);

// Arms a trap, allowing it to invoke its event handler the next time any of its
// triggers' conditions are met.
//
// Parameters:
//   |trap_handle|: The handle of the trap to be armed.
//   |num_blocking_events|: An address pointing to the number of elements
//       available for storage at the address given by |blocking_events|.
//       Optional and only used when |MOJO_RESULT_FAILED_PRECONDITION| is
//       returned. See below.
//   |blocking_events|: An output buffer for |MojoTrapEvent| structures to be
//       filled in if one or more triggers would have tripped the trap
//       immediately if it were armed. Optional and used only when
//       |MOJO_RESULT_FAILED_PRECONDITION| is returned. See below.
//
// Returns:
//   |MOJO_RESULT_OK| if the trap has been successfully armed.
//       |num_blocking_events| and |blocking_events| are ignored.
//   |MOJO_RESULT_NOT_FOUND| if the trap does not have any triggers.
//       |num_blocking_events| and |blocking_events| are ignored.
//   |MOJO_RESULT_INVALID_ARGUMENT| if |trap_handle| is not a valid trap handle,
//       or if |num_blocking_events| is non-null but |blocking_events| is
//       not.
//   |MOJO_RESULT_FAILED_PRECONDITION| if one or more triggers would have
//       tripped the trap immediately upon arming. If |num_blocking_events| is
//       non-null, this assumes there is enough space for |*num_blocking_events|
//       entries at the non-null address in |blocking_events|.
//
//       At most |*num_blocking_events| entries are populated there, with each
//       entry corresponding to one of the triggers which would have tripped the
//       trap. The actual number of entries populated is written to
//       |*num_blocking_events| before returning.
//
//       If there are more ready triggers than available provided storage, the
//       subset presented to the caller is arbitrary. The runtime makes an
//       effort to circulate triggers returned by consecutive failed
//       |MojoArmTrap()| calls so that callers may avoid handle starvation when
//       observing a large number of active handles with a single trap.
MOJO_SYSTEM_EXPORT MojoResult
MojoArmTrap(MojoHandle trap_handle,
            const struct MojoArmTrapOptions* options,
            uint32_t* num_blocking_events,
            struct MojoTrapEvent* blocking_events);

#ifdef __cplusplus
}  // extern "C"
#endif

#endif  // MOJO_PUBLIC_C_SYSTEM_TRAP_H_