"shared" status
Ali Çehreli
acehreli at yahoo.com
Mon Apr 16 23:52:39 PDT 2012
On 04/16/2012 03:57 AM, Zardoz wrote:
> So, if I need to share a array of 0x10000 elements between 3 or more
> threads, how should do it ?
1) The following program starts four threads to fill different parts of
a shared array:
import std.stdio;
import std.concurrency;
import core.thread;
void numberFiller(shared(int)[] area, int fillValue)
{
foreach (ref number; area) {
number = fillValue;
}
}
void main()
{
enum totalNumbers = 0x10;
auto numbers = new shared(int)[totalNumbers];
enum totalThreads = 4;
enum numbersPerThread = totalNumbers / totalThreads;
foreach (i; 0 .. totalThreads) {
immutable start = i * numbersPerThread;
immutable fillValue = i;
spawn(&numberFiller,
numbers[start .. start + numbersPerThread],
cast(int)fillValue);
}
thread_joinAll();
writeln(numbers);
}
The output:
[0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3]
2) The program above is being careful to limit the threads to different
parts of the array. In other cases lock-based multi-threading can be
used. The following program allows four thread append to a single array
as they get a hold of the slice:
import std.stdio;
import std.concurrency;
import core.thread;
import std.random;
class Job
{
int[] * slice;
size_t count;
this(ref int[] slice, size_t count)
{
this.slice = &slice;
this.count = count;
}
}
void numberAppender(shared(Job) job, int appendValue)
{
foreach (i; 0 .. job.count) {
synchronized (job) {
*job.slice ~= appendValue;
}
Thread.sleep(dur!"msecs"(uniform(1,100)));
}
}
void main()
{
enum totalNumbers = 0x10;
int[] numbers;
enum totalThreads = 4;
enum numbersPerThread = totalNumbers / totalThreads;
auto job = new shared(Job)(numbers, numbersPerThread);
foreach (i; 0 .. totalThreads) {
int appendValue = i;
spawn(&numberAppender, job, appendValue);
}
thread_joinAll();
writeln(numbers);
}
The output should be similar to this:
[0, 1, 3, 2, 1, 1, 2, 0, 3, 1, 3, 0, 2, 3, 0, 2]
(Note: I wish there were 'ref' variables in D. That's why Job.slice
above had to be a pointer.)
3) Better than the two approaches above may be to use message passing
and have the threads produce separate results to be either combined
later or simply used separately:
import std.stdio;
import std.concurrency;
void arrayMaker(Tid owner, int count, int value)
{
immutable(int)[] result;
foreach (i; 0 .. count) {
result ~= value;
}
owner.send(result);
}
void main()
{
enum totalNumbers = 0x10;
enum totalThreads = 4;
enum numbersPerThread = totalNumbers / totalThreads;
foreach (i; 0 .. totalThreads) {
int value = i;
spawn(&arrayMaker, thisTid, numbersPerThread, value);
}
immutable(int[])[] results;
foreach (i; 0 .. totalThreads) {
auto result = receiveOnly!(immutable(int)[])();
results ~= result;
}
writeln(results);
}
The output should be similar to this:
[[0, 0, 0, 0], [1, 1, 1, 1], [3, 3, 3, 3], [2, 2, 2, 2]]
(Note: I could not pass the results as shared int slices so I went back
to immutable.)
Ali
More information about the Digitalmars-d-learn
mailing list