Skip to content

Commit 9550cf6

Browse files
committed
Remove internal mutex
1 parent 3601a05 commit 9550cf6

File tree

7 files changed

+14
-152
lines changed

7 files changed

+14
-152
lines changed

Cargo.lock

Lines changed: 0 additions & 17 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/core/Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ serde_json = { version = "1.0", default-features = false, features = ["alloc", "
2121
serde = { version = "1.0", default-features = false, features = ["alloc", "derive", "rc"] }
2222
streaming-iterator = { version = "0.1.9", default-features = false, features = ["alloc"] }
2323
const_format = "0.2.34"
24-
lock_api = { version = "0.4.12", default-features = false }
2524
futures-lite = { version = "2.6.0", default-features = false, features = ["alloc"] }
2625
rustc-hash = { version = "2.1", default-features = false }
2726

crates/core/src/bson/de.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
199199

200200
fn deserialize_newtype_struct<V>(
201201
self,
202-
name: &'static str,
202+
_name: &'static str,
203203
visitor: V,
204204
) -> Result<V::Value, Self::Error>
205205
where

crates/core/src/lib.rs

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ use core::ffi::{c_char, c_int};
1111

1212
use sqlite::ResultCode;
1313
use sqlite_nostd as sqlite;
14-
use util::SQLITE3_API;
1514

1615
mod bson;
1716
mod checkpoint;
@@ -43,11 +42,6 @@ pub extern "C" fn sqlite3_powersync_init(
4342
api: *mut sqlite::api_routines,
4443
) -> c_int {
4544
sqlite::EXTENSION_INIT2(api);
46-
unsafe {
47-
// SAFETY: This field is only assigned once, when the library is loaded.
48-
SQLITE3_API = api
49-
};
50-
5145
let result = init_extension(db);
5246

5347
return if let Err(code) = result {

crates/core/src/sync/interface.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ pub fn register(db: *mut sqlite::sqlite3) -> Result<(), ResultCode> {
120120
argv: *mut *mut sqlite::value,
121121
) -> () {
122122
let result = (|| -> Result<(), SQLiteError> {
123-
let controller = unsafe { ctx.user_data().cast::<SqlController>().as_ref() }
123+
let controller = unsafe { ctx.user_data().cast::<SqlController>().as_mut() }
124124
.ok_or_else(|| SQLiteError::from(ResultCode::INTERNAL))?;
125125

126126
let args = sqlite::args!(argc, argv);

crates/core/src/sync/streaming_sync.rs

Lines changed: 10 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,7 @@ use alloc::{
1414
};
1515
use futures_lite::FutureExt;
1616

17-
use crate::{
18-
bson,
19-
error::SQLiteError,
20-
kv::client_id,
21-
util::{sqlite3_mutex, Mutex},
22-
};
17+
use crate::{bson, error::SQLiteError, kv::client_id};
2318
use sqlite_nostd::{self as sqlite, ResultCode};
2419

2520
use super::{
@@ -40,42 +35,35 @@ use super::{
4035
pub struct SyncClient {
4136
db: *mut sqlite::sqlite3,
4237
/// The current [ClientState] (essentially an optional [StreamingSyncIteration]).
43-
///
44-
/// This is guarded behind a mutex so that we can mutate the state without forcing callers to
45-
/// obtain a mutable reference to the [SyncClient] itself. It doesn't mean much in practice
46-
/// because it's impossible to run two `powersync_control` calls on the same database connection
47-
/// concurrently.
48-
state: Mutex<ClientState>,
38+
state: ClientState,
4939
}
5040

5141
impl SyncClient {
5242
pub fn new(db: *mut sqlite::sqlite3) -> Self {
5343
Self {
5444
db,
55-
state: sqlite3_mutex(ClientState::Idle),
45+
state: ClientState::Idle,
5646
}
5747
}
5848

5949
pub fn push_event<'a>(
60-
&self,
50+
&mut self,
6151
event: SyncControlRequest<'a>,
6252
) -> Result<Vec<Instruction>, SQLiteError> {
63-
let mut state = self.state.lock();
64-
6553
match event {
6654
SyncControlRequest::StartSyncStream { parameters } => {
67-
state.tear_down()?;
55+
self.state.tear_down()?;
6856

6957
let mut handle = SyncIterationHandle::new(self.db, parameters)?;
7058
let instructions = handle.initialize()?;
71-
*state = ClientState::IterationActive(handle);
59+
self.state = ClientState::IterationActive(handle);
7260

7361
Ok(instructions)
7462
}
7563
SyncControlRequest::SyncEvent(sync_event) => {
7664
let mut active = ActiveEvent::new(sync_event);
7765

78-
let ClientState::IterationActive(handle) = &mut *state else {
66+
let ClientState::IterationActive(handle) = &mut self.state else {
7967
return Err(SQLiteError(
8068
ResultCode::MISUSE,
8169
Some("No iteration is active".to_string()),
@@ -84,19 +72,19 @@ impl SyncClient {
8472

8573
match handle.run(&mut active) {
8674
Err(e) => {
87-
*state = ClientState::Idle;
75+
self.state = ClientState::Idle;
8876
return Err(e);
8977
}
9078
Ok(done) => {
9179
if done {
92-
*state = ClientState::Idle;
80+
self.state = ClientState::Idle;
9381
}
9482
}
9583
};
9684

9785
Ok(active.instructions)
9886
}
99-
SyncControlRequest::StopSyncStream => state.tear_down(),
87+
SyncControlRequest::StopSyncStream => self.state.tear_down(),
10088
}
10189
}
10290
}

crates/core/src/util.rs

Lines changed: 2 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,9 @@ use core::ptr::{self, null_mut};
55
use alloc::format;
66
use alloc::string::String;
77

8-
use lock_api::{GuardSend, Mutex as MutexApi, RawMutex};
9-
use serde::de::Visitor;
10-
use sqlite_nostd::bindings::SQLITE_MUTEX_FAST;
11-
use sqlite_nostd::{api_routines, Connection, Context};
12-
13-
use crate::error::SQLiteError;
8+
#[cfg(not(feature = "getrandom"))]
149
use crate::sqlite;
15-
use crate::sqlite::bindings::sqlite3_mutex;
10+
use serde::de::Visitor;
1611

1712
use uuid::Uuid;
1813

@@ -94,103 +89,6 @@ where
9489
deserializer.deserialize_option(ValueVisitor)
9590
}
9691

97-
pub struct SqliteMutex {
98-
ptr: *mut sqlite3_mutex,
99-
}
100-
101-
// We always invoke mutex APIs through the api routines, even when we link the rest of SQLite
102-
// statically.
103-
// The reason is that it's possible to omit the mutex code (in which case we don't want to link
104-
// undefined symbols).
105-
pub(crate) static mut SQLITE3_API: *mut api_routines = ptr::null_mut();
106-
107-
impl SqliteMutex {
108-
pub fn new() -> Self {
109-
let native_alloc = unsafe {
110-
// SAFETY: SQLITE3_API is only set once when the library is loaded by SQLite.
111-
(*SQLITE3_API).mutex_alloc
112-
};
113-
114-
Self {
115-
ptr: match native_alloc {
116-
None => null_mut(),
117-
Some(mutex_alloc) => unsafe {
118-
// SAFETY: We're allowed to call sqlite3_mutex_alloc with this bitmask:
119-
// https://sqlite.org/c3ref/mutex_alloc.html
120-
mutex_alloc(SQLITE_MUTEX_FAST as i32)
121-
},
122-
},
123-
}
124-
}
125-
}
126-
127-
unsafe impl RawMutex for SqliteMutex {
128-
const INIT: Self = SqliteMutex { ptr: null_mut() };
129-
130-
type GuardMarker = GuardSend;
131-
132-
fn lock(&self) {
133-
if self.ptr.is_null() {
134-
// Disable mutex code
135-
} else {
136-
unsafe {
137-
// SAFETY: When we get here, we were able to allocate a mutex (so mutex methods
138-
// must be present).
139-
(*SQLITE3_API).mutex_enter.unwrap_unchecked()(self.ptr)
140-
}
141-
}
142-
}
143-
144-
fn try_lock(&self) -> bool {
145-
if self.ptr.is_null() {
146-
// Disable mutex code
147-
true
148-
} else {
149-
let res = unsafe {
150-
// SAFETY: When we get here, we were able to allocate a mutex (so mutex methods
151-
// must be present).
152-
(*SQLITE3_API).mutex_try.unwrap_unchecked()(self.ptr)
153-
};
154-
res == 0
155-
}
156-
}
157-
158-
unsafe fn unlock(&self) {
159-
if self.ptr.is_null() {
160-
// Disable mutex code
161-
} else {
162-
unsafe {
163-
// SAFETY: When we get here, we were able to allocate a mutex (so mutex methods
164-
// must be present). Also, this method is only allowed to be called after a caller
165-
// has locked the mutex before.
166-
(*SQLITE3_API).mutex_leave.unwrap_unchecked()(self.ptr)
167-
}
168-
}
169-
}
170-
}
171-
172-
impl Drop for SqliteMutex {
173-
fn drop(&mut self) {
174-
if !self.ptr.is_null() {
175-
unsafe {
176-
// SAFETY: The pointer points to a valid mutex we own. This means that we have been
177-
// able to allocate a mutex, so mutex methods must be present.
178-
(*SQLITE3_API).mutex_free.unwrap_unchecked()(self.ptr)
179-
};
180-
}
181-
}
182-
}
183-
184-
pub type Mutex<T> = MutexApi<SqliteMutex, T>;
185-
186-
/// Creates a [Mutex] implementation using `sqlite3_mutex_enter` and `sqlite3_mutex_free`.
187-
///
188-
/// When SQLite has been compiled without mutexes, the returned mutex doesn't do anything.
189-
pub fn sqlite3_mutex<T>(value: T) -> Mutex<T> {
190-
let raw = SqliteMutex::new();
191-
MutexApi::from_raw(raw, value)
192-
}
193-
19492
// Use getrandom crate to generate UUID.
19593
// This is not available in all WASM builds - use the default in those cases.
19694
#[cfg(feature = "getrandom")]

0 commit comments

Comments
 (0)