Non-GC threads
Version | 1 |
Created | 2012-09-01 |
Status | Draft |
Last modified | 2012-09-01 |
Author | Piotr Szturmaj |
Abstract
The proposal is to create a base for safe, non garbage-collected threads. This is done by adding nogc attribute for functions. nogc functions cannot perform operations that may allocate garbage collected memory. They are covariant with gc ones.
Rationale
Currently, all functions can use garbage collected memory. Threads that call those functions must be managed by the garbage collector, which may occasionally suspend them to perform collection. This can lead to unwanted pauses, that are not acceptable in some situations, mainly real-time audio/video processing, gaming, and others. Rather than relying on particular (concurrent) implementation of the GC, or resorting to unsafe solutions, a language-level guarantee is proposed. Guarantee is that threads that spawn nogc functions will not be suspended during their execution.
It’s possible to create non-gc threads now, but current practices are unsafe and error prone. For example, one must check the code of all called functions to see if they don’t perform GC allocations. In this proposal, compiler guarantees that functions don’t allocate GC memory. This is similar to nothrow and pure handling. Compiler guarantees that pure functions can’t call impure ones, and nothrow functions can’t call throwing ones.
Description
Functions can be marked with nogc attribute, similarly to nothrow or pure marking. Nogc functions can’t perform operations listed here (D Operations That Involve the Garbage Collector). That is, they can’t do:
- NewExpression
- Array appending
- Array concatenation
- Array literals (except when used to initialize static data)
- Associative array literals
- Any insertion, removal, or lookups in an associative array
- Extracting keys or values from an associative array
- Taking the address of (i.e. making a delegate) a nested function that accesses variables in an outer scope
- A function literal that access variables in an outer scope
- An AssertExpression? that fails its condition
void func() nogc
{
auto ptr = malloc(4096); // ok
auto instance = new SomeClass(); // Error: nogc functions can't allocate using new
}
Nogc functions are statically checked by the compiler. If at least one of the operations listed above is used, this results in a compilation error.
Functions not marked with nogc attribute are called “gc” functions. All gc functions can call nongc functions, but nongc functions can’t call gc ones. This is analogous to pure and nothrow behavior. Compiler should infer nogc attribute automatically for matching functions, while explicit nogc attribute will force non-gc check on programmer’s demand.
Nogc functions are handled differently when they’re used to spawn threads:
Newly created thread is not added to the GC’s thread list. This way it’s never suspended. If some of the function’s arguments take references (directly or indirectly), then all of them are automatically added to the list of GC roots (addRoot()). It is possible to mark entry-point functions with nogc:
void main() nogc
{
}
This way entire program is guaranteed to not use GC at all (given that no static module constructors use GC). Code of the garbage collector doesn’t need to be linked, leading to smaller executables. This is also useful for writing programs that run in constrained environments, for example kernel-mode drivers or embedded/microcontroller software.
After all, users can benefit from proper modules, templates, clean syntax and other nice features of D, without using garbage collector.
Copyright
This document has been placed in the Public Domain.