Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add comment-documentation for several key Theia utility classes #13324

Merged
merged 5 commits into from
Feb 5, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions packages/core/src/common/disposable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,29 @@ Object.defineProperty(Disposable, 'NULL', {
}
});

/**
* Utility for tracking a collection of Disposable objects, specifically for
* the sake of finding out when all items in the collection have been disposed.
martin-fleck-at marked this conversation as resolved.
Show resolved Hide resolved
*
* ```
* const dc = new DisposableCollection(myDisposables);
* dc.onDispose(() => {
* console.log('All elements in the collection have been disposed');
martin-fleck-at marked this conversation as resolved.
Show resolved Hide resolved
* });
* ```
*
* You can add any number of Disposables to the collection at any time. You
* cannot query the contents of the collection. An element is automatically
* pruned from the collection when it is disposed.
*
* The collection will notify only once. It will continue to function
martin-fleck-at marked this conversation as resolved.
Show resolved Hide resolved
* in so far as accepting new Disposables and pruning them when they
* are disposed, but such activity will never result in another
* notification.
*
* Calling dispose() on the collection disposes all its elements. A notification
* is sent (if no notification was previously sent).
martin-fleck-at marked this conversation as resolved.
Show resolved Hide resolved
*/
martin-fleck-at marked this conversation as resolved.
Show resolved Hide resolved
export class DisposableCollection implements Disposable {

protected readonly disposables: Disposable[] = [];
Expand Down
55 changes: 55 additions & 0 deletions packages/core/src/common/reference.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,50 @@ export interface Reference<T> extends Disposable {
readonly object: T
}

/**
* Abstract class for a map of reference-counted disposable objects, with the
* following features:
*
* - values are not inserted explicitly; instead, acquire() is used to
* create the value for a given key, or return the previously created
* value for it. How the value is created for a given key is
* implementation specific.
*
* - any subsquent acquire() with the same key will bump the reference
* count on that value. acquire() returns not the value directly but
* a reference object that holds the value. Calling dispose() on the
* reference decreases the value's effective reference count.
*
* - a contained value will have its dispose() function called when its
* reference count reaches zero. The key/value pair will be purged
* from the collection.
*
* - calling dispose() on the value directly, instead of calling it on
* the reference returned by acquire(), will automatically dispose
* all outstanding references to that value and the key/value pair
* will be purged from the collection.
*
* - supports synchronous and asynchronous implementations. acquire() will
* return a Promise if the value cannot be created immediately
*
* - functions has|keys|values|get are always synchronous and the result
* excludes asynchronous additions in flight.
*
* - functions values|get return the value directly and not a reference
* to the value. Use these functions to obtain a value without bumping
* its reference count.
*
* - clients can register to be notified when values are added and removed;
* notification for asynchronous additions happen when the creation
* completes, not when it's requested.
*
* - keys can be any value/object that can be successfully stringified using
* JSON.stringify(), sans arguments
*
* - calling dispose() on the collection will dispose all outstanding
* references to all contained values, which results in the disposal of
* the values themselves.
*/
export abstract class AbstractReferenceCollection<K, V extends Disposable> implements Disposable {

protected readonly _keys = new Map<string, K>();
Expand Down Expand Up @@ -108,6 +152,12 @@ export abstract class AbstractReferenceCollection<K, V extends Disposable> imple

}

/**
* Asynchronous implementation of AbstractReferenceCollection that requires
* the client to provide a value factory, used to service the acquire()
* function. That factory may return a Promise if the value cannot be
* created immediately.
*/
export class ReferenceCollection<K, V extends Disposable> extends AbstractReferenceCollection<K, V> {

constructor(protected readonly factory: (key: K) => MaybePromise<V>) {
Expand Down Expand Up @@ -148,6 +198,11 @@ export class ReferenceCollection<K, V extends Disposable> extends AbstractRefere

}

/**
* Synchronous implementation of AbstractReferenceCollection that requires
* the client to provide a value factory, used to service the acquire()
* function.
*/
export class SyncReferenceCollection<K, V extends Disposable> extends AbstractReferenceCollection<K, V> {

constructor(protected readonly factory: (key: K) => V) {
Expand Down
Loading