2019-03-26 23:35:08 +01:00
Garbage collector interface
===========================
2019-03-27 17:21:52 +01:00
A garbage collector for AssemblyScript must implement the following common and either the tracing or reference counting interfaces:
2019-03-26 23:35:08 +01:00
Common
------
2019-03-27 17:41:06 +01:00
* **__ref_collect**(): `void` < br />
2019-03-27 14:43:35 +01:00
Triggers a full garbage collection cycle. Also indicates the presence of a GC.
2019-03-26 23:35:08 +01:00
Tracing
-------
2019-03-27 17:41:06 +01:00
* **__ref_register**(ref: `usize` ): `void` < br />
2019-03-26 23:35:08 +01:00
Sets up a new reference.
2019-03-27 17:41:06 +01:00
* **__ref_link**(ref: `usize` , parentRef: `usize` ): `void` < br />
2019-03-26 23:35:08 +01:00
Links a reference to a parent that is now referencing it.
2019-03-27 17:41:06 +01:00
* **__ref_unlink**(ref: `usize` , parentRef: `usize` ): `void` < br />
2019-03-29 18:56:32 +01:00
Unlinks a reference from a parent that was referencing it. Implementation is optional.
2019-03-26 23:35:08 +01:00
2019-04-02 10:12:57 +02:00
* **__ref_mark**(ref: `usize` ): `void` < br />
Marks a reference as being reachable so it doesn't become sweeped.
2019-03-26 23:35:08 +01:00
Reference counting
------------------
2019-03-27 17:41:06 +01:00
* **__ref_register**(ref: `usize` ): `void` < br />
2019-03-29 18:56:32 +01:00
Sets up a new reference. Implementation is optional.
2019-03-27 14:43:35 +01:00
2019-03-27 17:41:06 +01:00
* **__ref_retain**(ref: `usize` ): `void` < br />
2019-03-26 23:35:08 +01:00
Retains a reference, usually incrementing RC.
2019-03-27 17:41:06 +01:00
* **__ref_release**(ref: `usize` ): `void` < br />
2019-03-26 23:35:08 +01:00
Releases a reference, usually decrementing RC.
Typical patterns
----------------
Standard library components make use of the interface where managed references are stored or deleted. Common patterns are:
### General
```ts
/// < reference path = "./collector/index.d.ts" / >
if (isManaged< T > ()) {
// compiled only if T is a managed reference
... pattern ...
}
```
### Insertion
```ts
if (isNullable< T > ()) {
if (ref) {
if (isDefined(__ref_link)) __ref_link(ref, parentRef);
else if (isDefined(__ref_retain)) __ref_retain(ref);
else assert(false);
}
} else {
if (isDefined(__ref_link)) __ref_link(ref, parentRef);
else if (isDefined(__ref_retain)) __ref_retain(ref);
else assert(false);
}
```
### Replacement
```ts
if (ref !== oldRef) {
if (isNullable< T > ()) {
if (isDefined(__ref_link)) {
2019-03-29 18:56:32 +01:00
if (isDefined(__ref_unlink)) if (oldRef) __ref_unlink(oldRef, parentRef);
2019-03-26 23:35:08 +01:00
if (ref) __ref_link(ref, parentRef);
} else if (isDefined(__ref_retain)) {
if (oldRef) __ref_release(oldRef);
if (ref) __ref_retain(ref);
} else assert(false);
} else {
if (isDefined(__ref_link)) {
2019-03-29 18:56:32 +01:00
if (isDefined(__ref_unlink)) if (oldRef) __ref_unlink(oldRef, parentRef); // *
2019-03-26 23:35:08 +01:00
__ref_link(ref, parentRef);
} else if (isDefined(__ref_retain)) {
2019-03-27 17:41:06 +01:00
if (oldRef) __ref_release(oldRef); // *
2019-03-26 23:35:08 +01:00
__ref_retain(ref);
} else assert(false);
}
}
```
### Deletion
```ts
if (isNullable< T > ()) {
if (ref) {
2019-03-29 18:56:32 +01:00
if (isDefined(__ref_link)) {
if (isDefined(__ref_unlink)) __ref_unlink(ref, parentRef);
} else if (isDefined(__ref_retain)) __ref_release(ref);
2019-03-26 23:35:08 +01:00
else assert(false);
}
} else {
2019-03-29 18:56:32 +01:00
if (isDefined(__ref_link)) {
if (isDefined(__ref_unlink)) __ref_unlink(ref, parentRef);
} else if (isDefined(__ref_retain)) __ref_release(ref);
2019-03-26 23:35:08 +01:00
else assert(false);
}
```
2019-03-27 17:41:06 +01:00
(*) Note that some data structures may contain `null` values even though the value type isn't nullable. May be the case when appending a new element to an array for example.