1
1
import 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' ;
3
9
import { withF , withG } from '@matrixai/resources' ;
4
10
import { ErrorAsyncLocksLockBoxConflict } from './errors' ;
5
11
6
12
class LockBox < L extends Lockable = Lockable > implements Lockable {
7
13
protected _locks : Map < string , L > = new Map ( ) ;
8
14
9
- public lock ( ...requests : Array < LockRequest < L > > ) : ResourceAcquire < LockBox < L > > {
15
+ public lock ( ...requests : Array < MultiLockRequest < L > > ) : ResourceAcquire < LockBox < L > > {
10
16
return async ( ) => {
11
17
// Convert to strings
12
18
// This creates a copy of the requests
@@ -79,8 +85,8 @@ class LockBox<L extends Lockable = Lockable> implements Lockable {
79
85
}
80
86
81
87
public lockMulti (
82
- ...requests : Array < LockRequest < L > >
83
- ) : Array < [ ToString , ResourceAcquire < L > ] > {
88
+ ...requests : Array < MultiLockRequest < L > >
89
+ ) : Array < MultiLockAcquire < L > > {
84
90
// Convert to strings
85
91
// This creates a copy of the requests
86
92
let requests_ : Array <
@@ -101,51 +107,49 @@ class LockBox<L extends Lockable = Lockable> implements Lockable {
101
107
requests_ = requests_ . filter (
102
108
( [ key ] , i , arr ) => i === 0 || key !== arr [ i - 1 ] [ 0 ] ,
103
109
) ;
104
- const lockAcquires : Array < [ ToString , ResourceAcquire < L > ] > = [ ] ;
110
+ const lockAcquires : Array < MultiLockAcquire < L > > = [ ] ;
105
111
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
+ ) ;
122
125
}
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 ( ) ;
126
143
// If it is still locked, then it is held by a different context
127
144
// only delete if no contexts are locking the lock
128
145
if ( ! lock ! . isLocked ( ) ) {
129
146
this . _locks . delete ( key ) ;
130
147
}
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 ] ) ;
149
153
}
150
154
return lockAcquires ;
151
155
}
@@ -194,71 +198,72 @@ class LockBox<L extends Lockable = Lockable> implements Lockable {
194
198
195
199
public async withF < T > (
196
200
...params : [
197
- ...requests : Array < LockRequest < L > > ,
201
+ ...requests : Array < MultiLockRequest < L > > ,
198
202
f : ( lockBox : LockBox < L > ) => Promise < T > ,
199
203
]
200
204
) : Promise < T > {
201
205
const f = params . pop ( ) as ( lockBox : LockBox < L > ) => Promise < T > ;
202
206
return withF (
203
- [ this . lock ( ...( params as Array < LockRequest < L > > ) ) ] ,
207
+ [ this . lock ( ...( params as Array < MultiLockRequest < L > > ) ) ] ,
204
208
( [ lockBox ] ) => f ( lockBox ) ,
205
209
) ;
206
210
}
207
211
208
212
public async withMultiF < T > (
209
213
...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 > ,
212
216
]
213
217
) : 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 > > > =
217
222
lockAcquires . map (
218
- ( [ key , lockAcquire ] ) =>
223
+ ( [ key , lockAcquire , ... lockingParams ] ) =>
219
224
( ...r ) =>
220
225
lockAcquire ( ...r ) . then (
221
226
( [ lockRelease , lock ] ) =>
222
- [ lockRelease , [ key , lock ] ] as [ ResourceRelease , [ ToString , L ] ] ,
227
+ [ lockRelease , [ key , lock , ... lockingParams ] ] as [ ResourceRelease , MultiLockAcquired < L > ] ,
223
228
) ,
224
229
) ;
225
230
return withF ( lockAcquires_ , f ) ;
226
231
}
227
232
228
233
public withG < T , TReturn , TNext > (
229
234
...params : [
230
- ...requests : Array < LockRequest < L > > ,
235
+ ...requests : Array < MultiLockRequest < L > > ,
231
236
g : ( lockBox : LockBox < L > ) => AsyncGenerator < T , TReturn , TNext > ,
232
237
]
233
238
) : AsyncGenerator < T , TReturn , TNext > {
234
239
const g = params . pop ( ) as (
235
240
lockBox : LockBox < L > ,
236
241
) => AsyncGenerator < T , TReturn , TNext > ;
237
242
return withG (
238
- [ this . lock ( ...( params as Array < LockRequest < L > > ) ) ] ,
243
+ [ this . lock ( ...( params as Array < MultiLockRequest < L > > ) ) ] ,
239
244
( [ lockBox ] ) => g ( lockBox ) ,
240
245
) ;
241
246
}
242
247
243
248
public withMultiG < T , TReturn , TNext > (
244
249
...params : [
245
- ...requests : Array < LockRequest < L > > ,
250
+ ...requests : Array < MultiLockRequest < L > > ,
246
251
g : (
247
- multiLocks : Array < [ ToString , L ] > ,
252
+ multiLocks : Array < MultiLockAcquired < L > > ,
248
253
) => AsyncGenerator < T , TReturn , TNext > ,
249
254
]
250
255
) {
251
256
const g = params . pop ( ) as (
252
- multiLocks : Array < [ ToString , L ] > ,
257
+ multiLocks : Array < MultiLockAcquired < L > > ,
253
258
) => 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 > > > =
256
261
lockAcquires . map (
257
- ( [ key , lockAcquire ] ) =>
262
+ ( [ key , lockAcquire , ... lockingParams ] ) =>
258
263
( ...r ) =>
259
264
lockAcquire ( ...r ) . then (
260
265
( [ lockRelease , lock ] ) =>
261
- [ lockRelease , [ key , lock ] ] as [ ResourceRelease , [ ToString , L ] ] ,
266
+ [ lockRelease , [ key , lock , ... lockingParams ] ] as [ ResourceRelease , MultiLockAcquired < L > ] ,
262
267
) ,
263
268
) ;
264
269
return withG ( lockAcquires_ , g ) ;
0 commit comments