mirror of
https://github.com/launchbadge/sqlx.git
synced 2025-12-30 13:20:59 +00:00
66 lines
1.5 KiB
Rust
66 lines
1.5 KiB
Rust
use std::ffi::c_void;
|
|
use std::os::raw::c_int;
|
|
use std::slice;
|
|
use std::sync::{Condvar, Mutex};
|
|
|
|
use libsqlite3_sys::{sqlite3, sqlite3_unlock_notify, SQLITE_OK};
|
|
|
|
use crate::SqliteError;
|
|
|
|
// Wait for unlock notification (https://www.sqlite.org/unlock_notify.html)
|
|
pub unsafe fn wait(conn: *mut sqlite3) -> Result<(), SqliteError> {
|
|
let notify = Notify::new();
|
|
|
|
if sqlite3_unlock_notify(
|
|
conn,
|
|
Some(unlock_notify_cb),
|
|
¬ify as *const Notify as *mut Notify as *mut _,
|
|
) != SQLITE_OK
|
|
{
|
|
return Err(SqliteError::new(conn));
|
|
}
|
|
|
|
notify.wait();
|
|
|
|
Ok(())
|
|
}
|
|
|
|
unsafe extern "C" fn unlock_notify_cb(ptr: *mut *mut c_void, len: c_int) {
|
|
let ptr = ptr as *mut &Notify;
|
|
// We don't have a choice; we can't panic and unwind into FFI here.
|
|
let slice = slice::from_raw_parts(ptr, usize::try_from(len).unwrap_or(0));
|
|
|
|
for notify in slice {
|
|
notify.fire();
|
|
}
|
|
}
|
|
|
|
struct Notify {
|
|
mutex: Mutex<bool>,
|
|
condvar: Condvar,
|
|
}
|
|
|
|
impl Notify {
|
|
fn new() -> Self {
|
|
Self {
|
|
mutex: Mutex::new(false),
|
|
condvar: Condvar::new(),
|
|
}
|
|
}
|
|
|
|
fn wait(&self) {
|
|
// We only want to wait until the lock is available again.
|
|
#[allow(let_underscore_lock)]
|
|
let _ = self
|
|
.condvar
|
|
.wait_while(self.mutex.lock().unwrap(), |fired| !*fired)
|
|
.unwrap();
|
|
}
|
|
|
|
fn fire(&self) {
|
|
let mut lock = self.mutex.lock().unwrap();
|
|
*lock = true;
|
|
self.condvar.notify_one();
|
|
}
|
|
}
|