mirror of
https://github.com/chatmail/core.git
synced 2026-05-22 00:06:30 +03:00
fix: avoid manual poll impl for accounts events
This commit is contained in:
committed by
GitHub
parent
60a8b47ad0
commit
7786a4ced4
@@ -3576,7 +3576,7 @@ pub unsafe extern "C" fn dc_accounts_get_next_event(
|
|||||||
if emitter.is_null() {
|
if emitter.is_null() {
|
||||||
return ptr::null_mut();
|
return ptr::null_mut();
|
||||||
}
|
}
|
||||||
let emitter = &*emitter;
|
let emitter = &mut *emitter;
|
||||||
|
|
||||||
emitter
|
emitter
|
||||||
.recv_sync()
|
.recv_sync()
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::pin::Pin;
|
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
|
||||||
use std::task::{Context as TaskContext, Poll};
|
|
||||||
|
|
||||||
use async_std::fs;
|
use async_std::fs;
|
||||||
use async_std::path::PathBuf;
|
use async_std::path::PathBuf;
|
||||||
|
use async_std::prelude::*;
|
||||||
use async_std::sync::{Arc, RwLock};
|
use async_std::sync::{Arc, RwLock};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
@@ -225,61 +223,42 @@ impl Accounts {
|
|||||||
|
|
||||||
/// Unified event emitter.
|
/// Unified event emitter.
|
||||||
pub async fn get_event_emitter(&self) -> EventEmitter {
|
pub async fn get_event_emitter(&self) -> EventEmitter {
|
||||||
let emitters = self
|
let emitters: Vec<_> = self
|
||||||
.accounts
|
.accounts
|
||||||
.read()
|
.read()
|
||||||
.await
|
.await
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(id, a)| EmitterWrapper {
|
.map(|(_id, a)| a.get_event_emitter())
|
||||||
id: *id,
|
|
||||||
emitter: a.get_event_emitter(),
|
|
||||||
done: AtomicBool::new(false),
|
|
||||||
})
|
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
EventEmitter(emitters)
|
EventEmitter(futures::stream::select_all(emitters))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct EventEmitter(futures::stream::SelectAll<crate::events::EventEmitter>);
|
||||||
|
|
||||||
impl EventEmitter {
|
impl EventEmitter {
|
||||||
/// Blocking recv of an event. Return `None` if the `Sender` has been droped.
|
/// Blocking recv of an event. Return `None` if all `Sender`s have been droped.
|
||||||
pub fn recv_sync(&self) -> Option<Event> {
|
pub fn recv_sync(&mut self) -> Option<Event> {
|
||||||
async_std::task::block_on(self.recv())
|
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 all `Sender`s have been droped.
|
||||||
pub async fn recv(&self) -> Option<Event> {
|
pub async fn recv(&mut self) -> Option<Event> {
|
||||||
futures::future::poll_fn(|cx| Pin::new(self).recv_poll(cx)).await
|
self.0.next().await
|
||||||
}
|
|
||||||
|
|
||||||
fn recv_poll(self: Pin<&Self>, _cx: &mut TaskContext<'_>) -> Poll<Option<Event>> {
|
|
||||||
for e in &*self.0 {
|
|
||||||
if e.done.load(Ordering::Acquire) {
|
|
||||||
// skip emitters that are already done
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
match e.emitter.try_recv() {
|
|
||||||
Ok(event) => return Poll::Ready(Some(event)),
|
|
||||||
Err(async_std::sync::TryRecvError::Disconnected) => {
|
|
||||||
e.done.store(true, Ordering::Release);
|
|
||||||
}
|
|
||||||
Err(async_std::sync::TryRecvError::Empty) => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Poll::Pending
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
impl async_std::stream::Stream for EventEmitter {
|
||||||
pub struct EventEmitter(Vec<EmitterWrapper>);
|
type Item = Event;
|
||||||
|
|
||||||
#[derive(Debug)]
|
fn poll_next(
|
||||||
struct EmitterWrapper {
|
mut self: std::pin::Pin<&mut Self>,
|
||||||
id: u32,
|
cx: &mut std::task::Context<'_>,
|
||||||
emitter: crate::events::EventEmitter,
|
) -> std::task::Poll<Option<Self::Item>> {
|
||||||
done: AtomicBool,
|
std::pin::Pin::new(&mut self.0).poll_next(cx)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const CONFIG_NAME: &str = "accounts.toml";
|
pub const CONFIG_NAME: &str = "accounts.toml";
|
||||||
|
|||||||
@@ -58,12 +58,18 @@ impl EventEmitter {
|
|||||||
|
|
||||||
/// 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 droped.
|
||||||
pub async fn recv(&self) -> Option<Event> {
|
pub async fn recv(&self) -> Option<Event> {
|
||||||
// TODO: change once we can use async channels internally.
|
|
||||||
self.0.recv().await.ok()
|
self.0.recv().await.ok()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn try_recv(&self) -> Result<Event, async_std::sync::TryRecvError> {
|
impl async_std::stream::Stream for EventEmitter {
|
||||||
self.0.try_recv()
|
type Item = Event;
|
||||||
|
|
||||||
|
fn poll_next(
|
||||||
|
mut self: std::pin::Pin<&mut Self>,
|
||||||
|
cx: &mut std::task::Context<'_>,
|
||||||
|
) -> std::task::Poll<Option<Self::Item>> {
|
||||||
|
std::pin::Pin::new(&mut self.0).poll_next(cx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user