]> git.saurik.com Git - logizomai.git/commitdiff
Fold FutureSet into ResourceSet and add FutureSet.
authorJay Freeman (saurik) <saurik@saurik.com>
Tue, 24 Oct 2017 06:40:42 +0000 (23:40 -0700)
committerJay Freeman (saurik) <saurik@saurik.com>
Tue, 24 Oct 2017 06:40:42 +0000 (23:40 -0700)
lib/index.ts

index 4b875d4c0e81a16cda23041f5a65091fc9564f9e..d19a05af1e73a1cfb0d7fbb78f75843fd060cfe1 100644 (file)
@@ -99,14 +99,42 @@ export function using<Type extends Resource, Value>(resource: Type, code: (resou
     }
 }
 
+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();
     }
@@ -117,10 +145,22 @@ export class ResourceSet<Value extends Resource> extends Resource {
         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 :/
@@ -128,6 +168,13 @@ export class ResourceSet<Value extends Resource> extends Resource {
             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;
     }
 
@@ -151,18 +198,25 @@ export class ResourceSet<Value extends Resource> extends Resource {
     }
 }
 
-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;
@@ -171,33 +225,33 @@ export class FutureSet<Value extends Resource> extends ResourceSet<Value> {
                 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]();
     }
 }