mirror of
https://github.com/isar/rusqlite.git
synced 2024-11-26 03:11:36 +08:00
cleanup unlock_notify code a bit
This commit is contained in:
parent
3e57bf4567
commit
519684a744
@ -13,7 +13,6 @@ use super::{Connection, InterruptHandle, OpenFlags, Result};
|
|||||||
use crate::error::{error_from_handle, error_from_sqlite_code, Error};
|
use crate::error::{error_from_handle, error_from_sqlite_code, Error};
|
||||||
use crate::raw_statement::RawStatement;
|
use crate::raw_statement::RawStatement;
|
||||||
use crate::statement::Statement;
|
use crate::statement::Statement;
|
||||||
use crate::unlock_notify;
|
|
||||||
use crate::version::version_number;
|
use crate::version::version_number;
|
||||||
|
|
||||||
pub struct InnerConnection {
|
pub struct InnerConnection {
|
||||||
@ -223,35 +222,37 @@ impl InnerConnection {
|
|||||||
let mut c_stmt = ptr::null_mut();
|
let mut c_stmt = ptr::null_mut();
|
||||||
let (c_sql, len, _) = str_for_sqlite(sql.as_bytes())?;
|
let (c_sql, len, _) = str_for_sqlite(sql.as_bytes())?;
|
||||||
let mut c_tail = ptr::null();
|
let mut c_tail = ptr::null();
|
||||||
|
#[cfg(not(feature = "unlock_notify"))]
|
||||||
let r = unsafe {
|
let r = unsafe {
|
||||||
if cfg!(feature = "unlock_notify") {
|
ffi::sqlite3_prepare_v2(
|
||||||
let mut rc;
|
self.db(),
|
||||||
loop {
|
c_sql,
|
||||||
rc = ffi::sqlite3_prepare_v2(
|
len,
|
||||||
self.db(),
|
&mut c_stmt as *mut *mut ffi::sqlite3_stmt,
|
||||||
c_sql,
|
&mut c_tail as *mut *const c_char,
|
||||||
len,
|
)
|
||||||
&mut c_stmt as *mut *mut ffi::sqlite3_stmt,
|
};
|
||||||
&mut c_tail as *mut *const c_char,
|
#[cfg(feature = "unlock_notify")]
|
||||||
);
|
let r = unsafe {
|
||||||
if !unlock_notify::is_locked(self.db, rc) {
|
use crate::unlock_notify;
|
||||||
break;
|
let mut rc;
|
||||||
}
|
loop {
|
||||||
rc = unlock_notify::wait_for_unlock_notify(self.db);
|
rc = ffi::sqlite3_prepare_v2(
|
||||||
if rc != ffi::SQLITE_OK {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
rc
|
|
||||||
} else {
|
|
||||||
ffi::sqlite3_prepare_v2(
|
|
||||||
self.db(),
|
self.db(),
|
||||||
c_sql,
|
c_sql,
|
||||||
len,
|
len,
|
||||||
&mut c_stmt as *mut *mut ffi::sqlite3_stmt,
|
&mut c_stmt as *mut *mut ffi::sqlite3_stmt,
|
||||||
&mut c_tail as *mut *const c_char,
|
&mut c_tail as *mut *const c_char,
|
||||||
)
|
);
|
||||||
|
if !unlock_notify::is_locked(self.db, rc) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
rc = unlock_notify::wait_for_unlock_notify(self.db);
|
||||||
|
if rc != ffi::SQLITE_OK {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
rc
|
||||||
};
|
};
|
||||||
// If there is an error, *ppStmt is set to NULL.
|
// If there is an error, *ppStmt is set to NULL.
|
||||||
self.decode_result(r)?;
|
self.decode_result(r)?;
|
||||||
|
@ -125,6 +125,7 @@ mod statement;
|
|||||||
pub mod trace;
|
pub mod trace;
|
||||||
mod transaction;
|
mod transaction;
|
||||||
pub mod types;
|
pub mod types;
|
||||||
|
#[cfg(feature = "unlock_notify")]
|
||||||
mod unlock_notify;
|
mod unlock_notify;
|
||||||
mod version;
|
mod version;
|
||||||
#[cfg(feature = "vtab")]
|
#[cfg(feature = "vtab")]
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
use super::ffi;
|
use super::ffi;
|
||||||
use super::unlock_notify;
|
|
||||||
use super::StatementStatus;
|
use super::StatementStatus;
|
||||||
#[cfg(feature = "modern_sqlite")]
|
#[cfg(feature = "modern_sqlite")]
|
||||||
use crate::util::SqliteMallocString;
|
use crate::util::SqliteMallocString;
|
||||||
@ -101,25 +100,38 @@ impl RawStatement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(not(feature = "unlock_notify"), inline)]
|
#[inline]
|
||||||
|
#[cfg(not(feature = "unlock_notify"))]
|
||||||
pub fn step(&self) -> c_int {
|
pub fn step(&self) -> c_int {
|
||||||
if cfg!(feature = "unlock_notify") {
|
unsafe { ffi::sqlite3_step(self.ptr) }
|
||||||
let db = unsafe { ffi::sqlite3_db_handle(self.ptr) };
|
}
|
||||||
let mut rc;
|
|
||||||
loop {
|
#[cfg(feature = "unlock_notify")]
|
||||||
rc = unsafe { ffi::sqlite3_step(self.ptr) };
|
pub fn step(&self) -> c_int {
|
||||||
if unsafe { !unlock_notify::is_locked(db, rc) } {
|
use crate::unlock_notify;
|
||||||
break;
|
let mut db = core::ptr::null_mut::<ffi::sqlite3>();
|
||||||
|
loop {
|
||||||
|
unsafe {
|
||||||
|
let mut rc = ffi::sqlite3_step(self.ptr);
|
||||||
|
// Bail out early for success and errors unrelated to locking. We
|
||||||
|
// still need check `is_locked` after this, but checking now lets us
|
||||||
|
// avoid one or two (admittedly cheap) calls into SQLite that we
|
||||||
|
// don't need to make.
|
||||||
|
if (rc & 0xff) != ffi::SQLITE_LOCKED {
|
||||||
|
break rc;
|
||||||
}
|
}
|
||||||
rc = unsafe { unlock_notify::wait_for_unlock_notify(db) };
|
if db.is_null() {
|
||||||
|
db = ffi::sqlite3_db_handle(self.ptr);
|
||||||
|
}
|
||||||
|
if !unlock_notify::is_locked(db, rc) {
|
||||||
|
break rc;
|
||||||
|
}
|
||||||
|
rc = unlock_notify::wait_for_unlock_notify(db);
|
||||||
if rc != ffi::SQLITE_OK {
|
if rc != ffi::SQLITE_OK {
|
||||||
break;
|
break rc;
|
||||||
}
|
}
|
||||||
self.reset();
|
self.reset();
|
||||||
}
|
}
|
||||||
rc
|
|
||||||
} else {
|
|
||||||
unsafe { ffi::sqlite3_step(self.ptr) }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,22 +1,17 @@
|
|||||||
//! [Unlock Notification](http://sqlite.org/unlock_notify.html)
|
//! [Unlock Notification](http://sqlite.org/unlock_notify.html)
|
||||||
|
|
||||||
use std::os::raw::c_int;
|
use std::os::raw::c_int;
|
||||||
#[cfg(feature = "unlock_notify")]
|
|
||||||
use std::os::raw::c_void;
|
use std::os::raw::c_void;
|
||||||
#[cfg(feature = "unlock_notify")]
|
|
||||||
use std::panic::catch_unwind;
|
use std::panic::catch_unwind;
|
||||||
#[cfg(feature = "unlock_notify")]
|
|
||||||
use std::sync::{Condvar, Mutex};
|
use std::sync::{Condvar, Mutex};
|
||||||
|
|
||||||
use crate::ffi;
|
use crate::ffi;
|
||||||
|
|
||||||
#[cfg(feature = "unlock_notify")]
|
|
||||||
struct UnlockNotification {
|
struct UnlockNotification {
|
||||||
cond: Condvar, // Condition variable to wait on
|
cond: Condvar, // Condition variable to wait on
|
||||||
mutex: Mutex<bool>, // Mutex to protect structure
|
mutex: Mutex<bool>, // Mutex to protect structure
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "unlock_notify")]
|
|
||||||
#[allow(clippy::mutex_atomic)]
|
#[allow(clippy::mutex_atomic)]
|
||||||
impl UnlockNotification {
|
impl UnlockNotification {
|
||||||
fn new() -> UnlockNotification {
|
fn new() -> UnlockNotification {
|
||||||
@ -27,21 +22,25 @@ impl UnlockNotification {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn fired(&self) {
|
fn fired(&self) {
|
||||||
let mut flag = self.mutex.lock().unwrap();
|
let mut flag = unpoison(self.mutex.lock());
|
||||||
*flag = true;
|
*flag = true;
|
||||||
self.cond.notify_one();
|
self.cond.notify_one();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn wait(&self) {
|
fn wait(&self) {
|
||||||
let mut fired = self.mutex.lock().unwrap();
|
let mut fired = unpoison(self.mutex.lock());
|
||||||
while !*fired {
|
while !*fired {
|
||||||
fired = self.cond.wait(fired).unwrap();
|
fired = unpoison(self.cond.wait(fired));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn unpoison<T>(r: Result<T, std::sync::PoisonError<T>>) -> T {
|
||||||
|
r.unwrap_or_else(std::sync::PoisonError::into_inner)
|
||||||
|
}
|
||||||
|
|
||||||
/// This function is an unlock-notify callback
|
/// This function is an unlock-notify callback
|
||||||
#[cfg(feature = "unlock_notify")]
|
|
||||||
unsafe extern "C" fn unlock_notify_cb(ap_arg: *mut *mut c_void, n_arg: c_int) {
|
unsafe extern "C" fn unlock_notify_cb(ap_arg: *mut *mut c_void, n_arg: c_int) {
|
||||||
use std::slice::from_raw_parts;
|
use std::slice::from_raw_parts;
|
||||||
let args = from_raw_parts(ap_arg as *const &UnlockNotification, n_arg as usize);
|
let args = from_raw_parts(ap_arg as *const &UnlockNotification, n_arg as usize);
|
||||||
@ -50,7 +49,6 @@ unsafe extern "C" fn unlock_notify_cb(ap_arg: *mut *mut c_void, n_arg: c_int) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "unlock_notify")]
|
|
||||||
pub unsafe fn is_locked(db: *mut ffi::sqlite3, rc: c_int) -> bool {
|
pub unsafe fn is_locked(db: *mut ffi::sqlite3, rc: c_int) -> bool {
|
||||||
rc == ffi::SQLITE_LOCKED_SHAREDCACHE
|
rc == ffi::SQLITE_LOCKED_SHAREDCACHE
|
||||||
|| (rc & 0xFF) == ffi::SQLITE_LOCKED
|
|| (rc & 0xFF) == ffi::SQLITE_LOCKED
|
||||||
@ -87,17 +85,6 @@ pub unsafe fn wait_for_unlock_notify(db: *mut ffi::sqlite3) -> c_int {
|
|||||||
rc
|
rc
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "unlock_notify"))]
|
|
||||||
pub unsafe fn is_locked(_db: *mut ffi::sqlite3, _rc: c_int) -> bool {
|
|
||||||
unreachable!()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(feature = "unlock_notify"))]
|
|
||||||
pub unsafe fn wait_for_unlock_notify(_db: *mut ffi::sqlite3) -> c_int {
|
|
||||||
unreachable!()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "unlock_notify")]
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use crate::{Connection, OpenFlags, Result, Transaction, TransactionBehavior};
|
use crate::{Connection, OpenFlags, Result, Transaction, TransactionBehavior};
|
||||||
|
Loading…
Reference in New Issue
Block a user