Last active
June 3, 2023 12:01
-
-
Save SwadicalRag/ad637b1f6105c5a0b8b43e7900a5e5aa to your computer and use it in GitHub Desktop.
Two way weak map in TypeScript
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class TwoWayWeakMap { | |
constructor() { | |
this.keyToValue = new WeakMap(); | |
this.valueToKey = new WeakMap(); | |
this.keys = new Set(); | |
this.values = new Set(); | |
} | |
set(key, value) { | |
const weakValue = new WeakRef(value); | |
const weakKey = new WeakRef(key); | |
this.keyToValue.set(key, weakValue); | |
this.valueToKey.set(value, weakKey); | |
this.keys.add(new WeakRef(key)); | |
this.values.add(new WeakRef(value)); | |
} | |
getValue(key) { | |
const weakValue = this.keyToValue.get(key); | |
if (!weakValue) { | |
return undefined; | |
} | |
const value = weakValue.deref(); | |
if (!value) { | |
this.keyToValue.delete(key); | |
this.cleanup(); | |
} | |
return value; | |
} | |
getKey(value) { | |
const weakKey = this.valueToKey.get(value); | |
if (!weakKey) { | |
return undefined; | |
} | |
const key = weakKey.deref(); | |
if (!key) { | |
this.valueToKey.delete(value); | |
this.cleanup(); | |
} | |
return key; | |
} | |
cleanupRefs(refSet) { | |
for (let ref of refSet) { | |
if (ref.deref() === undefined) { | |
refSet.delete(ref); | |
} | |
} | |
} | |
cleanup() { | |
this.cleanupRefs(this.keys); | |
this.cleanupRefs(this.values); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class TwoWayWeakMap<K extends object, V extends object> { | |
private keyToValue: WeakMap<K, WeakRef<V>>; | |
private valueToKey: WeakMap<V, WeakRef<K>>; | |
private keys: Set<WeakRef<K>>; | |
private values: Set<WeakRef<V>>; | |
constructor() { | |
this.keyToValue = new WeakMap<K, WeakRef<V>>(); | |
this.valueToKey = new WeakMap<V, WeakRef<K>>(); | |
this.keys = new Set<WeakRef<K>>(); | |
this.values = new Set<WeakRef<V>>(); | |
} | |
set(key: K, value: V): void { | |
const weakValue = new WeakRef<V>(value); | |
const weakKey = new WeakRef<K>(key); | |
this.keyToValue.set(key, weakValue); | |
this.valueToKey.set(value, weakKey); | |
this.keys.add(new WeakRef<K>(key)); | |
this.values.add(new WeakRef<V>(value)); | |
} | |
getValue(key: K): V | undefined { | |
const weakValue = this.keyToValue.get(key); | |
if (!weakValue) { | |
return undefined; | |
} | |
const value = weakValue.deref(); | |
if (!value) { | |
this.keyToValue.delete(key); | |
this.cleanup(); | |
} | |
return value; | |
} | |
getKey(value: V): K | undefined { | |
const weakKey = this.valueToKey.get(value); | |
if (!weakKey) { | |
return undefined; | |
} | |
const key = weakKey.deref(); | |
if (!key) { | |
this.valueToKey.delete(value); | |
this.cleanup(); | |
} | |
return key; | |
} | |
private cleanupRefs(refSet: Set<WeakRef<K | V>>): void { | |
for (let ref of refSet) { | |
if (ref.deref() === undefined) { | |
refSet.delete(ref); | |
} | |
} | |
} | |
cleanup(): void { | |
this.cleanupRefs(this.keys); | |
this.cleanupRefs(this.values); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment