Странное поведение с ‘setMaxMailboxSize’

#d

#d

Вопрос:

Я написал простой, хотя и многопоточный генератор простых чисел. Алгоритм выглядит следующим образом: поток 0: генерирует последовательные числа. Потоки 1 .. N: отфильтровывают числа, которые не являются простыми. При каждом «новом» первичном обнаружении добавляется новый поток фильтра.

Возьмите I: никакого управления потоком вообще. Поток 0 ‘отправляет номера абсолютно свободно. Программа завершается сигналом 11 (ошибка сегмента), редко сигналом 8, еще реже завершается успешно.

Возьмите II: управление потоком с ‘setMaxMailboxSize’ равным 1. Большую часть времени все работает хорошо.

Возьмите III: теперь, если все это было результатом какого-то внутреннего переполнения, он должен хорошо работать с ‘setMaxMailboxSize’ равным 2 (или даже 10), я не прав? Поток 0 застревает после того, как он блокируется в первый раз.

Не мог бы кто-нибудь, пожалуйста, указать мне, что я пропустил?

Примечание 1: я использую DMD v2.053 под Ubuntu 10.04

Примечание 2: это мой код:

 #!/usr/bin/dmd -run

import std.stdio;
import std.conv;
import std.concurrency;

void main(string[] args)
{
    /* parse command line arguments */
    if (args.length < 2) {
        writeln("Usage: prime <number of primes to generate>");
        return;
    }
    auto nPrimes = to!int(args[1]);

    auto tid = spawn(amp;generate, thisTid);

    /* gather produced primes */
    for (;;) {
        auto prime = receiveOnly!int();
        writeln(prime);
        if (--nPrimes <= 0) {
            break;
        }
    }

    tid.send("stop");
}

void generate(Tid parentTid)
{
    bool terminate = false;

    // filter stage 1
    auto tid = spawn(amp;filter_stage, parentTid);
    /* WHAT DO I MISS HERE ? */
    setMaxMailboxSize(tid, 1, OnCrowding.block);

    for (int i = 2; !terminate; i  ) {
        receiveTimeout(0,
            (string cmd) {
                writeln(cmd);
                terminate = true;
            }
        );

        tid.send(i);
    }
}

void filter_stage(Tid parentTid)
{
    auto prime = receiveOnly!int();
    parentTid.send(prime);

    // filter stage 'N'
    auto tid = spawn(amp;filter_stage, parentTid);

    filter(prime, tid);
}

void filter(int prime, Tid tid)
{
    for (;;) {
        receive (
            (int number) {
                if (number % prime != 0) {
                    tid.send(number);
                }
            }
        );
    }
}
  

Комментарии:

1. возможно, вы создаете для многих потоков

2. ~ 1000 потоков — это слишком много? Сделай мне одолжение !

Ответ №1:

Звучит как ошибка в std.concurrency. Попробуйте обновить DMD до 2.055. Я не уверен, исправлена ли эта конкретная ошибка, но между 2.053 и 2.055 исправлено много ошибок. Если он все еще не работает, пожалуйста, отправьте сообщение об ошибке по адресу http://d.puremagic.com/issues /.

Комментарии:

1. Спасибо! Похоже, вы правы. После обновления поведение стало нормальным (по крайней мере, пока).