iodine 0.6.5 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of iodine might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +11 -0
- data/README.md +4 -4
- data/SPEC-Websocket-Draft.md +3 -6
- data/bin/mustache.rb +128 -0
- data/examples/test_template.mustache +16 -0
- data/ext/iodine/fio.c +9397 -0
- data/ext/iodine/fio.h +4723 -0
- data/ext/iodine/fio_ary.h +353 -54
- data/ext/iodine/fio_cli.c +351 -361
- data/ext/iodine/fio_cli.h +84 -105
- data/ext/iodine/fio_hashmap.h +70 -16
- data/ext/iodine/fio_json_parser.h +35 -24
- data/ext/iodine/fio_siphash.c +104 -4
- data/ext/iodine/fio_siphash.h +18 -2
- data/ext/iodine/fio_str.h +1218 -0
- data/ext/iodine/fio_tmpfile.h +1 -1
- data/ext/iodine/fiobj.h +13 -8
- data/ext/iodine/fiobj4sock.h +6 -8
- data/ext/iodine/fiobj_ary.c +107 -17
- data/ext/iodine/fiobj_ary.h +36 -4
- data/ext/iodine/fiobj_data.c +146 -127
- data/ext/iodine/fiobj_data.h +25 -23
- data/ext/iodine/fiobj_hash.c +7 -7
- data/ext/iodine/fiobj_hash.h +6 -5
- data/ext/iodine/fiobj_json.c +20 -17
- data/ext/iodine/fiobj_json.h +5 -5
- data/ext/iodine/fiobj_mem.h +71 -0
- data/ext/iodine/fiobj_mustache.c +310 -0
- data/ext/iodine/fiobj_mustache.h +40 -0
- data/ext/iodine/fiobj_numbers.c +199 -94
- data/ext/iodine/fiobj_numbers.h +7 -7
- data/ext/iodine/fiobj_str.c +142 -333
- data/ext/iodine/fiobj_str.h +65 -55
- data/ext/iodine/fiobject.c +49 -11
- data/ext/iodine/fiobject.h +40 -39
- data/ext/iodine/http.c +382 -190
- data/ext/iodine/http.h +124 -80
- data/ext/iodine/http1.c +99 -127
- data/ext/iodine/http1.h +5 -5
- data/ext/iodine/http1_parser.c +3 -2
- data/ext/iodine/http1_parser.h +2 -2
- data/ext/iodine/http_internal.c +14 -12
- data/ext/iodine/http_internal.h +25 -19
- data/ext/iodine/iodine.c +37 -18
- data/ext/iodine/iodine.h +4 -0
- data/ext/iodine/iodine_caller.c +9 -2
- data/ext/iodine/iodine_caller.h +2 -0
- data/ext/iodine/iodine_connection.c +82 -117
- data/ext/iodine/iodine_defer.c +57 -50
- data/ext/iodine/iodine_defer.h +0 -1
- data/ext/iodine/iodine_fiobj2rb.h +4 -2
- data/ext/iodine/iodine_helpers.c +4 -4
- data/ext/iodine/iodine_http.c +25 -32
- data/ext/iodine/iodine_json.c +2 -1
- data/ext/iodine/iodine_mustache.c +423 -0
- data/ext/iodine/iodine_mustache.h +6 -0
- data/ext/iodine/iodine_pubsub.c +48 -153
- data/ext/iodine/iodine_pubsub.h +5 -4
- data/ext/iodine/iodine_rack_io.c +7 -5
- data/ext/iodine/iodine_store.c +16 -13
- data/ext/iodine/iodine_tcp.c +26 -34
- data/ext/iodine/mustache_parser.h +1085 -0
- data/ext/iodine/redis_engine.c +740 -646
- data/ext/iodine/redis_engine.h +13 -15
- data/ext/iodine/resp_parser.h +11 -5
- data/ext/iodine/websocket_parser.h +13 -13
- data/ext/iodine/websockets.c +240 -393
- data/ext/iodine/websockets.h +52 -113
- data/lib/iodine.rb +1 -1
- data/lib/iodine/mustache.rb +140 -0
- data/lib/iodine/version.rb +1 -1
- metadata +15 -28
- data/ext/iodine/defer.c +0 -566
- data/ext/iodine/defer.h +0 -148
- data/ext/iodine/evio.c +0 -26
- data/ext/iodine/evio.h +0 -161
- data/ext/iodine/evio_callbacks.c +0 -26
- data/ext/iodine/evio_epoll.c +0 -251
- data/ext/iodine/evio_kqueue.c +0 -194
- data/ext/iodine/facil.c +0 -2325
- data/ext/iodine/facil.h +0 -616
- data/ext/iodine/fio_base64.c +0 -277
- data/ext/iodine/fio_base64.h +0 -71
- data/ext/iodine/fio_llist.h +0 -257
- data/ext/iodine/fio_mem.c +0 -675
- data/ext/iodine/fio_mem.h +0 -143
- data/ext/iodine/fio_random.c +0 -248
- data/ext/iodine/fio_random.h +0 -45
- data/ext/iodine/fio_sha1.c +0 -362
- data/ext/iodine/fio_sha1.h +0 -107
- data/ext/iodine/fio_sha2.c +0 -842
- data/ext/iodine/fio_sha2.h +0 -169
- data/ext/iodine/pubsub.c +0 -867
- data/ext/iodine/pubsub.h +0 -221
- data/ext/iodine/sock.c +0 -1366
- data/ext/iodine/sock.h +0 -566
- data/ext/iodine/spnlock.inc +0 -111
data/ext/iodine/defer.h
DELETED
@@ -1,148 +0,0 @@
|
|
1
|
-
/*
|
2
|
-
Copyright: Boaz Segev, 2016-2017
|
3
|
-
License: MIT
|
4
|
-
|
5
|
-
Feel free to copy, use and enjoy according to the license provided.
|
6
|
-
*/
|
7
|
-
#ifndef H_DEFER_H
|
8
|
-
/**
|
9
|
-
A library for deferring execution of code.
|
10
|
-
|
11
|
-
Deferred execution can be multi-threaded, although threads aren't managed by the
|
12
|
-
library.
|
13
|
-
|
14
|
-
All deferred execution is shared among the same process and inherited by any
|
15
|
-
forked process.
|
16
|
-
|
17
|
-
The defer library could produce a single page "memory leak", since the last task
|
18
|
-
buffer is nenver freed (it's left "on call" for new events). To avoid this leak
|
19
|
-
call `defer_clear_queue` before exiting the program.
|
20
|
-
*/
|
21
|
-
#define H_DEFER_H
|
22
|
-
#define LIB_DEFER_VERSION_MAJOR 0
|
23
|
-
#define LIB_DEFER_VERSION_MINOR 1
|
24
|
-
#define LIB_DEFER_VERSION_PATCH 2
|
25
|
-
|
26
|
-
/* child process reaping is can be enabled as a default */
|
27
|
-
#ifndef NO_CHILD_REAPER
|
28
|
-
#define NO_CHILD_REAPER 0
|
29
|
-
#endif
|
30
|
-
|
31
|
-
#ifdef __cplusplus
|
32
|
-
extern "C" {
|
33
|
-
#endif
|
34
|
-
/* *****************************************************************************
|
35
|
-
Core API
|
36
|
-
***************************************************************************** */
|
37
|
-
|
38
|
-
/** Defer an execution of a function for later. Returns -1 on error.*/
|
39
|
-
int defer(void (*func)(void *, void *), void *arg1, void *arg2);
|
40
|
-
|
41
|
-
/** Performs all deferred functions until the queue had been depleted. */
|
42
|
-
void defer_perform(void);
|
43
|
-
|
44
|
-
/** returns true if there are deferred functions waiting for execution. */
|
45
|
-
int defer_has_queue(void);
|
46
|
-
|
47
|
-
/** Clears the queue without performing any of the tasks. */
|
48
|
-
void defer_clear_queue(void);
|
49
|
-
|
50
|
-
/* *****************************************************************************
|
51
|
-
Thread Pool support
|
52
|
-
***************************************************************************** */
|
53
|
-
|
54
|
-
/** an opaque thread pool type */
|
55
|
-
typedef struct defer_pool *pool_pt;
|
56
|
-
|
57
|
-
/**
|
58
|
-
* Starts a thread pool that will run deferred tasks in the background.
|
59
|
-
*
|
60
|
-
* The `defer_idle` callback will be used to handle waiting threads. It can be
|
61
|
-
* used to sleep, or run background tasks. It will run concurrently and
|
62
|
-
* continuesly for all the threads in the pool that are idling.
|
63
|
-
*
|
64
|
-
* If `defer_idle` is NULL, a fallback to `nanosleep` will be used.
|
65
|
-
*/
|
66
|
-
pool_pt defer_pool_start(unsigned int thread_count);
|
67
|
-
|
68
|
-
/** Signals a running thread pool to stop. Returns immediately. */
|
69
|
-
void defer_pool_stop(pool_pt pool);
|
70
|
-
|
71
|
-
/**
|
72
|
-
* Waits for a running thread pool, joining threads and finishing all tasks.
|
73
|
-
*
|
74
|
-
* This function MUST be called in order to free the pool's data (the
|
75
|
-
* `pool_pt`).
|
76
|
-
*/
|
77
|
-
void defer_pool_wait(pool_pt pool);
|
78
|
-
|
79
|
-
/** Returns TRUE (1) if the pool is hadn't been signaled to finish up. */
|
80
|
-
int defer_pool_is_active(pool_pt pool);
|
81
|
-
|
82
|
-
/**
|
83
|
-
* OVERRIDE THIS to replace the default pthread implementation.
|
84
|
-
*
|
85
|
-
* Accepts a pointer to a function and a single argument that should be executed
|
86
|
-
* within a new thread.
|
87
|
-
*
|
88
|
-
* The function should allocate memory for the thread object and return a
|
89
|
-
* pointer to the allocated memory that identifies the thread.
|
90
|
-
*
|
91
|
-
* On error NULL should be returned.
|
92
|
-
*/
|
93
|
-
void *defer_new_thread(void *(*thread_func)(void *), void *arg);
|
94
|
-
|
95
|
-
/**
|
96
|
-
* OVERRIDE THIS to replace the default pthread implementation.
|
97
|
-
*
|
98
|
-
* Frees the memory asociated with a thread indentifier (allows the thread to
|
99
|
-
* run it's course, just the identifier is freed).
|
100
|
-
*/
|
101
|
-
void defer_free_thread(void *p_thr);
|
102
|
-
|
103
|
-
/**
|
104
|
-
* OVERRIDE THIS to replace the default pthread implementation.
|
105
|
-
*
|
106
|
-
* Accepts a pointer returned from `defer_new_thread` (should also free any
|
107
|
-
* allocated memory) and joins the associated thread.
|
108
|
-
*
|
109
|
-
* Return value is ignored.
|
110
|
-
*/
|
111
|
-
int defer_join_thread(void *p_thr);
|
112
|
-
|
113
|
-
/**
|
114
|
-
* OVERRIDE THIS to replace the default pthread implementation.
|
115
|
-
*
|
116
|
-
* Throttles or reschedules the current running thread. Default implementation
|
117
|
-
* simply micro-sleeps.
|
118
|
-
*/
|
119
|
-
void defer_thread_throttle(unsigned long microsec);
|
120
|
-
|
121
|
-
/**
|
122
|
-
* OVERRIDE THIS to replace the default nanosleep implementation.
|
123
|
-
*
|
124
|
-
* A thread entering this function should wait for new evennts.
|
125
|
-
*/
|
126
|
-
void defer_thread_wait(pool_pt pool, void *p_thr);
|
127
|
-
|
128
|
-
/**
|
129
|
-
* OVERRIDE THIS to replace the default implementation (which does nothing).
|
130
|
-
*
|
131
|
-
* This should signal a single waiting thread to wake up (a new task entered the
|
132
|
-
* queue).
|
133
|
-
*/
|
134
|
-
void defer_thread_signal(void);
|
135
|
-
|
136
|
-
/** Call this function after forking, to make sure no locks are engaged. */
|
137
|
-
void defer_on_fork(void);
|
138
|
-
|
139
|
-
#ifdef DEBUG
|
140
|
-
/** minor testing facilities */
|
141
|
-
void defer_test(void);
|
142
|
-
#endif
|
143
|
-
|
144
|
-
#ifdef __cplusplus
|
145
|
-
} /* closing brace for extern "C" */
|
146
|
-
#endif
|
147
|
-
|
148
|
-
#endif
|
data/ext/iodine/evio.c
DELETED
@@ -1,26 +0,0 @@
|
|
1
|
-
/*
|
2
|
-
Copyright: Boaz Segev, 2016-2017
|
3
|
-
License: MIT
|
4
|
-
|
5
|
-
Feel free to copy, use and enjoy according to the license provided.
|
6
|
-
*/
|
7
|
-
#ifndef _GNU_SOURCE
|
8
|
-
#define _GNU_SOURCE
|
9
|
-
#endif
|
10
|
-
|
11
|
-
#include "evio.h"
|
12
|
-
|
13
|
-
#include <stdio.h>
|
14
|
-
#include <stdlib.h>
|
15
|
-
|
16
|
-
/* *****************************************************************************
|
17
|
-
Callbacks - weak versions to be overridden.
|
18
|
-
***************************************************************************** */
|
19
|
-
#pragma weak evio_on_data
|
20
|
-
void __attribute__((weak)) evio_on_data(void *arg) { (void)arg; }
|
21
|
-
#pragma weak evio_on_ready
|
22
|
-
void __attribute__((weak)) evio_on_ready(void *arg) { (void)arg; }
|
23
|
-
#pragma weak evio_on_error
|
24
|
-
void __attribute__((weak)) evio_on_error(void *arg) { (void)arg; }
|
25
|
-
#pragma weak evio_on_close
|
26
|
-
void __attribute__((weak)) evio_on_close(void *arg) { (void)arg; }
|
data/ext/iodine/evio.h
DELETED
@@ -1,161 +0,0 @@
|
|
1
|
-
/*
|
2
|
-
Copyright: Boaz Segev, 2016-2017
|
3
|
-
License: MIT
|
4
|
-
|
5
|
-
Feel free to copy, use and enjoy according to the license provided.
|
6
|
-
*/
|
7
|
-
#ifndef H_FACIL_EVIO_H
|
8
|
-
#include <stdint.h>
|
9
|
-
#include <stdlib.h>
|
10
|
-
|
11
|
-
/**
|
12
|
-
This is an `epoll` / `kqueue` ONE-SHOT polling wrapper, allowing for portability
|
13
|
-
between BSD and Linux polling machanisms and routing events to hard-coded
|
14
|
-
callbacks (weak function symbols).
|
15
|
-
|
16
|
-
The callbacks supported by thils library:
|
17
|
-
|
18
|
-
* `evio_on_data(intptr_t)` called when data is available or on timer.
|
19
|
-
* `evio_on_ready(intptr_t)` called when writing is possible.
|
20
|
-
* `evio_on_error(intptr_t)` called when an error occured.
|
21
|
-
* `evio_on_close(intptr_t)` called when the connection was remotely closed.
|
22
|
-
|
23
|
-
*/
|
24
|
-
#define H_FACIL_EVIO_H
|
25
|
-
#define LIB_EVIO_VERSION_MAJOR 0
|
26
|
-
#define LIB_EVIO_VERSION_MINOR 2
|
27
|
-
#define LIB_EVIO_VERSION_PATCH 0
|
28
|
-
|
29
|
-
#if defined(__linux__)
|
30
|
-
#define EVIO_ENGINE_EPOLL 1
|
31
|
-
#elif defined(__APPLE__) || defined(__unix__)
|
32
|
-
#define EVIO_ENGINE_KQUEUE 1
|
33
|
-
#else
|
34
|
-
#error This library currently supports only Unix based systems with kqueue or epoll (i.e. Linux and BSD)
|
35
|
-
#endif
|
36
|
-
|
37
|
-
#ifdef __cplusplus
|
38
|
-
extern "C" {
|
39
|
-
#endif
|
40
|
-
|
41
|
-
#ifndef EVIO_MAX_EVENTS
|
42
|
-
#define EVIO_MAX_EVENTS 64
|
43
|
-
#endif
|
44
|
-
#ifndef EVIO_TICK
|
45
|
-
#define EVIO_TICK 512 /** in milliseconsd */
|
46
|
-
#endif
|
47
|
-
|
48
|
-
#if (EVIO_MAX_EVENTS & 1)
|
49
|
-
#error EVIO_MAX_EVENTS must be an EVEN number.
|
50
|
-
#endif
|
51
|
-
#if EVIO_MAX_EVENTS <= 3
|
52
|
-
#error EVIO_MAX_EVENTS must be an GREATER than 4.
|
53
|
-
#endif
|
54
|
-
|
55
|
-
/**
|
56
|
-
Creates the `epoll` or `kqueue` object.
|
57
|
-
|
58
|
-
It's impossible to add or remove file descriptors from the polling system before
|
59
|
-
calling this method.
|
60
|
-
|
61
|
-
Returns -1 on error, otherwise returns a unique value representing the `epoll`
|
62
|
-
or `kqueue` object. The returned value can be safely ignored.
|
63
|
-
|
64
|
-
NOTE: Once an `epoll` / `kqueue` object was opened, `fork` should be avoided,
|
65
|
-
since ALL the events will be shared among the forked processes (while not ALL
|
66
|
-
the file descriptors are expected to be shared).
|
67
|
-
*/
|
68
|
-
intptr_t evio_create(void);
|
69
|
-
|
70
|
-
/**
|
71
|
-
Reviews any pending events (up to EVIO_MAX_EVENTS) and calls any callbacks.
|
72
|
-
|
73
|
-
Waits up to `timeout_millisec` for events to occur.
|
74
|
-
|
75
|
-
Returns -1 on error, otherwise returns the number of events handled.
|
76
|
-
*/
|
77
|
-
int evio_review(const int timeout_millisec);
|
78
|
-
|
79
|
-
/** Waits up to `timeout_millisec` for events. Events aren't reviewed. */
|
80
|
-
int evio_wait(const int timeout_millisec);
|
81
|
-
|
82
|
-
/**
|
83
|
-
Closes the `epoll` / `kqueue` object, releasing it's resources (important if
|
84
|
-
forking!).
|
85
|
-
*/
|
86
|
-
void evio_close(void);
|
87
|
-
|
88
|
-
/**
|
89
|
-
returns true if the evio is available for adding or removing file descriptors.
|
90
|
-
*/
|
91
|
-
int evio_isactive(void);
|
92
|
-
|
93
|
-
/* *****************************************************************************
|
94
|
-
Adding and removing normal file descriptors (ONE SHOT).
|
95
|
-
*/
|
96
|
-
|
97
|
-
/**
|
98
|
-
Adds a file descriptor to the polling object (ONE SHOT), both for read / write
|
99
|
-
readiness.
|
100
|
-
|
101
|
-
Returns -1 on error, otherwise return value is system dependent and can be
|
102
|
-
safely ignored.
|
103
|
-
*/
|
104
|
-
int evio_add(int fd, void *callback_arg);
|
105
|
-
|
106
|
-
/**
|
107
|
-
Adds a file descriptor to the polling object (ONE SHOT), to be polled for
|
108
|
-
incoming data (`evio_on_data` wil be called).
|
109
|
-
|
110
|
-
Returns -1 on error, otherwise return value is system dependent and can be
|
111
|
-
safely ignored.
|
112
|
-
*/
|
113
|
-
int evio_add_read(int fd, void *callback_arg);
|
114
|
-
|
115
|
-
/**
|
116
|
-
Adds a file descriptor to the polling object (ONE SHOT), to be polled for
|
117
|
-
outgoing buffer readiness data (`evio_on_ready` wil be called).
|
118
|
-
|
119
|
-
Returns -1 on error, otherwise return value is system dependent and can be
|
120
|
-
safely ignored.
|
121
|
-
*/
|
122
|
-
int evio_add_write(int fd, void *callback_arg);
|
123
|
-
|
124
|
-
/**
|
125
|
-
Removes a file descriptor from the polling object.
|
126
|
-
*/
|
127
|
-
void evio_remove(int fd);
|
128
|
-
|
129
|
-
/* *****************************************************************************
|
130
|
-
Timers.
|
131
|
-
*/
|
132
|
-
|
133
|
-
/**
|
134
|
-
Creates a timer file descriptor, system dependent.
|
135
|
-
|
136
|
-
Returns -1 on error, or a valid fd on success.
|
137
|
-
|
138
|
-
NOTE: Systems have a limit on the number of timers that can be opened.
|
139
|
-
*/
|
140
|
-
int evio_open_timer(void);
|
141
|
-
|
142
|
-
/**
|
143
|
-
Adds a timer file descriptor, so that callbacks will be called for it's events.
|
144
|
-
|
145
|
-
Returns -1 on error, otherwise return value is system dependent.
|
146
|
-
*/
|
147
|
-
int evio_set_timer(int fd, void *callback_arg, unsigned long milliseconds);
|
148
|
-
|
149
|
-
/* *****************************************************************************
|
150
|
-
Callbacks - override these.
|
151
|
-
*/
|
152
|
-
void evio_on_data(void *);
|
153
|
-
void evio_on_ready(void *);
|
154
|
-
void evio_on_error(void *);
|
155
|
-
void evio_on_close(void *);
|
156
|
-
|
157
|
-
#ifdef __cplusplus
|
158
|
-
} /* extern "C" */
|
159
|
-
#endif
|
160
|
-
|
161
|
-
#endif /* H_FACIL_EVIO_H */
|
data/ext/iodine/evio_callbacks.c
DELETED
@@ -1,26 +0,0 @@
|
|
1
|
-
/*
|
2
|
-
Copyright: Boaz Segev, 2016-2017
|
3
|
-
License: MIT
|
4
|
-
|
5
|
-
Feel free to copy, use and enjoy according to the license provided.
|
6
|
-
*/
|
7
|
-
#ifndef _GNU_SOURCE
|
8
|
-
#define _GNU_SOURCE
|
9
|
-
#endif
|
10
|
-
|
11
|
-
#include "evio.h"
|
12
|
-
|
13
|
-
#include <stdio.h>
|
14
|
-
#include <stdlib.h>
|
15
|
-
|
16
|
-
/* *****************************************************************************
|
17
|
-
Callbacks - weak versions to be overridden.
|
18
|
-
***************************************************************************** */
|
19
|
-
#pragma weak evio_on_data
|
20
|
-
void __attribute__((weak)) evio_on_data(void *arg) { (void)arg; }
|
21
|
-
#pragma weak evio_on_ready
|
22
|
-
void __attribute__((weak)) evio_on_ready(void *arg) { (void)arg; }
|
23
|
-
#pragma weak evio_on_error
|
24
|
-
void __attribute__((weak)) evio_on_error(void *arg) { (void)arg; }
|
25
|
-
#pragma weak evio_on_close
|
26
|
-
void __attribute__((weak)) evio_on_close(void *arg) { (void)arg; }
|
data/ext/iodine/evio_epoll.c
DELETED
@@ -1,251 +0,0 @@
|
|
1
|
-
/*
|
2
|
-
Copyright: Boaz Segev, 2016-2017
|
3
|
-
License: MIT
|
4
|
-
|
5
|
-
Feel free to copy, use and enjoy according to the license provided.
|
6
|
-
*/
|
7
|
-
#ifndef _GNU_SOURCE
|
8
|
-
#define _GNU_SOURCE
|
9
|
-
#endif
|
10
|
-
|
11
|
-
#include "evio.h"
|
12
|
-
|
13
|
-
#ifdef EVIO_ENGINE_EPOLL
|
14
|
-
|
15
|
-
#include <assert.h>
|
16
|
-
#include <errno.h>
|
17
|
-
#include <fcntl.h>
|
18
|
-
#include <netdb.h>
|
19
|
-
#include <stdint.h>
|
20
|
-
#include <stdio.h>
|
21
|
-
#include <stdlib.h>
|
22
|
-
#include <string.h>
|
23
|
-
#include <sys/socket.h>
|
24
|
-
#include <sys/time.h>
|
25
|
-
#include <sys/types.h>
|
26
|
-
#include <time.h>
|
27
|
-
#include <unistd.h>
|
28
|
-
|
29
|
-
/* *****************************************************************************
|
30
|
-
Global data and system independant code
|
31
|
-
***************************************************************************** */
|
32
|
-
|
33
|
-
/* epoll tester, in and out */
|
34
|
-
static int evio_fd[3] = {-1, -1, -1};
|
35
|
-
|
36
|
-
/** Closes the `epoll` / `kqueue` object, releasing it's resources. */
|
37
|
-
void evio_close() {
|
38
|
-
for (int i = 0; i < 3; ++i) {
|
39
|
-
if (evio_fd[i] != -1) {
|
40
|
-
close(evio_fd[i]);
|
41
|
-
evio_fd[i] = -1;
|
42
|
-
}
|
43
|
-
}
|
44
|
-
}
|
45
|
-
|
46
|
-
/**
|
47
|
-
returns true if the evio is available for adding or removing file descriptors.
|
48
|
-
*/
|
49
|
-
int evio_isactive(void) { return evio_fd[0] >= 0; }
|
50
|
-
|
51
|
-
/* *****************************************************************************
|
52
|
-
Linux `epoll` implementation
|
53
|
-
***************************************************************************** */
|
54
|
-
#include <sys/epoll.h>
|
55
|
-
#include <sys/timerfd.h>
|
56
|
-
|
57
|
-
/**
|
58
|
-
Creates the `epoll` or `kqueue` object.
|
59
|
-
*/
|
60
|
-
intptr_t evio_create() {
|
61
|
-
evio_close();
|
62
|
-
for (int i = 0; i < 3; ++i) {
|
63
|
-
evio_fd[i] = epoll_create1(EPOLL_CLOEXEC);
|
64
|
-
if (evio_fd[i] == -1)
|
65
|
-
goto error;
|
66
|
-
}
|
67
|
-
for (int i = 1; i < 3; ++i) {
|
68
|
-
struct epoll_event chevent = {
|
69
|
-
.events = (EPOLLOUT | EPOLLIN), .data.fd = evio_fd[i],
|
70
|
-
};
|
71
|
-
if (epoll_ctl(evio_fd[0], EPOLL_CTL_ADD, evio_fd[i], &chevent) == -1)
|
72
|
-
goto error;
|
73
|
-
}
|
74
|
-
return 0;
|
75
|
-
error:
|
76
|
-
#if DEBUB
|
77
|
-
perror("ERROR: (evoid) failed to initialize");
|
78
|
-
#endif
|
79
|
-
evio_close();
|
80
|
-
return -1;
|
81
|
-
}
|
82
|
-
|
83
|
-
/**
|
84
|
-
Removes a file descriptor from the polling object.
|
85
|
-
*/
|
86
|
-
void evio_remove(int fd) {
|
87
|
-
if (evio_fd[0] < 0)
|
88
|
-
return;
|
89
|
-
struct epoll_event chevent = {.events = (EPOLLOUT | EPOLLIN), .data.fd = fd};
|
90
|
-
epoll_ctl(evio_fd[1], EPOLL_CTL_DEL, fd, &chevent);
|
91
|
-
epoll_ctl(evio_fd[2], EPOLL_CTL_DEL, fd, &chevent);
|
92
|
-
}
|
93
|
-
|
94
|
-
static inline int evio_add2(int fd, void *callback_arg, uint32_t events,
|
95
|
-
int ep_fd) {
|
96
|
-
struct epoll_event chevent;
|
97
|
-
errno = 0;
|
98
|
-
chevent = (struct epoll_event){
|
99
|
-
.events = events, .data.ptr = (void *)callback_arg,
|
100
|
-
};
|
101
|
-
int ret = epoll_ctl(ep_fd, EPOLL_CTL_MOD, fd, &chevent);
|
102
|
-
if (ret == -1 && errno == ENOENT) {
|
103
|
-
errno = 0;
|
104
|
-
chevent = (struct epoll_event){
|
105
|
-
.events = events, .data.ptr = (void *)callback_arg,
|
106
|
-
};
|
107
|
-
ret = epoll_ctl(ep_fd, EPOLL_CTL_ADD, fd, &chevent);
|
108
|
-
}
|
109
|
-
return ret;
|
110
|
-
}
|
111
|
-
|
112
|
-
/**
|
113
|
-
Adds a file descriptor to the polling object.
|
114
|
-
*/
|
115
|
-
int evio_add(int fd, void *callback_arg) {
|
116
|
-
if (evio_add2(fd, callback_arg,
|
117
|
-
(EPOLLIN | EPOLLRDHUP | EPOLLHUP | EPOLLONESHOT),
|
118
|
-
evio_fd[1]) == -1)
|
119
|
-
return -1;
|
120
|
-
if (evio_add2(fd, callback_arg,
|
121
|
-
(EPOLLOUT | EPOLLRDHUP | EPOLLHUP | EPOLLONESHOT),
|
122
|
-
evio_fd[2]) == -1)
|
123
|
-
return -1;
|
124
|
-
return 0;
|
125
|
-
}
|
126
|
-
|
127
|
-
/**
|
128
|
-
Adds a file descriptor to the polling object (ONE SHOT), to be polled for
|
129
|
-
incoming data (`evio_on_data` wil be called).
|
130
|
-
*/
|
131
|
-
int evio_add_read(int fd, void *callback_arg) {
|
132
|
-
return evio_add2(fd, callback_arg,
|
133
|
-
(EPOLLIN | EPOLLRDHUP | EPOLLHUP | EPOLLONESHOT),
|
134
|
-
evio_fd[1]);
|
135
|
-
}
|
136
|
-
|
137
|
-
/**
|
138
|
-
Adds a file descriptor to the polling object (ONE SHOT), to be polled for
|
139
|
-
outgoing buffer readiness data (`evio_on_ready` wil be called).
|
140
|
-
*/
|
141
|
-
int evio_add_write(int fd, void *callback_arg) {
|
142
|
-
return evio_add2(fd, callback_arg,
|
143
|
-
(EPOLLOUT | EPOLLRDHUP | EPOLLHUP | EPOLLONESHOT),
|
144
|
-
evio_fd[2]);
|
145
|
-
}
|
146
|
-
|
147
|
-
/**
|
148
|
-
Creates a timer file descriptor, system dependent.
|
149
|
-
*/
|
150
|
-
int evio_open_timer(void) {
|
151
|
-
#ifndef TFD_NONBLOCK
|
152
|
-
int fd = timerfd_create(CLOCK_MONOTONIC, O_NONBLOCK);
|
153
|
-
if (fd != -1) { /* make sure it's a non-blocking timer. */
|
154
|
-
#if defined(O_NONBLOCK)
|
155
|
-
/* Fixme: O_NONBLOCK is defined but broken on SunOS 4.1.x and AIX 3.2.5. */
|
156
|
-
int flags;
|
157
|
-
if (-1 == (flags = fcntl(fd, F_GETFL, 0)))
|
158
|
-
flags = 0;
|
159
|
-
if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1)
|
160
|
-
goto error;
|
161
|
-
#else
|
162
|
-
/* no O_NONBLOCK, use the old way of doing it */
|
163
|
-
static int flags = 1;
|
164
|
-
if (ioctl(fd, FIOBIO, &flags) == -1)
|
165
|
-
goto error;
|
166
|
-
#endif
|
167
|
-
}
|
168
|
-
return fd;
|
169
|
-
error:
|
170
|
-
close(fd);
|
171
|
-
return -1;
|
172
|
-
#else
|
173
|
-
return timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK);
|
174
|
-
#endif
|
175
|
-
}
|
176
|
-
|
177
|
-
/**
|
178
|
-
Adds a timer file descriptor, so that callbacks will be called for it's events.
|
179
|
-
*/
|
180
|
-
int evio_set_timer(int fd, void *callback_arg, unsigned long milliseconds) {
|
181
|
-
|
182
|
-
if (evio_fd[0] < 0)
|
183
|
-
return -1;
|
184
|
-
/* clear out existing timer marker, if exists. */
|
185
|
-
char data[8]; // void * is 8 byte long
|
186
|
-
if (read(fd, &data, 8) < 0)
|
187
|
-
data[0] = 0;
|
188
|
-
/* set file's time value */
|
189
|
-
struct itimerspec new_t_data;
|
190
|
-
new_t_data.it_value.tv_sec = new_t_data.it_interval.tv_sec =
|
191
|
-
milliseconds / 1000;
|
192
|
-
new_t_data.it_value.tv_nsec = new_t_data.it_interval.tv_nsec =
|
193
|
-
(milliseconds % 1000) * 1000000;
|
194
|
-
if (timerfd_settime(fd, 0, &new_t_data, NULL) == -1)
|
195
|
-
return -1;
|
196
|
-
/* add to epoll */
|
197
|
-
return evio_add2(fd, callback_arg, (EPOLLIN | EPOLLONESHOT), evio_fd[1]);
|
198
|
-
}
|
199
|
-
|
200
|
-
/**
|
201
|
-
Reviews any pending events (up to EVIO_MAX_EVENTS) and calls any callbacks.
|
202
|
-
*/
|
203
|
-
int evio_review(const int timeout_millisec) {
|
204
|
-
if (evio_fd[0] < 0)
|
205
|
-
return -1;
|
206
|
-
struct epoll_event internal[2];
|
207
|
-
struct epoll_event events[EVIO_MAX_EVENTS];
|
208
|
-
int total = 0;
|
209
|
-
/* wait for events and handle them */
|
210
|
-
int internal_count = epoll_wait(evio_fd[0], internal, 2, timeout_millisec);
|
211
|
-
if (internal_count == -1)
|
212
|
-
return -1;
|
213
|
-
if (internal_count == 0)
|
214
|
-
return 0;
|
215
|
-
for (int j = 0; j < internal_count; ++j) {
|
216
|
-
int active_count =
|
217
|
-
epoll_wait(internal[j].data.fd, events, EVIO_MAX_EVENTS, 0);
|
218
|
-
if (active_count > 0) {
|
219
|
-
for (int i = 0; i < active_count; i++) {
|
220
|
-
if (events[i].events & (~(EPOLLIN | EPOLLOUT))) {
|
221
|
-
// errors are hendled as disconnections (on_close)
|
222
|
-
evio_on_error(events[i].data.ptr);
|
223
|
-
} else {
|
224
|
-
// no error, then it's an active event(s)
|
225
|
-
if (events[i].events & EPOLLOUT) {
|
226
|
-
evio_on_ready(events[i].data.ptr);
|
227
|
-
}
|
228
|
-
if (events[i].events & EPOLLIN)
|
229
|
-
evio_on_data(events[i].data.ptr);
|
230
|
-
}
|
231
|
-
} // end for loop
|
232
|
-
total += active_count;
|
233
|
-
}
|
234
|
-
}
|
235
|
-
|
236
|
-
return total;
|
237
|
-
}
|
238
|
-
|
239
|
-
#include <poll.h>
|
240
|
-
|
241
|
-
/** Waits up to `timeout_millisec` for events. No events are signaled. */
|
242
|
-
int evio_wait(const int timeout_millisec) {
|
243
|
-
if (evio_fd[0] < 0)
|
244
|
-
return -1;
|
245
|
-
struct pollfd pollfd = {
|
246
|
-
.fd = evio_fd[0], .events = POLLIN,
|
247
|
-
};
|
248
|
-
return poll(&pollfd, 1, timeout_millisec);
|
249
|
-
}
|
250
|
-
|
251
|
-
#endif /* system dependent code */
|