Skip to content

File dp_interrupt_guard_core.h

FileList > dp_interrupt_guard > dp_interrupt_guard_core.h

Go to the source code of this file

  • #include "dp_interrupt.h"
  • #include <stddef.h>
  • #include <stdint.h>

Public Types

Type Name
typedef dp_interrupt_guard_t dp_interrupt_guard_state_t
typedef struct dp_interrupt_guard dp_interrupt_guard_t
A scoped handle to the process-wide interrupt facility.

Public Functions

Type Name
dp_interrupt_guard_t * dp_interrupt_guard_create (const int32_t * signals, size_t n_signals, uint32_t latency_ms)
Clear the flag, optionally install handlers, and remember what to undo.
void dp_interrupt_guard_destroy (dp_interrupt_guard_t * guard)
Restore every handler and latency this guard changed.
void dp_interrupt_guard_interrupt (dp_interrupt_guard_t * guard)
Ask every blocking wait in this process to stop.
int dp_interrupt_guard_interrupted (const dp_interrupt_guard_t * guard)
Non-zero once a stop has been requested.
uint32_t dp_interrupt_guard_latency_ms (const dp_interrupt_guard_t * guard)
The wait slice every blocking wait in this process uses.
void dp_interrupt_guard_resume (dp_interrupt_guard_t * guard)
Clear the flag so waits proceed again.

Public Types Documentation

typedef dp_interrupt_guard_state_t

typedef dp_interrupt_guard_t dp_interrupt_guard_state_t;

typedef dp_interrupt_guard_t

A scoped handle to the process-wide interrupt facility.

typedef struct dp_interrupt_guard dp_interrupt_guard_t;

The flag above is process-wide and stays so, so this is a handle to a facility rather than an instance of one: two guards observe the same flag. What a guard scopes is the arming which signals it installed, and the latency it overrode so that both can be undone exactly, by the code that did them, without a caller tracking it.

It exists because that bookkeeping had been living in the Python binding, which is the one place doppler does not put logic. See docs/design/io-termination.md.


Public Functions Documentation

function dp_interrupt_guard_create

Clear the flag, optionally install handlers, and remember what to undo.

dp_interrupt_guard_t * dp_interrupt_guard_create (
    const int32_t * signals,
    size_t n_signals,
    uint32_t latency_ms
) 

Construction is what ARMS: on return the handlers are installed and the flag is clear. A stale flag would otherwise refuse the first wait inside the very block that just armed it.

Parameters:

  • signals Signals to install on; may be NULL for none, in which case the guard is only a handle to the flag.
  • n_signals How many signals holds.
  • latency_ms Wait-slice override; 0 leaves the process setting alone, and only a non-zero value is restored. Fixed width rather than unsigned, because a public ABI should not carry a platform-dependent one.

Returns:

A guard, or NULL if a handler could not be installed in which case any already installed by this call are restored first, so a failed create arms nothing.

>>> from doppler.interrupt import Interrupt
>>> it = Interrupt([])
>>> it.interrupted()
0

function dp_interrupt_guard_destroy

Restore every handler and latency this guard changed.

void dp_interrupt_guard_destroy (
    dp_interrupt_guard_t * guard
) 

Does NOT clear the flag: a caller that was interrupted still needs to see that it was, after the block that noticed has exited.

Parameters:

  • guard Guard; NULL is a no-op.

function dp_interrupt_guard_interrupt

Ask every blocking wait in this process to stop.

void dp_interrupt_guard_interrupt (
    dp_interrupt_guard_t * guard
) 

The object's face onto dp_interrupt(). It takes a guard because that is how a method is called, not because the request is scoped to one the flag is process-wide, and a request through any guard is seen by every waiter.

Parameters:

  • guard Guard; NULL is a no-op.
>>> from doppler.interrupt import Interrupt
>>> it = Interrupt([])
>>> it.interrupt()
>>> it.interrupted()
1

function dp_interrupt_guard_interrupted

Non-zero once a stop has been requested.

int dp_interrupt_guard_interrupted (
    const dp_interrupt_guard_t * guard
) 

Parameters:

  • guard Guard; NULL reads the flag anyway, since it is process-wide and a guard is not what holds it.

Returns:

Non-zero if interrupted.

>>> from doppler.interrupt import Interrupt
>>> import numpy as np
>>> it = Interrupt(np.array([], dtype=np.int32))
>>> it.interrupted()
0
>>> it.interrupt()
>>> it.interrupted()
1

function dp_interrupt_guard_latency_ms

The wait slice every blocking wait in this process uses.

uint32_t dp_interrupt_guard_latency_ms (
    const dp_interrupt_guard_t * guard
) 

The readback for the constructor's latency_ms, and it reads the PROCESS setting rather than what this guard asked for those differ when the guard passed 0, which means "leave it alone". A value a caller can set and not read back is a value they cannot reason about.

Parameters:

  • guard Guard; NULL reads the process setting anyway.

Returns:

Milliseconds.

>>> import numpy as np
>>> from doppler.interrupt import Interrupt
>>> it = Interrupt(np.array([], dtype=np.int32), latency_ms=25)
>>> it.latency_ms()
25

function dp_interrupt_guard_resume

Clear the flag so waits proceed again.

void dp_interrupt_guard_resume (
    dp_interrupt_guard_t * guard
) 

Parameters:

  • guard Guard; NULL is still honoured, for the reason above.
>>> from doppler.interrupt import Interrupt
>>> it = Interrupt([])
>>> it.interrupt()
>>> it.resume()
>>> it.interrupted()
0


The documentation for this class was generated from the following file native/inc/dp_interrupt_guard/dp_interrupt_guard_core.h