Skip to content

Instantly share code, notes, and snippets.

@eatnumber1
Created July 31, 2011 05:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save eatnumber1/1116445 to your computer and use it in GitHub Desktop.
Save eatnumber1/1116445 to your computer and use it in GitHub Desktop.
D Runtime Initialization Routine Wrapper
import core.atomic;
import core.runtime;
import core.sync.mutex;
version( Windows ) {
import core.stdc.stdlib;
} else version( Posix ) {
import core.sys.posix.stdlib;
} else {
static assert(false, "Unknown platform");
}
shared int calls = 0;
shared Mutex initLock = null;
private Mutex newLock() {
auto ci = Mutex.classinfo;
auto ptr = malloc(ci.init.length);
if( ptr is null ) return null;
(cast(byte*) ptr)[0..ci.init.length] = ci.init[];
auto mutex = cast(Mutex) ptr;
mutex.__ctor();
return mutex;
}
private void freeLock( Mutex lock ) {
lock.__dtor();
free(cast(void *) lock);
}
extern (C) {
bool init() {
Mutex mutex = newLock();
if( mutex is null ) return false;
if( initLock is null ) {
initLock = cast(shared) mutex;
} else
// This is necessary for proper operation, but I can't get it to compile...
//if( !cas(cast(shared(const(Mutex)*)) &initLock, cast(const) null, cast(const) mutex) )
freeLock(cast(Mutex) initLock);
bool ret;
synchronized( initLock ) {
ret = calls == 0 ? Runtime.initialize() : true;
calls++;
}
return ret;
}
bool terminate() {
assert(initLock !is null);
assert(calls >= 0);
bool destroyLock = false, ret;
synchronized( initLock ) {
if( calls == 0 ) {
ret = Runtime.terminate();
destroyLock = true;
} else {
ret = true;
}
calls--;
}
if( destroyLock ) freeLock(cast(Mutex) initLock);
return ret;
}
bool init2() {
return atomicOp!"+="(calls, 1) == 1 ? Runtime.initialize() : true;
}
bool terminate2() {
return atomicOp!"-="(calls, 1) == 0 ? Runtime.terminate() : true;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment