11import type { ResourceAcquire , ResourceRelease } from '@matrixai/resources' ;
2- import type { Lockable , ToString , LockRequest } from './types' ;
2+ import type {
3+ ToString ,
4+ Lockable ,
5+ MultiLockRequest ,
6+ MultiLockAcquire ,
7+ MultiLockAcquired
8+ } from './types' ;
39import { withF , withG } from '@matrixai/resources' ;
410import { ErrorAsyncLocksLockBoxConflict } from './errors' ;
511
612class LockBox < L extends Lockable = Lockable > implements Lockable {
713 protected _locks : Map < string , L > = new Map ( ) ;
814
9- public lock ( ...requests : Array < LockRequest < L > > ) : ResourceAcquire < LockBox < L > > {
15+ public lock ( ...requests : Array < MultiLockRequest < L > > ) : ResourceAcquire < LockBox < L > > {
1016 return async ( ) => {
1117 // Convert to strings
1218 // This creates a copy of the requests
@@ -79,8 +85,8 @@ class LockBox<L extends Lockable = Lockable> implements Lockable {
7985 }
8086
8187 public lockMulti (
82- ...requests : Array < LockRequest < L > >
83- ) : Array < [ ToString , ResourceAcquire < L > ] > {
88+ ...requests : Array < MultiLockRequest < L > >
89+ ) : Array < MultiLockAcquire < L > > {
8490 // Convert to strings
8591 // This creates a copy of the requests
8692 let requests_ : Array <
@@ -101,51 +107,49 @@ class LockBox<L extends Lockable = Lockable> implements Lockable {
101107 requests_ = requests_ . filter (
102108 ( [ key ] , i , arr ) => i === 0 || key !== arr [ i - 1 ] [ 0 ] ,
103109 ) ;
104- const lockAcquires : Array < [ ToString , ResourceAcquire < L > ] > = [ ] ;
110+ const lockAcquires : Array < MultiLockAcquire < L > > = [ ] ;
105111 for ( const [ key , keyOrig , LockConstructor , ...lockingParams ] of requests_ ) {
106- lockAcquires . push ( [
107- keyOrig ,
108- async ( ) => {
109- let lock = this . _locks . get ( key ) ;
110- let lockRelease : ResourceRelease ;
111- try {
112- if ( lock == null ) {
113- lock = new LockConstructor ( ) ;
114- this . _locks . set ( key , lock ) ;
115- } else {
116- // It is possible to swap the lock class, but only after the lock key is released
117- if ( ! ( lock instanceof LockConstructor ) ) {
118- throw new ErrorAsyncLocksLockBoxConflict (
119- `Lock ${ key } is already locked with class ${ lock . constructor . name } , which conflicts with class ${ LockConstructor . name } ` ,
120- ) ;
121- }
112+ const lockAcquire : ResourceAcquire < L > = async ( ) => {
113+ let lock = this . _locks . get ( key ) ;
114+ let lockRelease : ResourceRelease ;
115+ try {
116+ if ( lock == null ) {
117+ lock = new LockConstructor ( ) ;
118+ this . _locks . set ( key , lock ) ;
119+ } else {
120+ // It is possible to swap the lock class, but only after the lock key is released
121+ if ( ! ( lock instanceof LockConstructor ) ) {
122+ throw new ErrorAsyncLocksLockBoxConflict (
123+ `Lock ${ key } is already locked with class ${ lock . constructor . name } , which conflicts with class ${ LockConstructor . name } ` ,
124+ ) ;
122125 }
123- const lockAcquire = lock . lock ( ...lockingParams ) ;
124- [ lockRelease ] = await lockAcquire ( ) ;
125- } catch ( e ) {
126+ }
127+ const lockAcquire = lock . lock ( ...lockingParams ) ;
128+ [ lockRelease ] = await lockAcquire ( ) ;
129+ } catch ( e ) {
130+ // If it is still locked, then it is held by a different context
131+ // only delete if no contexts are locking the lock
132+ if ( ! lock ! . isLocked ( ) ) {
133+ this . _locks . delete ( key ) ;
134+ }
135+ throw e ;
136+ }
137+ let released = false ;
138+ return [
139+ async ( ) => {
140+ if ( released ) return ;
141+ released = true ;
142+ await lockRelease ( ) ;
126143 // If it is still locked, then it is held by a different context
127144 // only delete if no contexts are locking the lock
128145 if ( ! lock ! . isLocked ( ) ) {
129146 this . _locks . delete ( key ) ;
130147 }
131- throw e ;
132- }
133- let released = false ;
134- return [
135- async ( ) => {
136- if ( released ) return ;
137- released = true ;
138- await lockRelease ( ) ;
139- // If it is still locked, then it is held by a different context
140- // only delete if no contexts are locking the lock
141- if ( ! lock ! . isLocked ( ) ) {
142- this . _locks . delete ( key ) ;
143- }
144- } ,
145- lock ,
146- ] ;
147- } ,
148- ] ) ;
148+ } ,
149+ lock ,
150+ ] ;
151+ } ;
152+ lockAcquires . push ( [ keyOrig , lockAcquire , ...lockingParams ] ) ;
149153 }
150154 return lockAcquires ;
151155 }
@@ -194,71 +198,72 @@ class LockBox<L extends Lockable = Lockable> implements Lockable {
194198
195199 public async withF < T > (
196200 ...params : [
197- ...requests : Array < LockRequest < L > > ,
201+ ...requests : Array < MultiLockRequest < L > > ,
198202 f : ( lockBox : LockBox < L > ) => Promise < T > ,
199203 ]
200204 ) : Promise < T > {
201205 const f = params . pop ( ) as ( lockBox : LockBox < L > ) => Promise < T > ;
202206 return withF (
203- [ this . lock ( ...( params as Array < LockRequest < L > > ) ) ] ,
207+ [ this . lock ( ...( params as Array < MultiLockRequest < L > > ) ) ] ,
204208 ( [ lockBox ] ) => f ( lockBox ) ,
205209 ) ;
206210 }
207211
208212 public async withMultiF < T > (
209213 ...params : [
210- ...requests : Array < LockRequest < L > > ,
211- f : ( multiLocks : Array < [ ToString , L ] > ) => Promise < T > ,
214+ ...requests : Array < MultiLockRequest < L > > ,
215+ f : ( multiLocks : Array < MultiLockAcquired < L > > ) => Promise < T > ,
212216 ]
213217 ) : Promise < T > {
214- const f = params . pop ( ) as ( multiLocks : Array < [ ToString , L ] > ) => Promise < T > ;
215- const lockAcquires = this . lockMulti ( ...( params as Array < LockRequest < L > > ) ) ;
216- const lockAcquires_ : Array < ResourceAcquire < [ ToString , L ] > > =
218+ const f = params . pop ( ) as ( multiLocks : Array < MultiLockAcquired < L > > ) => Promise < T > ;
219+ const lockAcquires = this . lockMulti ( ...( params as Array < MultiLockRequest < L > > ) ) ;
220+
221+ const lockAcquires_ : Array < ResourceAcquire < MultiLockAcquired < L > > > =
217222 lockAcquires . map (
218- ( [ key , lockAcquire ] ) =>
223+ ( [ key , lockAcquire , ... lockingParams ] ) =>
219224 ( ...r ) =>
220225 lockAcquire ( ...r ) . then (
221226 ( [ lockRelease , lock ] ) =>
222- [ lockRelease , [ key , lock ] ] as [ ResourceRelease , [ ToString , L ] ] ,
227+ [ lockRelease , [ key , lock , ... lockingParams ] ] as [ ResourceRelease , MultiLockAcquired < L > ] ,
223228 ) ,
224229 ) ;
225230 return withF ( lockAcquires_ , f ) ;
226231 }
227232
228233 public withG < T , TReturn , TNext > (
229234 ...params : [
230- ...requests : Array < LockRequest < L > > ,
235+ ...requests : Array < MultiLockRequest < L > > ,
231236 g : ( lockBox : LockBox < L > ) => AsyncGenerator < T , TReturn , TNext > ,
232237 ]
233238 ) : AsyncGenerator < T , TReturn , TNext > {
234239 const g = params . pop ( ) as (
235240 lockBox : LockBox < L > ,
236241 ) => AsyncGenerator < T , TReturn , TNext > ;
237242 return withG (
238- [ this . lock ( ...( params as Array < LockRequest < L > > ) ) ] ,
243+ [ this . lock ( ...( params as Array < MultiLockRequest < L > > ) ) ] ,
239244 ( [ lockBox ] ) => g ( lockBox ) ,
240245 ) ;
241246 }
242247
243248 public withMultiG < T , TReturn , TNext > (
244249 ...params : [
245- ...requests : Array < LockRequest < L > > ,
250+ ...requests : Array < MultiLockRequest < L > > ,
246251 g : (
247- multiLocks : Array < [ ToString , L ] > ,
252+ multiLocks : Array < MultiLockAcquired < L > > ,
248253 ) => AsyncGenerator < T , TReturn , TNext > ,
249254 ]
250255 ) {
251256 const g = params . pop ( ) as (
252- multiLocks : Array < [ ToString , L ] > ,
257+ multiLocks : Array < MultiLockAcquired < L > > ,
253258 ) => AsyncGenerator < T , TReturn , TNext > ;
254- const lockAcquires = this . lockMulti ( ...( params as Array < LockRequest < L > > ) ) ;
255- const lockAcquires_ : Array < ResourceAcquire < [ ToString , L ] > > =
259+ const lockAcquires = this . lockMulti ( ...( params as Array < MultiLockRequest < L > > ) ) ;
260+ const lockAcquires_ : Array < ResourceAcquire < MultiLockAcquired < L > > > =
256261 lockAcquires . map (
257- ( [ key , lockAcquire ] ) =>
262+ ( [ key , lockAcquire , ... lockingParams ] ) =>
258263 ( ...r ) =>
259264 lockAcquire ( ...r ) . then (
260265 ( [ lockRelease , lock ] ) =>
261- [ lockRelease , [ key , lock ] ] as [ ResourceRelease , [ ToString , L ] ] ,
266+ [ lockRelease , [ key , lock , ... lockingParams ] ] as [ ResourceRelease , MultiLockAcquired < L > ] ,
262267 ) ,
263268 ) ;
264269 return withG ( lockAcquires_ , g ) ;
0 commit comments