Compilation Options

(Note that wherever "MiniD" is mentioned, it's mostly referring to "the reference D implementation of MiniD, the library" and not to the language. The language doesn't really have any restrictions.)

MiniD provides some options that you can use to enable or disable certain features for purposes of library size, D heap allocation, and extra features.

Readline Support (Posix systems only)

libreadline is a popular library for console input on Posix-compliant systems. It, along with libhistory, support input history and other fun things.

If you want the minid.commandline module to support libreadline, define the MDReadline version when compiling, and also link to libreadline and libhistory.

If you don't feel like bothering with that, though, there's always rlwrap, which is pretty awesome.

Coroutine Support

MiniD has two levels of coroutine support: normal and extended.

Normal coroutine support is the default. In this mode, you may only create coroutines using MiniD (script) functions as the coroutine bodies. Yielding is restricted in that a coroutine may only yield if there are no native calls or metamethod calls on the call stack of that coroutine. The yield native API function is also absent.

Extended coroutine support removes all yielding restrictions and allows you to create coroutines with script or native functions as their bodies.

The reason for the two levels of support is due to the fact that in order to lift the restrictions imposed by normal mode, native coroutine objects (the tango.core.Thread.Fiber class) must be created. This involves performing a D heap allocation, which may not be desirable, as this could trigger a GC cycle in the host application (which, in a real-time application like a game, might not be acceptable).

For those who don't want their scripts triggering GC cycles in the host at all, the normal option is the way to go.

For those who don't mind the extra allocations, or who really need to be able to yield anywhere or to create native coroutines, the extended coroutine mode is the most flexible, at the cost of allocating a native coroutine object for every MiniD coroutine.

A word on performance: when native coroutine objects are used, yielding and resuming are slightly slower than when the script coroutine support is used. However, this is a tiny, tiny fraction of the time that will be spent executing your code. The amount of time used to execute the body of the coroutine will likely far exceed the slight loss of performance due to the slower yields and resumes. Even using native coroutine objects, MiniD still beats most other languages in the cheap-concurrency benchmark from the Great Computer Language Shootout. (well, at least when that benchmark existed, it did.)

Using native coroutine objects also uses a bit more memory. Each object consumes around 16 extra KB, though this is something that can (note: will) be able to be set by the user of the library.

Something to keep in mind when using native coroutines, however, is the call depth limitation. Due to current limitations in Tango's Fiber implementation, the stack size of a Fiber (and incidentally, a coroutine) is limited, and going too deep will result in a stack overflow instead of the stack growing to accommodate. There has been talk of fixing this, but until that happens, you will be stuck with a fixed stack size for each coroutine, and if you need more, you'll have to increase the fixed stack size.

If you want to use extended mode, define the MDExtendedCoro version. If you don't define it, normal coroutine mode will be used. You can find out what version is being compiled by checking the minid.types.MDCoroSupport constant; this is a string containing "Normal" or "Extended".

Fiber Pooling

If you use the MDExtendedCoro version, you can also optionally define the MDPoolFibers version. If this is defined, any Fiber objects that are created by coroutines are put into a pool when the coroutine object is collected, so that the fiber object can be reused. This means that the Fiber objects that are allocated on the D heap are never deallocated, but with the benefit that if you create and destroy a lot of coroutines, it'll be less work for the D GC, since it won't be constantly collecting Fibers only to have new ones allocated soon after.

Memory Leak Detector

The MiniD implementation is probably not perfect. If you notice your app's memory usage mysteriously creeping up and you've determined that it's not your code, it might be MiniD. You can define the debug version LEAK_DETECTOR (with i.e. the "-debug=LEAK_DETECTOR" compiler switch to DMD) to turn on MiniD's memory leak detector. This will keep track of the size and type of every memory block that is allocated and deallocated by the MiniD GC, and when the VM is closed (this is important - the leak detection is performed in the closeVM function), if there are any stray blocks that are not collected by the GC, they are reported on stdout and an exception is thrown. I used this when developing MiniD and found it immensely helpful. In addition, turning on this debug version will also check that no double-frees or frees of non-MiniD-allocated memory are performed (which sometimes happened during the course of development of the compiler).