Skip to content

Commit

Permalink
add Recyclable!
Browse files Browse the repository at this point in the history
  • Loading branch information
yilabs committed Nov 14, 2022
1 parent 5882a8e commit 987b75d
Showing 1 changed file with 69 additions and 1 deletion.
70 changes: 69 additions & 1 deletion source/jdiutil/memory.d
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
module jdiutil.memory;

import core.memory;

import std.exception;
import std.experimental.logger;
import std.stdio;
import std.traits;

version (unittest) {
import fluent.asserts;
public import fluent.asserts;
}

public import jdiutil.jdiutil;
Expand Down Expand Up @@ -137,6 +139,72 @@ unittest {

}

/* ========================================================================== *\
object pool
\* ========================================================================== */
const int EACH_WAIT_MILLISECONDS = 100;

// allocate an array of T at init, and recycle the object to reduce memory usage
// TODO: add linked-list for size unbounded pool
template Recyclable(T) {
static if (is(T == struct)) {
alias RefT = T*;
} else {
alias RefT = T;
}

// https://issues.dlang.org/show_bug.cgi?id=20838#c12
// manually take care of required 16-bytes alignment: for cas(CMPXCHG16B)
public align(16) shared bool taken; // core.atomic.cas to select free one to use

static __gshared T[] pool;

static void initObjectPool(long size) {
pool = new T[size]; // why in actual run, we need more than numWorkerThreads?

static if (is(T == class)) { // TODO: heapAllocN
foreach (i; 0 .. size) {
pool[i] = new T();
}
}
}

static RefT make(int wait=int.max) { // how many times should wait, by default will wait
enforce(pool.length > 0);
for (;;) {
foreach (ref nd; pool) { // loop on the pool array
if (core.atomic.cas(&(nd.taken), false, true)) { // atomic op!
enforce(nd.taken);
static if (is(T == struct)) {
return &nd;
} else {
return nd;
}
}
}

if (wait-- > 0) {
Thread.sleep(dur!("msecs")(EACH_WAIT_MILLISECONDS));
} else {
return null;
}
}
return null;
}

}

// release the object, and put back into the recycle bin
void recycle(T)(T needleDev) {
if (needleDev is null) {
return;
}
bool released = (core.atomic.cas(&(needleDev.taken), true, false)); // atomic op!
enforce(released);
}



/* ========================================================================== *\
\* ========================================================================== */
// from: https://forum.dlang.org/post/acafsosotrjdswwuklob@forum.dlang.org
Expand Down

0 comments on commit 987b75d

Please sign in to comment.