Introduce interruptor tool
An interruptor instance will help to wake up a blocking call from another thread (typically to terminate immediately on Ctrl+C).
This commit is contained in:
78
app/src/util/intr.h
Normal file
78
app/src/util/intr.h
Normal file
@@ -0,0 +1,78 @@
|
||||
#ifndef SC_INTR_H
|
||||
#define SC_INTR_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#include <stdatomic.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "net.h"
|
||||
#include "process.h"
|
||||
#include "thread.h"
|
||||
|
||||
/**
|
||||
* Interruptor to wake up a blocking call from another thread
|
||||
*
|
||||
* It allows to register a socket or a process before a blocking call, and
|
||||
* interrupt/close from another thread to wake up the blocking call.
|
||||
*/
|
||||
struct sc_intr {
|
||||
sc_mutex mutex;
|
||||
|
||||
sc_socket socket;
|
||||
sc_pid process;
|
||||
|
||||
// Written protected by the mutex to avoid race conditions against
|
||||
// sc_intr_set_socket() and sc_intr_set_process(), but can be read
|
||||
// (atomically) without mutex
|
||||
atomic_bool interrupted;
|
||||
};
|
||||
|
||||
/**
|
||||
* Initialize an interruptor
|
||||
*/
|
||||
bool
|
||||
sc_intr_init(struct sc_intr *intr);
|
||||
|
||||
/**
|
||||
* Set a socket as the interruptible component
|
||||
*
|
||||
* Call with SC_INVALID_SOCKET to unset.
|
||||
*/
|
||||
bool
|
||||
sc_intr_set_socket(struct sc_intr *intr, sc_socket socket);
|
||||
|
||||
/**
|
||||
* Set a process as the interruptible component
|
||||
*
|
||||
* Call with SC_PROCESS_NONE to unset.
|
||||
*/
|
||||
bool
|
||||
sc_intr_set_process(struct sc_intr *intr, sc_pid socket);
|
||||
|
||||
/**
|
||||
* Interrupt the current interruptible component
|
||||
*
|
||||
* Must be called from a different thread.
|
||||
*/
|
||||
void
|
||||
sc_intr_interrupt(struct sc_intr *intr);
|
||||
|
||||
/**
|
||||
* Read the interrupted state
|
||||
*
|
||||
* It is exposed as a static inline function because it just loads from an
|
||||
* atomic.
|
||||
*/
|
||||
static inline bool
|
||||
sc_intr_is_interrupted(struct sc_intr *intr) {
|
||||
return atomic_load_explicit(&intr->interrupted, memory_order_relaxed);
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy the interruptor
|
||||
*/
|
||||
void
|
||||
sc_intr_destroy(struct sc_intr *intr);
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user