Skip to content

Commit

Permalink
improved example
Browse files Browse the repository at this point in the history
  • Loading branch information
Filippo Brizzi committed Jan 23, 2024
1 parent b683136 commit ec33a29
Show file tree
Hide file tree
Showing 2 changed files with 89 additions and 2 deletions.
5 changes: 3 additions & 2 deletions examples/z_pub.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ int main(int argc, char **argv) {
if (argc > 3) add_matching_listener = atoi(argv[3]);

z_owned_config_t config = z_config_default();
if (argc > 3) {
if (argc > 4) {
if (zc_config_insert_json(z_loan(config), Z_CONFIG_CONNECT_KEY, argv[3]) < 0) {
printf(
"Couldn't insert value `%s` in configuration at `%s`. This is likely because `%s` expects a "
Expand All @@ -64,9 +64,10 @@ int main(int argc, char **argv) {
exit(-1);
}

z_owned_matching_listener_t listener;
if (add_matching_listener) {
z_owned_closure_matching_status_t callback = z_closure(matching_status_handler);
z_publisher_matching_listener_callback(z_loan(pub), z_move(callback));
listener = z_publisher_matching_listener_callback(z_loan(pub), z_move(callback));
}

char buf[256];
Expand Down
86 changes: 86 additions & 0 deletions src/closures/matching_status_closure.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
use libc::c_void;

use crate::z_matching_status_t;
/// A closure is a structure that contains all the elements for stateful, memory-leak-free callbacks:
///
/// Members:
/// void *context: a pointer to an arbitrary state.
/// void *call(const struct z_owned_reply_t*, const void *context): the typical callback function. `context` will be passed as its last argument.
/// void *drop(void*): allows the callback's state to be freed.
///
/// Closures are not guaranteed not to be called concurrently.
///
/// It is guaranteed that:
///
/// - `call` will never be called once `drop` has started.
/// - `drop` will only be called **once**, and **after every** `call` has ended.
/// - The two previous guarantees imply that `call` and `drop` are never called concurrently.
#[repr(C)]
pub struct z_owned_closure_matching_status_t {
context: *mut c_void,
call: Option<extern "C" fn(&z_matching_status_t, *mut c_void)>,
drop: Option<extern "C" fn(*mut c_void)>,
}

impl z_owned_closure_matching_status_t {
pub fn empty() -> Self {
z_owned_closure_matching_status_t {
context: std::ptr::null_mut(),
call: None,
drop: None,
}
}
}
unsafe impl Send for z_owned_closure_matching_status_t {}
unsafe impl Sync for z_owned_closure_matching_status_t {}
impl Drop for z_owned_closure_matching_status_t {
fn drop(&mut self) {
if let Some(drop) = self.drop {
drop(self.context)
}
}
}
/// Constructs a null safe-to-drop value of 'z_owned_closure_matching_status_t' type
#[no_mangle]
pub extern "C" fn z_closure_matching_status_null() -> z_owned_closure_matching_status_t {
z_owned_closure_matching_status_t::empty()
}
/// Calls the closure. Calling an uninitialized closure is a no-op.
#[no_mangle]
pub extern "C" fn z_closure_matching_status_call(
closure: &z_owned_closure_matching_status_t,
sample: &z_matching_status_t,
) {
match closure.call {
Some(call) => call(sample, closure.context),
None => {
log::error!("Attempted to call an uninitialized closure!");
}
}
}
/// Drops the closure. Droping an uninitialized closure is a no-op.
#[no_mangle]
pub extern "C" fn z_closure_matching_status_drop(closure: &mut z_owned_closure_matching_status_t) {
let mut empty_closure = z_owned_closure_matching_status_t::empty();
std::mem::swap(&mut empty_closure, closure);
}
impl<F: Fn(&z_matching_status_t)> From<F> for z_owned_closure_matching_status_t {
fn from(f: F) -> Self {
let this = Box::into_raw(Box::new(f)) as _;
extern "C" fn call<F: Fn(&z_matching_status_t)>(
response: &z_matching_status_t,
this: *mut c_void,
) {
let this = unsafe { &*(this as *const F) };
this(response)
}
extern "C" fn drop<F>(this: *mut c_void) {
std::mem::drop(unsafe { Box::from_raw(this as *mut F) })
}
z_owned_closure_matching_status_t {
context: this,
call: Some(call::<F>),
drop: Some(drop::<F>),
}
}
}

0 comments on commit ec33a29

Please sign in to comment.