mirror of
https://github.com/chatmail/core.git
synced 2026-04-23 00:16:34 +03:00
feat: implement minimal rust threads
This commit is contained in:
15
Cargo.lock
generated
15
Cargo.lock
generated
@@ -498,6 +498,19 @@ dependencies = [
|
|||||||
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam"
|
||||||
|
version = "0.7.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"crossbeam-channel 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"crossbeam-epoch 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"crossbeam-queue 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossbeam-channel"
|
name = "crossbeam-channel"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
@@ -641,6 +654,7 @@ dependencies = [
|
|||||||
"byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"charset 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"charset 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"chrono 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
"chrono 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"crossbeam 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"debug_stub_derive 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"debug_stub_derive 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"deltachat_derive 2.0.0",
|
"deltachat_derive 2.0.0",
|
||||||
"email 0.0.21 (git+https://github.com/deltachat/rust-email)",
|
"email 0.0.21 (git+https://github.com/deltachat/rust-email)",
|
||||||
@@ -3346,6 +3360,7 @@ dependencies = [
|
|||||||
"checksum core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e7ca8a5221364ef15ce201e8ed2f609fc312682a8f4e0e3d4aa5879764e0fa3b"
|
"checksum core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e7ca8a5221364ef15ce201e8ed2f609fc312682a8f4e0e3d4aa5879764e0fa3b"
|
||||||
"checksum crc24 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "fd121741cf3eb82c08dd3023eb55bf2665e5f60ec20f89760cf836ae4562e6a0"
|
"checksum crc24 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "fd121741cf3eb82c08dd3023eb55bf2665e5f60ec20f89760cf836ae4562e6a0"
|
||||||
"checksum crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1"
|
"checksum crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1"
|
||||||
|
"checksum crossbeam 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "69323bff1fb41c635347b8ead484a5ca6c3f11914d784170b158d8449ab07f8e"
|
||||||
"checksum crossbeam-channel 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "acec9a3b0b3559f15aee4f90746c4e5e293b701c0f7d3925d24e01645267b68c"
|
"checksum crossbeam-channel 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "acec9a3b0b3559f15aee4f90746c4e5e293b701c0f7d3925d24e01645267b68c"
|
||||||
"checksum crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c3aa945d63861bfe624b55d153a39684da1e8c0bc8fba932f7ee3a3c16cea3ca"
|
"checksum crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c3aa945d63861bfe624b55d153a39684da1e8c0bc8fba932f7ee3a3c16cea3ca"
|
||||||
"checksum crossbeam-epoch 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5064ebdbf05ce3cb95e45c8b086f72263f4166b29b97f6baff7ef7fe047b55ac"
|
"checksum crossbeam-epoch 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5064ebdbf05ce3cb95e45c8b086f72263f4166b29b97f6baff7ef7fe047b55ac"
|
||||||
|
|||||||
@@ -58,8 +58,8 @@ encoded-words = { git = "https://github.com/async-email/encoded-words", branch="
|
|||||||
native-tls = "0.2.3"
|
native-tls = "0.2.3"
|
||||||
image = { version = "0.22.4", default-features=false, features = ["gif_codec", "jpeg", "ico", "png_codec", "pnm", "webp", "bmp"] }
|
image = { version = "0.22.4", default-features=false, features = ["gif_codec", "jpeg", "ico", "png_codec", "pnm", "webp", "bmp"] }
|
||||||
pretty_env_logger = "0.3.1"
|
pretty_env_logger = "0.3.1"
|
||||||
|
|
||||||
rustyline = { version = "4.1.0", optional = true }
|
rustyline = { version = "4.1.0", optional = true }
|
||||||
|
crossbeam = "0.7.3"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
tempfile = "3.0"
|
tempfile = "3.0"
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ categories = ["cryptography", "std", "email"]
|
|||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
name = "deltachat"
|
name = "deltachat"
|
||||||
crate-type = ["cdylib", "staticlib"]
|
crate-type = ["cdylib"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
deltachat = { path = "../", default-features = false }
|
deltachat = { path = "../", default-features = false }
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
nightly-2019-11-06
|
nightly-2020-01-26
|
||||||
|
|||||||
103
src/context.rs
103
src/context.rs
@@ -3,7 +3,9 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::ffi::OsString;
|
use std::ffi::OsString;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::sync::{Arc, Condvar, Mutex, RwLock};
|
use std::sync::{Arc, Condvar, Mutex, RwLock, atomic::{Ordering, AtomicBool}};
|
||||||
|
|
||||||
|
use crossbeam::channel::{bounded, unbounded, Receiver, Sender};
|
||||||
|
|
||||||
use crate::chat::*;
|
use crate::chat::*;
|
||||||
use crate::config::Config;
|
use crate::config::Config;
|
||||||
@@ -47,8 +49,6 @@ pub struct Context {
|
|||||||
pub smtp: Arc<Mutex<Smtp>>,
|
pub smtp: Arc<Mutex<Smtp>>,
|
||||||
pub smtp_state: Arc<(Mutex<SmtpState>, Condvar)>,
|
pub smtp_state: Arc<(Mutex<SmtpState>, Condvar)>,
|
||||||
pub oauth2_critical: Arc<Mutex<()>>,
|
pub oauth2_critical: Arc<Mutex<()>>,
|
||||||
#[debug_stub = "Callback"]
|
|
||||||
cb: Box<ContextCallback>,
|
|
||||||
pub os_name: Option<String>,
|
pub os_name: Option<String>,
|
||||||
pub cmdline_sel_chat_id: Arc<RwLock<ChatId>>,
|
pub cmdline_sel_chat_id: Arc<RwLock<ChatId>>,
|
||||||
pub bob: Arc<RwLock<BobStatus>>,
|
pub bob: Arc<RwLock<BobStatus>>,
|
||||||
@@ -57,6 +57,16 @@ pub struct Context {
|
|||||||
/// Mutex to avoid generating the key for the user more than once.
|
/// Mutex to avoid generating the key for the user more than once.
|
||||||
pub generating_key_mutex: Mutex<()>,
|
pub generating_key_mutex: Mutex<()>,
|
||||||
pub translated_stockstrings: RwLock<HashMap<usize, String>>,
|
pub translated_stockstrings: RwLock<HashMap<usize, String>>,
|
||||||
|
|
||||||
|
#[debug_stub = "Callback"]
|
||||||
|
cb: Box<ContextCallback>,
|
||||||
|
|
||||||
|
event_sender: Sender<Event>,
|
||||||
|
event_receiver: Receiver<Event>,
|
||||||
|
shutdown_sender: Sender<()>,
|
||||||
|
shutdown_receiver: Receiver<()>,
|
||||||
|
|
||||||
|
is_running: AtomicBool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
@@ -80,6 +90,16 @@ pub fn get_info() -> HashMap<&'static str, String> {
|
|||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! while_running {
|
||||||
|
($self:expr, $code:block) => {
|
||||||
|
if $self.is_running.load(Ordering::Relaxed) {
|
||||||
|
$code
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
impl Context {
|
impl Context {
|
||||||
/// Creates new context.
|
/// Creates new context.
|
||||||
pub fn new(cb: Box<ContextCallback>, os_name: String, dbfile: PathBuf) -> Result<Context> {
|
pub fn new(cb: Box<ContextCallback>, os_name: String, dbfile: PathBuf) -> Result<Context> {
|
||||||
@@ -106,6 +126,10 @@ impl Context {
|
|||||||
"Blobdir does not exist: {}",
|
"Blobdir does not exist: {}",
|
||||||
blobdir.display()
|
blobdir.display()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let (event_sender, event_receiver) = unbounded();
|
||||||
|
let (shutdown_sender, shutdown_receiver) = bounded(0);
|
||||||
|
|
||||||
let ctx = Context {
|
let ctx = Context {
|
||||||
blobdir,
|
blobdir,
|
||||||
dbfile,
|
dbfile,
|
||||||
@@ -138,6 +162,11 @@ impl Context {
|
|||||||
perform_inbox_jobs_needed: Arc::new(RwLock::new(false)),
|
perform_inbox_jobs_needed: Arc::new(RwLock::new(false)),
|
||||||
generating_key_mutex: Mutex::new(()),
|
generating_key_mutex: Mutex::new(()),
|
||||||
translated_stockstrings: RwLock::new(HashMap::new()),
|
translated_stockstrings: RwLock::new(HashMap::new()),
|
||||||
|
event_sender,
|
||||||
|
event_receiver,
|
||||||
|
shutdown_sender,
|
||||||
|
shutdown_receiver,
|
||||||
|
is_running: Default::default(),
|
||||||
};
|
};
|
||||||
|
|
||||||
ensure!(
|
ensure!(
|
||||||
@@ -159,7 +188,73 @@ impl Context {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn call_cb(&self, event: Event) {
|
pub fn call_cb(&self, event: Event) {
|
||||||
(*self.cb)(self, event);
|
self.event_sender.send(event).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Start the run loop.
|
||||||
|
pub fn run(&self) {
|
||||||
|
use crossbeam::channel::select;
|
||||||
|
|
||||||
|
self.is_running.store(true, Ordering::Relaxed);
|
||||||
|
|
||||||
|
crossbeam::scope(|s| {
|
||||||
|
let imap_handle = s.spawn(|_| loop {
|
||||||
|
while_running!(self, {
|
||||||
|
perform_inbox_jobs(self);
|
||||||
|
while_running!(self, {
|
||||||
|
perform_inbox_fetch(self);
|
||||||
|
while_running!(self, { perform_inbox_idle(self) });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
let mvbox_handle = s.spawn(|_| loop {
|
||||||
|
while_running!(self, {
|
||||||
|
perform_mvbox_fetch(self);
|
||||||
|
while_running!(self, {
|
||||||
|
perform_mvbox_idle(self);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
let sentbox_handle = s.spawn(|_| loop {
|
||||||
|
while_running!(self, {
|
||||||
|
perform_sentbox_fetch(self);
|
||||||
|
while_running!(self, {
|
||||||
|
perform_sentbox_idle(self);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
let smtp_handle = s.spawn(|_| loop {
|
||||||
|
while_running!(self, {
|
||||||
|
perform_smtp_jobs(self);
|
||||||
|
while_running!(self, {
|
||||||
|
perform_smtp_idle(self);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
loop {
|
||||||
|
select! {
|
||||||
|
recv(self.event_receiver) -> event => {
|
||||||
|
// This gurantees that the callback is always called from the thread
|
||||||
|
// that called `run`.
|
||||||
|
(*self.cb)(self, event.unwrap())
|
||||||
|
},
|
||||||
|
recv(self.shutdown_receiver) -> _ => break,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
imap_handle.join().unwrap();
|
||||||
|
mvbox_handle.join().unwrap();
|
||||||
|
sentbox_handle.join().unwrap();
|
||||||
|
smtp_handle.join().unwrap();
|
||||||
|
})
|
||||||
|
.unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Stop the run loop. Blocks until all threads have shutdown.
|
||||||
|
pub fn shutdown(&self) {
|
||||||
|
self.is_running.store(false, Ordering::Relaxed);
|
||||||
|
self.shutdown_sender.send(()).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
#![forbid(unsafe_code)]
|
|
||||||
#![deny(clippy::correctness, missing_debug_implementations, clippy::all)]
|
#![deny(clippy::correctness, missing_debug_implementations, clippy::all)]
|
||||||
#![allow(clippy::match_bool)]
|
#![allow(clippy::match_bool)]
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user