File: aml.h

package info (click to toggle)
aml 0.3.0-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 220 kB
  • sloc: ansic: 2,042; cpp: 573; makefile: 3
file content (206 lines) | stat: -rw-r--r-- 6,450 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
/*
 * Copyright (c) 2020 - 2022 Andri Yngvason
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 * PERFORMANCE OF THIS SOFTWARE.
 */

#pragma once

#ifndef AML_UNSTABLE_API
#define AML_UNSTABLE_API 0
#endif

/* Something like this is necessary when changes are made that don't break the
 * build but will cause nasty bugs if ignored.
 */
#if AML_UNSTABLE_API != 1
#error "API has changed! Please, observe the changes and acknowledge by defining AML_UNSTABLE_API as 1 before including aml.h"
#endif

#include <stdint.h>
#include <stdbool.h>
#include <unistd.h>

struct aml;
struct aml_handler;
struct aml_timer;
struct aml_ticker;
struct aml_signal;
struct aml_work;
struct aml_idle;

enum aml_event {
	AML_EVENT_NONE = 0,
	AML_EVENT_READ = 1 << 0,
	AML_EVENT_WRITE = 1 << 1,
	AML_EVENT_OOB = 1 << 2,
};

typedef void (*aml_callback_fn)(void* obj);
typedef void (*aml_free_fn)(void*);

extern const char aml_version[];
extern const int aml_unstable_abi_version;

/* Create a new main loop instance */
struct aml* aml_new(void);

/* The backend should supply a minimum of n worker threads in its thread pool.
 *
 * If n == -1, the backend should supply as many workers as there are available
 * CPU cores/threads on the system.
 */
int aml_require_workers(struct aml*, int n);

/* Get/set the default main loop instance */
void aml_set_default(struct aml*);
struct aml* aml_get_default(void);

/* Check if there are pending events. The user should call aml_dispatch()
 * afterwards if there are any pending events.
 *
 * This function behaves like poll(): it will wait for either a timeout (in µs)
 * or a signal. Will block indefinitely if timeout is -1.
 *
 * Returns: -1 on timeout or signal; otherwise number of pending events.
 */
int aml_poll(struct aml*, int64_t timeout);

/* This is a convenience function that calls aml_poll() and aml_dispatch() in
 * a loop until aml_exit() is called.
 */
int aml_run(struct aml*);

/* Instruct the main loop to exit.
 */
void aml_exit(struct aml*);

/* Dispatch pending events */
void aml_dispatch(struct aml* self);

/* Trigger an immediate return from aml_poll().
 */
void aml_interrupt(struct aml*);

/* Increment the reference count by one.
 *
 * Returns how many references there were BEFORE the call.
 */
int aml_ref(void* obj);

/* Decrement the reference count by one.
 *
 * Returns how many references there are AFTER the call.
 */
int aml_unref(void* obj);

/* Create a new weak reference to the object.
 *
 * The reference object must be deleted using aml_weak_ref_del().
 */
struct aml_weak_ref* aml_weak_ref_new(void* obj);

/* Delete a weak reference created by aml_weak_ref_new().
 */
void aml_weak_ref_del(struct aml_weak_ref* self);

/* Try to get a new strong reference from a weak reference object.
 *
 * If the weak reference is still valid, the reference count on the returned
 * aml object will be increased by one. Otherwise NULL is returned.
 */
void* aml_weak_ref_read(struct aml_weak_ref* self);

/* The following calls create event handler objects.
 *
 * An object will have a reference count of 1 upon creation and must be freed
 * using aml_unref().
 */
struct aml_handler* aml_handler_new(int fd, aml_callback_fn, void* userdata,
                                    aml_free_fn);

struct aml_timer* aml_timer_new(uint64_t timeout, aml_callback_fn,
                                void* userdata, aml_free_fn);

struct aml_ticker* aml_ticker_new(uint64_t period, aml_callback_fn,
                                  void* userdata, aml_free_fn);

struct aml_signal* aml_signal_new(int signo, aml_callback_fn,
                                  void* userdata, aml_free_fn);

struct aml_work* aml_work_new(aml_callback_fn work_fn, aml_callback_fn done_fn,
                              void* userdata, aml_free_fn);

struct aml_idle* aml_idle_new(aml_callback_fn done_fn, void* userdata,
                              aml_free_fn);

/* Get the file descriptor associated with either a handler or the main loop.
 *
 * Calling this on objects of other types is illegal and may cause SIGABRT to
 * be raised.
 *
 * The fd returned from the main loop object can be used in other main loops to
 * monitor events on an aml main loop.
 */
int aml_get_fd(const void* obj);

/* Associate random data with an object.
 *
 * If a free function is defined, it will be called to free the assigned
 * userdata when the object is freed as a result of aml_unref().
 */
void aml_set_userdata(void* obj, void* userdata, aml_free_fn);
void* aml_get_userdata(const void* obj);

void aml_set_event_mask(struct aml_handler* obj, enum aml_event mask);
enum aml_event aml_get_event_mask(const struct aml_handler* obj);

/* Check which events are pending on an fd event handler.
 */
enum aml_event aml_get_revents(const struct aml_handler* obj);

/* Set timeout/period of a timer/ticker in µs
 *
 * Calling this on a started timer/ticker yields undefined behaviour
 */
void aml_set_duration(void* obj, uint64_t value);

/* Start an event handler.
 *
 * This increases the reference count on the handler object.
 *
 * Returns: 0 on success, -1 if the handler is already started.
 */
int aml_start(struct aml*, void* obj);

/* Stop an event handler.
 *
 * This decreases the reference count on a handler object.
 *
 * The callback or done function will not be run after this is called. However,
 * for aml_work, the work function may already be executing and it will be
 * allowed to complete.
 *
 * Returns: 0 on success, -1 if the handler is already stopped.
 */
int aml_stop(struct aml*, void* obj);

/* Check if an event handler is started.
 *
 * Returns: true if it has been started, false otherwise.
 */
bool aml_is_started(struct aml*, void* obj);

/* Get the signal assigned to a signal handler.
 */
int aml_get_signo(const struct aml_signal* sig);