In process locking implemented, not sqlite locking.
This commit is contained in:
+22
-1
@@ -83,6 +83,18 @@ Returns all keys.
|
||||
|
||||
Returns all key-value pairs.
|
||||
}
|
||||
|
||||
@defmethod[(with-lock [proc (-> any/c)]) any/c]{
|
||||
|
||||
Calls @racket[proc] while holding the lock belonging to this keystore
|
||||
object and returns the value produced by @racket[proc]. Other threads
|
||||
using @method[keystore% with-lock] on the same object wait until the lock is
|
||||
released.
|
||||
|
||||
The lock is reentrant for nested calls on the same thread and is
|
||||
released when control leaves @racket[proc], including when an exception
|
||||
is raised. Keystore methods do not acquire this lock automatically.
|
||||
}
|
||||
}
|
||||
|
||||
@section{Examples}
|
||||
@@ -115,4 +127,13 @@ Returns all key-value pairs.
|
||||
@racketblock[
|
||||
(send ks glob "*b*")
|
||||
(send ks glob-kv "*b*")
|
||||
]
|
||||
]
|
||||
|
||||
@subsection{Locking}
|
||||
|
||||
@racketblock[
|
||||
(send ks with-lock
|
||||
(λ ()
|
||||
(send ks set! 'counter
|
||||
(add1 (send ks get 'counter 0)))))
|
||||
]
|
||||
|
||||
+39
-4
@@ -19,11 +19,18 @@ stringified lowercase form, which allows glob-style queries.
|
||||
@defstruct*[keystore
|
||||
([file any/c]
|
||||
[path path?]
|
||||
[dbh any/c])]{
|
||||
[dbh any/c]
|
||||
[lock-sem semaphore?]
|
||||
[in-lock (or/c thread? #f)]
|
||||
[entered exact-nonnegative-integer?])]{
|
||||
|
||||
Represents an open keystore. The @racket[file] field contains the
|
||||
original argument, @racket[path] is the resolved database path, and
|
||||
@racket[dbh] is the SQLite connection.
|
||||
@racket[dbh] is the SQLite connection. The remaining fields implement
|
||||
the reentrant lock used by @racket[ks-with-lock]: @racket[lock-sem]
|
||||
serializes access, @racket[in-lock] records the thread that holds the
|
||||
lock, and @racket[entered] records that thread's nesting depth. The
|
||||
@racket[in-lock] and @racket[entered] fields are mutable internal state.
|
||||
|
||||
The @tt{keystore?} predicate is altered to also check if the
|
||||
database connection is (still) valid.
|
||||
@@ -149,7 +156,25 @@ Commits a transaction with "COMMIT".
|
||||
@defproc[(ks-abort-transaction [ks keystore?]) boolean?]{
|
||||
|
||||
Aborts a transaction with "ROLLBACK".
|
||||
}
|
||||
}
|
||||
|
||||
@section{Locking}
|
||||
|
||||
@defproc[(ks-with-lock [ks keystore?] [proc (-> any/c)]) any/c]{
|
||||
|
||||
Calls @racket[proc] while holding the lock belonging to @racket[ks] and
|
||||
returns the value produced by @racket[proc]. Other threads using
|
||||
@racket[ks-with-lock] with the same keystore handle wait until the lock
|
||||
is released.
|
||||
|
||||
The lock is reentrant: @racket[proc] may call @racket[ks-with-lock]
|
||||
again on the same handle and thread. The lock is released when control
|
||||
leaves @racket[proc], including when an exception is raised.
|
||||
|
||||
The lock coordinates only code that uses the same keystore handle and
|
||||
explicitly calls @racket[ks-with-lock]. Individual keystore operations
|
||||
do not acquire it automatically.
|
||||
}
|
||||
|
||||
@section{Examples}
|
||||
|
||||
@@ -180,4 +205,14 @@ Aborts a transaction with "ROLLBACK".
|
||||
|
||||
@racketblock[
|
||||
(ks-keys-glob ks "*b*")
|
||||
]
|
||||
]
|
||||
|
||||
@subsection{Locking Example}
|
||||
|
||||
@racketblock[
|
||||
(ks-with-lock
|
||||
ks
|
||||
(λ ()
|
||||
(ks-set! ks 'counter
|
||||
(add1 (ks-get ks 'counter 0)))))
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user