Skip to content

Commit 3acfd1d

Browse files
committed
feat(sys): reimplement ngx_event_t macros and inline methods
Bindgen does not support functional macros or inline functions, so we have to maintain a copy of the implementation for any such item we need to use.
1 parent b7b6e32 commit 3acfd1d

File tree

3 files changed

+88
-17
lines changed

3 files changed

+88
-17
lines changed

examples/async.rs

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use ngx::core;
88
use ngx::ffi::{
99
ngx_array_push, ngx_command_t, ngx_conf_t, ngx_cycle, ngx_event_t, ngx_http_core_module, ngx_http_core_run_phases,
1010
ngx_http_handler_pt, ngx_http_module_t, ngx_http_phases_NGX_HTTP_ACCESS_PHASE, ngx_http_request_t, ngx_int_t,
11-
ngx_module_t, ngx_posted_events, ngx_queue_s, ngx_str_t, ngx_uint_t, NGX_CONF_TAKE1, NGX_HTTP_LOC_CONF,
11+
ngx_module_t, ngx_post_event, ngx_posted_events, ngx_str_t, ngx_uint_t, NGX_CONF_TAKE1, NGX_HTTP_LOC_CONF,
1212
NGX_HTTP_LOC_CONF_OFFSET, NGX_HTTP_MODULE,
1313
};
1414
use ngx::http::{self, HTTPModule, MergeConfigError};
@@ -112,7 +112,7 @@ unsafe extern "C" fn check_async_work_done(event: *mut ngx_event_t) {
112112
// this doesn't have have good performance but works as a simple thread-safe example and doesn't causes
113113
// segfault. The best method that provides both thread-safety and performance requires
114114
// an nginx patch.
115-
post_event(event, addr_of_mut!(ngx_posted_events));
115+
ngx_post_event(event, addr_of_mut!(ngx_posted_events));
116116
}
117117
}
118118

@@ -128,20 +128,6 @@ struct EventData {
128128
unsafe impl Send for EventData {}
129129
unsafe impl Sync for EventData {}
130130

131-
// same as ngx_post_event
132-
// source: https://github.com/nginx/ngx-rust/pull/31/files#diff-132330bb775bed17fb9990ec2b56e6c52e6a9e56d62f2114fade95e4decdba08R80-R90
133-
unsafe fn post_event(event: *mut ngx_event_t, queue: *mut ngx_queue_s) {
134-
let event = &mut (*event);
135-
if event.posted() == 0 {
136-
event.set_posted(1);
137-
// translated from ngx_queue_insert_tail macro
138-
event.queue.prev = (*queue).prev;
139-
(*event.queue.prev).next = &event.queue as *const _ as *mut _;
140-
event.queue.next = queue;
141-
(*queue).prev = &event.queue as *const _ as *mut _;
142-
}
143-
}
144-
145131
http_request_handler!(async_access_handler, |request: &mut http::Request| {
146132
let co = unsafe { request.get_module_loc_conf::<ModuleConfig>(&*addr_of!(ngx_http_async_module)) };
147133
let co = co.expect("module config is none");
@@ -184,7 +170,7 @@ http_request_handler!(async_access_handler, |request: &mut http::Request| {
184170
event.data = Arc::into_raw(event_data.clone()) as _;
185171
event.log = (*ngx_cycle).log;
186172

187-
post_event(event, addr_of_mut!(ngx_posted_events));
173+
ngx_post_event(event, addr_of_mut!(ngx_posted_events));
188174
}
189175

190176
ngx_log_debug_http!(request, "async module enabled: {}", co.enable);

nginx-sys/src/event.rs

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
use core::ptr;
2+
3+
use crate::{
4+
ngx_current_msec, ngx_event_t, ngx_event_timer_rbtree, ngx_msec_t, ngx_queue_insert_before, ngx_queue_remove,
5+
ngx_queue_t, ngx_rbtree_delete, ngx_rbtree_insert, NGX_TIMER_LAZY_DELAY,
6+
};
7+
8+
/// Sets a timeout for an event.
9+
///
10+
/// # Safety
11+
///
12+
///`ev` must be a valid pointer to an `ngx_event_t`.
13+
#[inline]
14+
pub unsafe fn ngx_add_timer(ev: *mut ngx_event_t, timer: ngx_msec_t) {
15+
let key: ngx_msec_t = ngx_current_msec.wrapping_add(timer);
16+
17+
if (*ev).timer_set() != 0 {
18+
/*
19+
* Use a previous timer value if difference between it and a new
20+
* value is less than NGX_TIMER_LAZY_DELAY milliseconds: this allows
21+
* to minimize the rbtree operations for fast connections.
22+
*/
23+
if key.abs_diff((*ev).timer.key) < NGX_TIMER_LAZY_DELAY as _ {
24+
return;
25+
}
26+
27+
ngx_del_timer(ev);
28+
}
29+
30+
(*ev).timer.key = key;
31+
32+
ngx_rbtree_insert(
33+
ptr::addr_of_mut!(ngx_event_timer_rbtree),
34+
ptr::addr_of_mut!((*ev).timer),
35+
);
36+
37+
(*ev).set_timer_set(1);
38+
}
39+
40+
/// Deletes a previously set timeout.
41+
///
42+
/// # Safety
43+
///
44+
/// `ev` must be a valid pointer to an `ngx_event_t`, previously armed with [ngx_add_timer].
45+
#[inline]
46+
pub unsafe fn ngx_del_timer(ev: *mut ngx_event_t) {
47+
ngx_rbtree_delete(
48+
ptr::addr_of_mut!(ngx_event_timer_rbtree),
49+
ptr::addr_of_mut!((*ev).timer),
50+
);
51+
52+
(*ev).timer.left = ptr::null_mut();
53+
(*ev).timer.right = ptr::null_mut();
54+
(*ev).timer.parent = ptr::null_mut();
55+
56+
(*ev).set_timer_set(0);
57+
}
58+
59+
/// Post the event `ev` to the post queue `q`.
60+
///
61+
/// # Safety
62+
///
63+
/// `ev` must be a valid pointer to an `ngx_event_t`.
64+
/// `q` is a valid pointer to a queue head.
65+
#[inline]
66+
pub unsafe fn ngx_post_event(ev: *mut ngx_event_t, q: *mut ngx_queue_t) {
67+
if (*ev).posted() == 0 {
68+
(*ev).set_posted(1);
69+
ngx_queue_insert_before(q, ptr::addr_of_mut!((*ev).queue));
70+
}
71+
}
72+
73+
/// Deletes the event `ev` from the queue it's currently posted in.
74+
///
75+
/// # Safety
76+
///
77+
/// `ev` must be a valid pointer to an `ngx_event_t`.
78+
/// `ev.queue` is initialized with `ngx_queue_init`.
79+
#[inline]
80+
pub unsafe fn ngx_delete_posted_event(ev: *mut ngx_event_t) {
81+
(*ev).set_posted(0);
82+
ngx_queue_remove(ptr::addr_of_mut!((*ev).queue));
83+
}

nginx-sys/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#![warn(missing_docs)]
33
#![no_std]
44

5+
mod event;
56
mod queue;
67

78
use core::fmt;
@@ -24,6 +25,7 @@ mod bindings {
2425
#[doc(no_inline)]
2526
pub use bindings::*;
2627

28+
pub use event::*;
2729
pub use queue::*;
2830

2931
/// The offset of the `main_conf` field in the `ngx_http_conf_ctx_t` struct.

0 commit comments

Comments
 (0)