ffi: add RwLock to dc_accounts_t for thread safety

This commit is contained in:
link2xt
2021-09-05 11:10:30 +00:00
parent d05b399eac
commit 40fe65716f

View File

@@ -17,11 +17,13 @@ extern crate serde_json;
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::convert::TryInto; use std::convert::TryInto;
use std::fmt::Write; use std::fmt::Write;
use std::ops::Deref;
use std::ptr; use std::ptr;
use std::str::FromStr; use std::str::FromStr;
use std::time::{Duration, SystemTime}; use std::time::{Duration, SystemTime};
use anyhow::Context as _; use anyhow::Context as _;
use async_std::sync::RwLock;
use async_std::task::{block_on, spawn}; use async_std::task::{block_on, spawn};
use num_traits::{FromPrimitive, ToPrimitive}; use num_traits::{FromPrimitive, ToPrimitive};
@@ -3688,8 +3690,29 @@ pub unsafe extern "C" fn dc_provider_unref(provider: *mut dc_provider_t) {
// -- Accounts // -- Accounts
/// Reader-writer lock wrapper for accounts manager to guarantee thread safety when using
/// `dc_accounts_t` in multiple threads at once.
pub struct AccountsWrapper {
inner: RwLock<Accounts>,
}
impl Deref for AccountsWrapper {
type Target = RwLock<Accounts>;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl AccountsWrapper {
fn new(accounts: Accounts) -> Self {
let inner = RwLock::new(accounts);
Self { inner }
}
}
/// Struct representing a list of deltachat accounts. /// Struct representing a list of deltachat accounts.
pub type dc_accounts_t = Accounts; pub type dc_accounts_t = AccountsWrapper;
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn dc_accounts_new( pub unsafe extern "C" fn dc_accounts_new(
@@ -3712,7 +3735,7 @@ pub unsafe extern "C" fn dc_accounts_new(
let accs = block_on(Accounts::new(os_name, as_path(dbfile).to_path_buf().into())); let accs = block_on(Accounts::new(os_name, as_path(dbfile).to_path_buf().into()));
match accs { match accs {
Ok(accs) => Box::into_raw(Box::new(accs)), Ok(accs) => Box::into_raw(Box::new(AccountsWrapper::new(accs))),
Err(err) => { Err(err) => {
// We are using Anyhow's .context() and to show the inner error, too, we need the {:#}: // We are using Anyhow's .context() and to show the inner error, too, we need the {:#}:
eprintln!("failed to create accounts: {:#}", err); eprintln!("failed to create accounts: {:#}", err);
@@ -3744,7 +3767,7 @@ pub unsafe extern "C" fn dc_accounts_get_account(
} }
let accounts = &*accounts; let accounts = &*accounts;
block_on(accounts.get_account(id)) block_on(async move { accounts.read().await.get_account(id).await })
.map(|ctx| Box::into_raw(Box::new(ctx))) .map(|ctx| Box::into_raw(Box::new(ctx)))
.unwrap_or_else(std::ptr::null_mut) .unwrap_or_else(std::ptr::null_mut)
} }
@@ -3759,7 +3782,7 @@ pub unsafe extern "C" fn dc_accounts_get_selected_account(
} }
let accounts = &*accounts; let accounts = &*accounts;
block_on(accounts.get_selected_account()) block_on(async move { accounts.read().await.get_selected_account().await })
.map(|ctx| Box::into_raw(Box::new(ctx))) .map(|ctx| Box::into_raw(Box::new(ctx)))
.unwrap_or_else(std::ptr::null_mut) .unwrap_or_else(std::ptr::null_mut)
} }
@@ -3775,7 +3798,7 @@ pub unsafe extern "C" fn dc_accounts_select_account(
} }
let accounts = &*accounts; let accounts = &*accounts;
block_on(accounts.select_account(id)) block_on(async move { accounts.write().await.select_account(id).await })
.map(|_| 1) .map(|_| 1)
.unwrap_or(0) .unwrap_or(0)
} }
@@ -3789,7 +3812,7 @@ pub unsafe extern "C" fn dc_accounts_add_account(accounts: *mut dc_accounts_t) -
let accounts = &mut *accounts; let accounts = &mut *accounts;
block_on(accounts.add_account()).unwrap_or(0) block_on(async move { accounts.write().await.add_account().await }).unwrap_or(0)
} }
#[no_mangle] #[no_mangle]
@@ -3804,7 +3827,7 @@ pub unsafe extern "C" fn dc_accounts_remove_account(
let accounts = &mut *accounts; let accounts = &mut *accounts;
block_on(accounts.remove_account(id)) block_on(async move { accounts.write().await.remove_account(id).await })
.map(|_| 1) .map(|_| 1)
.unwrap_or_else(|_| 0) .unwrap_or_else(|_| 0)
} }
@@ -3822,9 +3845,15 @@ pub unsafe extern "C" fn dc_accounts_migrate_account(
let accounts = &mut *accounts; let accounts = &mut *accounts;
let dbfile = to_string_lossy(dbfile); let dbfile = to_string_lossy(dbfile);
block_on(accounts.migrate_account(async_std::path::PathBuf::from(dbfile))) block_on(async move {
.map(|_| 1) accounts
.unwrap_or_else(|_| 0) .write()
.await
.migrate_account(async_std::path::PathBuf::from(dbfile))
.await
})
.map(|_| 1)
.unwrap_or_else(|_| 0)
} }
#[no_mangle] #[no_mangle]
@@ -3835,7 +3864,7 @@ pub unsafe extern "C" fn dc_accounts_get_all(accounts: *mut dc_accounts_t) -> *m
} }
let accounts = &*accounts; let accounts = &*accounts;
let list = block_on(accounts.get_all()); let list = block_on(async move { accounts.read().await.get_all().await });
let array: dc_array_t = list.into(); let array: dc_array_t = list.into();
Box::into_raw(Box::new(array)) Box::into_raw(Box::new(array))
@@ -3848,7 +3877,7 @@ pub unsafe extern "C" fn dc_accounts_all_work_done(accounts: *mut dc_accounts_t)
return 0; return 0;
} }
let accounts = &*accounts; let accounts = &*accounts;
block_on(async move { accounts.all_work_done().await as libc::c_int }) block_on(async move { accounts.read().await.all_work_done().await as libc::c_int })
} }
#[no_mangle] #[no_mangle]
@@ -3859,7 +3888,7 @@ pub unsafe extern "C" fn dc_accounts_start_io(accounts: *mut dc_accounts_t) {
} }
let accounts = &*accounts; let accounts = &*accounts;
block_on(accounts.start_io()); block_on(async move { accounts.read().await.start_io().await });
} }
#[no_mangle] #[no_mangle]
@@ -3870,7 +3899,7 @@ pub unsafe extern "C" fn dc_accounts_stop_io(accounts: *mut dc_accounts_t) {
} }
let accounts = &*accounts; let accounts = &*accounts;
block_on(accounts.stop_io()); block_on(async move { accounts.read().await.stop_io().await });
} }
#[no_mangle] #[no_mangle]
@@ -3881,7 +3910,7 @@ pub unsafe extern "C" fn dc_accounts_maybe_network(accounts: *mut dc_accounts_t)
} }
let accounts = &*accounts; let accounts = &*accounts;
block_on(accounts.maybe_network()); block_on(async move { accounts.read().await.maybe_network().await });
} }
#[no_mangle] #[no_mangle]
@@ -3892,7 +3921,7 @@ pub unsafe extern "C" fn dc_accounts_maybe_network_lost(accounts: *mut dc_accoun
} }
let accounts = &*accounts; let accounts = &*accounts;
block_on(accounts.maybe_network_lost()); block_on(async move { accounts.write().await.maybe_network_lost().await });
} }
pub type dc_accounts_event_emitter_t = deltachat::accounts::EventEmitter; pub type dc_accounts_event_emitter_t = deltachat::accounts::EventEmitter;
@@ -3907,7 +3936,7 @@ pub unsafe extern "C" fn dc_accounts_get_event_emitter(
} }
let accounts = &*accounts; let accounts = &*accounts;
let emitter = block_on(accounts.get_event_emitter()); let emitter = block_on(async move { accounts.read().await.get_event_emitter().await });
Box::into_raw(Box::new(emitter)) Box::into_raw(Box::new(emitter))
} }