обмениваться данными только для чтения между несколькими потоками после их однократного вычисления в C ++ - PullRequest
0 голосов
/ 07 декабря 2018

Я очень новичок в многопоточном программировании и мне нужно несколько советов по этой проблеме, с которой я сталкиваюсь.

У меня есть этот объект, который нужно вычислять дорого, поэтому я хочу вычислить его только в случае необходимости, а затем рассчитать, поделиться им с доступом для чтения, если это понадобится другому потоку.Я знаю только, для каких входных данных мне нужны вычисления во время выполнения.

Так что моя основная идея была примерно такой:

class ExpansiveDoubleCalc
{
    private:
        static double *ptr[10];
        double DoExpansiveCalc(int input)
        {
            double expansivecalc = (123.4 * input);
            return expansivecalc;
        }

    public:
        ExpansiveDoubleCalc(int input, double* output)
        {
            if(ptr[input]==NULL)
                *ptr[input] = DoExpansiveCalc(input);
            output = ptr[input];
        }

};

double * ExpansiveDoubleCalc::ptr[10]{};

Допустим, мне нужно только это для ввода <10.Из моего небольшого понимания многопоточности это имеет многочисленные проблемы: * потоки могут пытаться запустить DoExpansiveCalc одновременно * как только они получают вычисленный указатель для вывода обратно, это может быть медленным, если несколько потоков пытаются получить к нему доступ </p>

Это правильно?Как я могу сделать это безопасно?Кроме того, я должен, вероятно, вернуть указатель const здесь, верно?Есть ли хороший способ сделать это?

Спасибо за помощь!Ура!

Ответы [ 2 ]

0 голосов
/ 11 января 2019

Итак, в конце концов, я пошел с Meyers Singleton , который содержит массив, в котором хранятся дорогостоящие вычисления для каждого ввода int, вычисляя его только в том случае, если записи в массиве нет.Если кому-то интересно, я могу собрать пример кода.

0 голосов
/ 07 декабря 2018

Обычное решение на основе блокировки в современном cpp: https://gcc.godbolt.org/z/SsQaEB

Некоторые примечания:

  1. Я устанавливаю размер во время выполнения.измените на std::array, если вы знаете размер во время компиляции.
  2. Обычно не рекомендуется использовать статическое глобальное состояние.Используйте rawptr или std::shared_ptr для явного совместного использования объекта.

#include<mutex>
#include<vector>

class ExpensiveDoubleCalc {
    public:
    ExpensiveDoubleCalc(size_t size) : data(size){
    }

    static double DoExpensiveCalc(int input) {
        return 123.4 * input;
    }

    double get(int input) {
        return data.at(input).get(input);
    }

    private:
    struct Data {
        bool isSet{false};
        double val;
        std::mutex m;
        double get(int input){
            std::lock_guard<std::mutex> lock{m};
            if(isSet){
                return val;
            } else {
                val = DoExpensiveCalc(input);
                isSet = true;
                return val;
            }
        }
    };    
    std::vector<Data> data;

};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...