}
}
+interface Waitable<Value> {
+ size: number;
+ values(): IterableIterator<Value>;
+ waiters: Set<(value: Value | null) => void> | null;
+}
+
+function Get<Value>(set: Waitable<Value>, code?: () => void): Promise<Value> {
+ return new Promise<Value>((resolve, reject) => {
+ if (set.size !== 0)
+ resolve(set.values().next().value);
+ else {
+ if (set.waiters === null)
+ set.waiters = new Set<(value: Value | null) => void>();
+ set.waiters.add((value: Value | null) => {
+ if (value === null)
+ reject();
+ else
+ resolve(value);
+ });
+ if (code !== undefined)
+ code();
+ }
+ });
+}
+
export class ResourceSet<Value extends Resource> extends Resource {
private readonly set: Set<Value>;
+ public waiters: Set<(value: Value | null) => void> | null;
constructor() { super();
this.set = new Set<Value>();
+ this.waiters = null;
}
protected finalize(): void {
+ this.cancel();
this.clear();
super.finalize();
}
return this.set.clear();
}
+ public cancel(): void {
+ const waiters = this.waiters;
+ this.waiters = null;
+ if (waiters !== null)
+ for (const waiter of waiters)
+ waiter(null);
+ }
+
public has(value: Value): boolean {
return this.set.has(value);
}
+ public get(code?: () => void): Promise<Value> {
+ return Get(this, code);
+ }
+
public add(value: Value): this {
// .add() should return a boolean
// this is simply incompetence :/
value.retain();
this.set.add(value);
}
+
+ const waiters = this.waiters;
+ this.waiters = null;
+ if (waiters !== null)
+ for (const waiter of waiters)
+ waiter(value);
+
return this;
}
}
}
-export class FutureSet<Value extends Resource> extends ResourceSet<Value> {
- private waiters: Set<(value: Value | null) => void> | null;
+export class FutureSet<Value> extends Resource {
+ private readonly set: Set<Value>;
+ public waiters: Set<(value: Value | null) => void> | null;
constructor() { super();
+ this.set = new Set<Value>();
this.waiters = null;
}
protected finalize(): void {
this.cancel();
+ this.clear();
super.finalize();
}
+ public clear(): void {
+ return this.set.clear();
+ }
+
public cancel(): void {
const waiters = this.waiters;
this.waiters = null;
waiter(null);
}
+ public has(value: Value): boolean {
+ return this.set.has(value);
+ }
+
public get(code?: () => void): Promise<Value> {
- return new Promise<Value>((resolve, reject) => {
- if (this.size !== 0)
- resolve(this.values().next().value);
- else {
- if (this.waiters === null)
- this.waiters = new Set<(value: Value | null) => void>();
- this.waiters.add((value: Value | null) => {
- if (value === null)
- reject();
- else
- resolve(value);
- });
- if (code !== undefined)
- code();
- }
- });
+ return Get(this, code);
}
public add(value: Value): this {
- const result = super.add(value);
- const waiters = this.waiters;
- this.waiters = null;
- if (waiters !== null)
- for (const waiter of waiters)
- waiter(value);
- return result;
+ this.set.add(value);
+ return this;
+ }
+
+ public delete(value: Value): boolean {
+ return this.set.delete(value);
+ }
+
+ public values(): IterableIterator<Value> {
+ return this.set.values();
+ }
+
+ public get size(): number {
+ return this.set.size;
+ }
+
+ public [Symbol.iterator](): IterableIterator<Value> {
+ return this.set[Symbol.iterator]();
}
}