2016-03-26 7 views
3

У меня чертовски время, пытаясь заставить барьерную синхронизацию в D работать правильно. В настоящее время я не получаю ошибок компилятора, но каждый раз, когда он достигает барьера, я получаю ошибку сегментации. Вот в основном то, что у меня есть:Share Barrier через потоки в D

import std.stdio; 
import std.conv; 
import std.concurrency; 
import core.thread; 
import core.sync.barrier; 

//create barrier 
Barrier barrier; 

void the_thread() 
{ 
    barrier.wait(); //I get a segmentation fault here 
} 

void main(string[] args) 
{ 
    int threads = to!int(args[1]); //number of threads 

    //init barrier 
    barrier = new Barrier(threads); 

    //launch threads 
    foreach(i; 0 .. threads) 
    { 
     spawn(&the_thread); 
    } 
    thread_joinAll(); 
} 

Я попытался полностью определяя барьер в основной функции, но МДД жалуется:

static assert "Aliases to mutable thread-local data not allowed." 

Я также попытался передать его в качестве общей переменной и I получить это:

non-shared method core.sync.barrier.Barrier.wait is not callable using a shared object 
+0

Маркировка барьера как '__gshared' делает его работу для меня (на Windows). – sigod

ответ

2

Глобальные переменные являются поточно-локальная по умолчанию в D. при установке barrier в основном потоке, вы только установить его в основном потоке; для других потоков, barrier будет null.

Вы можете отметить barrier в __gshared, чтобы сделать его поточно-глобальный, хотя это немного рубить:

__gshared Barrier barrier; 

Функция порождения потока позволяет только передачу данных, помеченных как shared, как вы обнаружили. Однако, поскольку функция Barrier.wait не отмечена как shared, вы не можете назвать ее объектом shared(Barrier), что делает его в основном бесполезным. В качестве другого хака, вы можете бросить его неразделенные первый перед вызовом wait:

(cast()barrier).wait(); 
+0

А! Я знал, что это будет что-то с управлением памятью в D, которое я не понял. Теперь вы описали их как хаки. Разве это так, что такой обмен будет выполнен в D или есть ли не хакерский способ, с которым я могу это выполнить? – jdeters

+0

'shared' немного ... underspecified. Моя интерпретация заключается в том, что любые данные, разделяемые по потокам, должны быть «разделены», только «общие» методы могут быть вызваны на «shared» объектах, а листинг на unshared определяется только в том случае, если поток имеет эксклюзивный доступ к объекту (например, защищенный мьютексом). Поэтому функции «Barrier.wait», «Mutex.lock» и т. Д. Должны быть «разделены», но это не так, что является ИМО недостатком стандартной библиотеки. –

+0

@ColonelThirtyTwo Для этого вам нужно создать билет для отслеживания ошибок. – sigod