diff --git a/CHANGELOG.md b/CHANGELOG.md index 3c2bfa43e..612ea6cef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,9 @@ ## 1.79.0 +### API-Changes +- add `dc_event_emitter_close()` to termitate event loops in a thread-safe way + ### Changes - Send locations in the background regardless of SMTP loop activity #3247 - refactorings #3268 diff --git a/deltachat-ffi/deltachat.h b/deltachat-ffi/deltachat.h index 3e08daa05..58c642d08 100644 --- a/deltachat-ffi/deltachat.h +++ b/deltachat-ffi/deltachat.h @@ -5201,6 +5201,15 @@ dc_event_t* dc_get_next_event(dc_event_emitter_t* emitter); void dc_event_emitter_unref(dc_event_emitter_t* emitter); +/** + * Closes event emitter object. + * + * @memberof dc_event_emitter_t + * @param emitter Event emitter object as returned from dc_get_event_emitter(). + */ +void dc_event_emitter_close(dc_event_emitter_t* emitter); + + /** * @class dc_accounts_event_emitter_t * diff --git a/deltachat-ffi/src/lib.rs b/deltachat-ffi/src/lib.rs index cf5ed81ea..4e9568eac 100644 --- a/deltachat-ffi/src/lib.rs +++ b/deltachat-ffi/src/lib.rs @@ -640,6 +640,18 @@ pub unsafe extern "C" fn dc_event_emitter_unref(emitter: *mut dc_event_emitter_t Box::from_raw(emitter); } +#[no_mangle] +pub unsafe extern "C" fn dc_event_emitter_close(emitter: *mut dc_event_emitter_t) { + if emitter.is_null() { + eprintln!("ignoring careless call to dc_event_emitter_close()"); + return; + } + + let emitter = &mut *emitter; + + block_on(emitter.close()) +} + #[no_mangle] pub unsafe extern "C" fn dc_get_next_event(events: *mut dc_event_emitter_t) -> *mut dc_event_t { if events.is_null() { diff --git a/src/events.rs b/src/events.rs index 73ae3a49b..67ba8a010 100644 --- a/src/events.rs +++ b/src/events.rs @@ -64,15 +64,20 @@ impl Events { pub struct EventEmitter(Receiver); impl EventEmitter { - /// Blocking recv of an event. Return `None` if the `Sender` has been droped. + /// Blocking recv of an event. Return `None` if the `Sender` has been dropped. pub fn recv_sync(&self) -> Option { async_std::task::block_on(self.recv()) } - /// Async recv of an event. Return `None` if the `Sender` has been droped. + /// Async recv of an event. Return `None` if the `Sender` has been dropped. pub async fn recv(&self) -> Option { self.0.recv().await.ok() } + + /// Closes event emitter. + pub async fn close(&mut self) { + self.0.close(); + } } impl async_std::stream::Stream for EventEmitter {