@@ -3,11 +3,23 @@ use std::ptr::NonNull;
3
3
use libsqlite3_sys:: { sqlite3, sqlite3_close, SQLITE_OK } ;
4
4
5
5
use crate :: sqlite:: SqliteError ;
6
+ use std:: sync:: Arc ;
6
7
7
8
/// Managed handle to the raw SQLite3 database handle.
8
- /// The database handle will be closed when this is dropped.
9
+ /// The database handle will be closed when this is dropped and no `ConnectionHandleRef`s exist .
9
10
#[ derive( Debug ) ]
10
- pub ( crate ) struct ConnectionHandle ( pub ( super ) NonNull < sqlite3 > ) ;
11
+ pub ( crate ) struct ConnectionHandle ( Arc < HandleInner > ) ;
12
+
13
+ /// A wrapper around `ConnectionHandle` which only exists for a `StatementWorker` to own
14
+ /// which prevents the `sqlite3` handle from being finalized while it is running `sqlite3_step()`
15
+ /// or `sqlite3_reset()`.
16
+ ///
17
+ /// Note that this does *not* actually give access to the database handle!
18
+ pub ( crate ) struct ConnectionHandleRef ( Arc < HandleInner > ) ;
19
+
20
+ // Wrapper for `*mut sqlite3` which finalizes the handle on-drop.
21
+ #[ derive( Debug ) ]
22
+ struct HandleInner ( NonNull < sqlite3 > ) ;
11
23
12
24
// A SQLite3 handle is safe to send between threads, provided not more than
13
25
// one is accessing it at the same time. This is upheld as long as [SQLITE_CONFIG_MULTITHREAD] is
@@ -20,19 +32,32 @@ pub(crate) struct ConnectionHandle(pub(super) NonNull<sqlite3>);
20
32
21
33
unsafe impl Send for ConnectionHandle { }
22
34
35
+ // SAFETY: `Arc<T>` normally only implements `Send` where `T: Sync` because it allows
36
+ // concurrent access.
37
+ //
38
+ // However, in this case we're only using `Arc` to prevent the database handle from being
39
+ // finalized while the worker still holds a statement handle; `ConnectionHandleRef` thus
40
+ // should *not* actually provide access to the database handle.
41
+ unsafe impl Send for ConnectionHandleRef { }
42
+
23
43
impl ConnectionHandle {
24
44
#[ inline]
25
45
pub ( super ) unsafe fn new ( ptr : * mut sqlite3 ) -> Self {
26
- Self ( NonNull :: new_unchecked ( ptr) )
46
+ Self ( Arc :: new ( HandleInner ( NonNull :: new_unchecked ( ptr) ) ) )
27
47
}
28
48
29
49
#[ inline]
30
50
pub ( crate ) fn as_ptr ( & self ) -> * mut sqlite3 {
31
- self . 0 . as_ptr ( )
51
+ self . 0 . 0 . as_ptr ( )
52
+ }
53
+
54
+ #[ inline]
55
+ pub ( crate ) fn to_ref ( & self ) -> ConnectionHandleRef {
56
+ ConnectionHandleRef ( Arc :: clone ( & self . 0 ) )
32
57
}
33
58
}
34
59
35
- impl Drop for ConnectionHandle {
60
+ impl Drop for HandleInner {
36
61
fn drop ( & mut self ) {
37
62
unsafe {
38
63
// https://sqlite.org/c3ref/close.html
0 commit comments