Skip to content

Commit 01f5d85

Browse files
Merge pull request #2 from knowledgecode/develop
Add waitLeave and isLocked methods
2 parents f0eece1 + f7dccc9 commit 01f5d85

5 files changed

Lines changed: 439 additions & 184 deletions

File tree

README.md

Lines changed: 84 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ await criticalSection.enter(window);
2424
- **🎯 Object-centric design**: Your domain objects become the locks themselves
2525
- **🧠 Intuitive mental model**: One object = one critical section, naturally aligned with OOP
2626
- **♻️ Automatic cleanup**: WeakMap prevents memory leaks through garbage collection
27-
- **⚡ Lightweight**: Just 3 methods - `enter()`, `tryEnter()`, `leave()`
27+
- **⚡ Lightweight**: Just 5 methods - `enter()`, `tryEnter()`, `waitLeave()`, `isLocked()`, `leave()`
2828
- **🌐 Universal**: Works in Node.js, browsers, and all modern JavaScript environments
2929
- **🔒 Type-safe**: Full TypeScript support with strict type checking
3030
- **📦 Zero dependencies**: No external runtime dependencies
@@ -128,7 +128,7 @@ Attempts to enter a critical section immediately without waiting.
128128

129129
**Returns:**
130130

131-
- `boolean` - `true` if successfully entered, `false` if already occupied
131+
- `boolean` - `true` if successfully entered, `false` if already locked
132132

133133
**Example:**
134134

@@ -142,6 +142,55 @@ if (criticalSection.tryEnter(myResource)) {
142142
}
143143
```
144144

145+
### `criticalSection.waitLeave(obj: object, timeout?: number): Promise<boolean>`
146+
147+
Waits for the critical section to be released without locking it. Unlike `enter()`, this method does not acquire the lock after waiting.
148+
149+
**Parameters:**
150+
151+
- `obj` - Any object to wait for
152+
- `timeout` (optional) - Maximum time to wait in milliseconds. If not provided, waits indefinitely
153+
154+
**Returns:**
155+
156+
- `Promise<boolean>` - Resolves to `true` when the critical section is released, `false` if timeout occurs
157+
158+
**Example:**
159+
160+
```typescript
161+
// Wait for resource to become available without locking it
162+
const released = await criticalSection.waitLeave(myResource, 2000);
163+
if (released) {
164+
// Resource is now available (but not locked by us)
165+
console.log('Resource is free');
166+
} else {
167+
// Timeout occurred
168+
console.log('Resource still busy after 2 seconds');
169+
}
170+
```
171+
172+
### `criticalSection.isLocked(obj: object): boolean`
173+
174+
Checks if the critical section for the specified object is currently locked.
175+
176+
**Parameters:**
177+
178+
- `obj` - The object to check
179+
180+
**Returns:**
181+
182+
- `boolean` - `true` if the critical section is locked, `false` otherwise
183+
184+
**Example:**
185+
186+
```typescript
187+
if (criticalSection.isLocked(myResource)) {
188+
console.log('Resource is currently locked');
189+
} else {
190+
console.log('Resource is available');
191+
}
192+
```
193+
145194
### `criticalSection.leave(obj: object): void`
146195

147196
Leaves the critical section for the given object, allowing queued entries to proceed.
@@ -305,6 +354,39 @@ printDocument('Report B');
305354
printDocument('Report C');
306355
```
307356

357+
### Monitoring Resource Availability
358+
359+
```typescript
360+
const sharedCache = { name: 'user-cache' };
361+
362+
// Wait for cache to be free before doing cleanup
363+
async function cleanupCache() {
364+
console.log('Waiting for cache to be released...');
365+
366+
// Wait without locking - other operations can still use the cache
367+
const released = await criticalSection.waitLeave(sharedCache, 5000);
368+
369+
if (released) {
370+
// Now we can safely check or perform non-critical operations
371+
if (!criticalSection.isLocked(sharedCache)) {
372+
console.log('Cache is free, starting cleanup...');
373+
// Perform cleanup operations
374+
}
375+
} else {
376+
console.log('Cache is still busy, will retry later');
377+
}
378+
}
379+
380+
// Check status without affecting the lock
381+
function getCacheStatus() {
382+
if (criticalSection.isLocked(sharedCache)) {
383+
return 'Cache is currently in use';
384+
} else {
385+
return 'Cache is available';
386+
}
387+
}
388+
```
389+
308390
## How It Works
309391

310392
Uses a `WeakMap` to associate objects with their critical section state. Different objects = independent locks. When objects are garbage collected, their critical section state is automatically cleaned up.

0 commit comments

Comments
 (0)