Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.98/64: Рейтинг темы: голосов - 64, средняя оценка - 4.98
1 / 1 / 0
Регистрация: 06.02.2019
Сообщений: 217

Ссылка на метод дочернего класса из родительского

24.07.2019, 04:47. Показов 13284. Ответов 46

Студворк — интернет-сервис помощи студентам
Всем привет! Я новичок в C++. Помогите, пожалуйста, сослаться из родительского класса на метод, реализованный в дочернем классе, и, соответственно, вызвать его в родительском классе.
Пытаюсь сделать так:

Родительский класс:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
template <typename TP>
class ThreadPull
{
void (TP::*ThreadFunc)(size_t &i, size_t &n) = nullptr; // ссылка на метод дочернего класса
.....
}
.....
template <typename TP>
void ThreadPull<TP>::LaunchPull(void (TP::*_ThreadFunc)(size_t &i, size_t &n), std::function<void(void)> lambda)
{
ThreadFunc = _ThreadFunc; // присваивается так
}
.....
template <typename TP>
void ThreadPull<TP>::MultiThreadTask(size_t id)
{
(this->*ThreadFunc)(i, n); // вызывается так
}
Дочерний класс:
C++
1
2
3
4
5
class LongArrayProcessing : public ThreadPull<LongArrayProcessing>
.....
LaunchPull(&LongArrayProcessing::ThreadMultipliar, [this]() {
        arrSize = d.size();
    });
Программа не компилируется. Помогите, пожалуйста, разобраться, в чем дело.
Полный код программы:
Файл ThreadPull.h
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#ifndef THREADPULL
#define THREADPULL
 
#include <list>
#include <thread>
#include <mutex>
#include <condition_variable>
 
template <typename TP>
class ThreadPull
{
protected:
    const unsigned int numCores = std::thread::hardware_concurrency();
 
    unsigned int calcRange;
    std::list<std::thread> threads;
    std::mutex mx;
    std::condition_variable cv;
    volatile size_t mi = 0;
    volatile size_t inuse = 0;
    volatile bool stop = false;
    size_t arrSize;
 
    void (TP::*ThreadFunc)(size_t &i, size_t &n) = nullptr;
    void MultiThreadTask(size_t id);
 
public:
    ThreadPull();
    ~ThreadPull();
 
    void LaunchPull(void (TP::*_ThreadFunc)(size_t &i, size_t &n), std::function<void(void)> lambda);
};
 
#include <algorithm>
 
template <typename TP>
ThreadPull<TP>::ThreadPull()
{
    for (size_t i = (size_t)numCores; i > 0; --i)
    {
        threads.push_back(std::thread([this, i]() {
            MultiThreadTask(i);
        }));
    }
}
 
template <typename TP>
ThreadPull<TP>::~ThreadPull()
{
    {
        std::lock_guard<std::mutex> lock(mx);
        stop = true;
        cv.notify_all();
    }
 
    for (auto &thread : threads)
        if (thread.joinable())
            thread.join();
}
 
template <typename TP>
void ThreadPull<TP>::MultiThreadTask(size_t id)
{
    while (true)
    {
        size_t i, n;
        {
            std::unique_lock<std::mutex> lock(mx);
            while (true)
            {
                if (stop)
                    return;
 
                if (mi < arrSize)
                {
                    i = mi;
                    n = mi = std::min(arrSize, mi + calcRange);
 
                    ++inuse;
                    break;
                }
                cv.wait(lock);
            }
        }
 
        (this->*ThreadFunc)(i, n);
 
        std::lock_guard<std::mutex> lock(mx);
        --inuse;
        cv.notify_all();
    }
}
 
template <typename TP>
void ThreadPull<TP>::LaunchPull(void (TP::*_ThreadFunc)(size_t &i, size_t &n), std::function<void(void)> lambda)
{
    {
        std::lock_guard<std::mutex> lock(mx);
 
        mi = 0;
        lambda();
        calcRange = arrSize / numCores;
        ThreadFunc = _ThreadFunc;
 
        cv.notify_all();
    }
 
    {
        std::unique_lock<std::mutex> lock(mx);
        while (mi < arrSize || inuse != 0)
            cv.wait(lock);
    }
}
 
#endif // !THREADPULL
Файл LongArrayProcessing.h
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#ifndef LONGARRAYPROCESSING
#define LONGARRAYPROCESSING
 
#include <vector>
#include <list>
#include <thread>
#include <mutex>
#include <condition_variable>
 
#include "ThreadPull.h"
 
class LongArrayProcessing : public ThreadPull<LongArrayProcessing>
{
private:
    const unsigned int cnt;
 
    unsigned int maxArrIdx;
    std::vector<double> a;
    std::vector<double> b;
    std::vector<double> c;
    std::vector<double> d;
    std::vector<double> correctAns;
    double *e, *sumCorrectAns;
    unsigned int eCnt;
 
    double MyRandom();
    void MultiThreadTest(unsigned int startIdx, unsigned int endIdx);
 
    void ThreadMultipliar(size_t &i, size_t &n);
    void ThreadSummator(size_t &i, size_t &n);
 
public:
    void Init();
    LongArrayProcessing(unsigned int _cnt, unsigned int _eCnt);
    ~LongArrayProcessing();
    std::chrono::milliseconds ProcessArray();
    std::chrono::milliseconds ProcessArrayCondVar();
    std::chrono::milliseconds ProcessArraySummator();
    std::vector<double> &GetC() { return c; }
    std::vector<double> &GetD() { return d; }
    std::vector<double> &GetCorrectAns() { return correctAns; }
    double *GetE() { return e; }
    double *GetSumCorrectAns() { return sumCorrectAns; }
};
 
#endif // !LONGARRAYPROCESSING
Файл LongArrayProcessing.cpp
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#include "LongArrayProcessing.h"
 
#include <ctime>
#include <iostream>
#include <algorithm>
 
using namespace std;
 
LongArrayProcessing::LongArrayProcessing(unsigned int _cnt, unsigned int _eCnt)
    : cnt(_cnt), eCnt(_eCnt), maxArrIdx(cnt), a(cnt), b(cnt), c(cnt), d(cnt), correctAns(cnt)
{
    cout << "Start!" << endl;
 
    e = new double[eCnt];
    sumCorrectAns = new double[eCnt];
 
    cout << "End!" << endl;
}
 
LongArrayProcessing::~LongArrayProcessing()
{
    delete[] e;
    delete[] sumCorrectAns;
}
 
void LongArrayProcessing::Init()
{
    for (unsigned int i = 0; i < cnt; i++)
    {
        a[i] = 100.0 * MyRandom() - 50.0;
        b[i] = 100.0 * MyRandom() - 50.0;
        c[i] = 0;
        d[i] = 0;
        correctAns[i] = a[i] * b[i];
    }
 
    for (unsigned int i = 0; i < eCnt; i++)
    {
        e[i] = 0;
        sumCorrectAns[i] = a[i] + b[i];
    }
}
 
double LongArrayProcessing::MyRandom()
{
    return static_cast<double>(rand()) / RAND_MAX;
}
 
void LongArrayProcessing::MultiThreadTest(unsigned int startIdx, unsigned int endIdx)
{
    for (unsigned int i = startIdx; i < endIdx; i++)
    {
        c[i] = a[i] * b[i];
    }
}
 
chrono::milliseconds LongArrayProcessing::ProcessArray()
{
    unsigned int numCores = std::thread::hardware_concurrency();
    unsigned int numThreads = numCores - 1;
    unsigned int calcRange = (unsigned int)c.size() / numCores;
 
    auto begin = chrono::steady_clock::now();
 
    list<thread> ts;
    unsigned int startIdx = 0;
 
    for (unsigned int t = 0; t < numThreads; t++)
    {
        unsigned int endIdx = startIdx + calcRange;
        ts.push_back(thread([this, startIdx, endIdx]() {
            MultiThreadTest(startIdx, endIdx);
        }));
        startIdx = endIdx;
    }
 
    MultiThreadTest(startIdx, maxArrIdx);
 
    for (auto &el : ts)
        el.join();
 
    auto end = chrono::steady_clock::now();
    return chrono::duration_cast<chrono::milliseconds>(end - begin);
}
 
chrono::milliseconds LongArrayProcessing::ProcessArrayCondVar()
{
    auto begin = chrono::steady_clock::now();
 
    LaunchPull(&LongArrayProcessing::ThreadMultipliar, [this]() {
        arrSize = d.size();
    });
 
    auto end = chrono::steady_clock::now();
    return chrono::duration_cast<chrono::milliseconds>(end - begin);
}
 
void LongArrayProcessing::ThreadMultipliar(size_t &i, size_t &n)
{
    for (; i < n; ++i)
    {
        d[i] = a[i] * b[i];
    }
}
 
std::chrono::milliseconds LongArrayProcessing::ProcessArraySummator()
{
    auto begin = chrono::steady_clock::now();
 
    LaunchPull(&LongArrayProcessing::ThreadSummator, [this]() {
        arrSize = (size_t)eCnt;
    });
 
    auto end = chrono::steady_clock::now();
    return chrono::duration_cast<chrono::milliseconds>(end - begin);
}
 
void LongArrayProcessing::ThreadSummator(size_t &i, size_t &n)
{
    for (; i < n; ++i)
    {
        e[i] = a[i] + b[i];
    }
}
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
24.07.2019, 04:47
Ответы с готовыми решениями:

Может ли метод родительского класса обратиться к полю дочернего класса
Может ли метод родительского класса обратиться к полю дочернего класса?

Как вызвать виртуальную функцию из дочернего класса, если она определена и вызывается в конструкторе РОДИТЕЛЬСКОГО класса?
Ну то есть так: есть родительский и дочерний класс, в родительском определен виртуальная функция и вызывается в его конструкторе (камень...

Как передать в метод класса Menu указатель на метод дочернего класса?
Как передать в метод базового класса указатель на метод дочернего: class Menu() { protected: setCallback(*********); //...

46
1 / 1 / 0
Регистрация: 06.02.2019
Сообщений: 217
24.07.2019, 21:49  [ТС]
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
Там требуется со ссылками (непонятно, кстати, нафига) - void MultiThreadTest(size_t &startIdx, size_t &endIdx);
Этот метод потоки создает на лету. Он работает.

Добавлено через 1 минуту
Теперь куча ошибок линковки появилось.
Code
1
2
3
4
5
6
7
8
Серьезность  Код  Описание    Проект    Файл    Строка    Состояние подавления
Ошибка    LNK1169 обнаружен многократно определенный символ - один или более    TestThreads D:\CppProjects\TestThreads\Release\TestThreads.exe  1   
Серьезность  Код  Описание    Проект    Файл    Строка    Состояние подавления
Ошибка    LNK2005 "public: __thiscall ThreadPull::~ThreadPull(void)" (??1ThreadPull@@QAE@XZ) уже определен в LongArrayProcessing.obj TestThreads D:\CppProjects\TestThreads\TestThreads\LongArrayProcessing.obj  1   
Серьезность  Код  Описание    Проект    Файл    Строка    Состояние подавления
Ошибка    LNK2005 "public: __thiscall ThreadPull::ThreadPull(void)" (??0ThreadPull@@QAE@XZ) уже определен в LongArrayProcessing.obj  TestThreads D:\CppProjects\TestThreads\TestThreads\LongArrayProcessing.obj  1   
Серьезность  Код  Описание    Проект    Файл    Строка    Состояние подавления
Ошибка    LNK2005 "protected: void __thiscall ThreadPull::MultiThreadTask(unsigned int)" (?MultiThreadTask@ThreadPull@@IAEXI@Z) уже определен в LongArrayProcessing.obj  TestThreads D:\CppProjects\TestThreads\TestThreads\LongArrayProcessing.obj  1
0
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
24.07.2019, 21:53
Покажи код для LongArrayProcessing

Добавлено через 2 минуты
Цитата Сообщение от YagDen Посмотреть сообщение
Теперь куча ошибок линковки появилось.
template <typename TP> там убрал, везде?
0
1 / 1 / 0
Регистрация: 06.02.2019
Сообщений: 217
24.07.2019, 21:56  [ТС]
LongArrayProcessing.h
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#ifndef LONGARRAYPROCESSING
#define LONGARRAYPROCESSING
 
#include <vector>
#include <list>
#include <thread>
#include <mutex>
#include <condition_variable>
 
#include "ThreadPull.h"
 
class LongArrayProcessing : public ThreadPull
{
private:
    const unsigned int cnt;
    
    unsigned int maxArrIdx;
    std::vector<double> a;
    std::vector<double> b;
    std::vector<double> c;
    std::vector<double> d;
    std::vector<double> correctAns;
    double *e, *sumCorrectAns;
    unsigned int eCnt;
 
    double MyRandom();
    void MultiThreadTest(unsigned int startIdx, unsigned int endIdx);
 
    void ThreadMultipliar(size_t &i, size_t &n);
    void ThreadSummator(size_t &i, size_t &n);
 
public:
    void Init();
    LongArrayProcessing(unsigned int _cnt, unsigned int _eCnt);
    ~LongArrayProcessing();
    std::chrono::milliseconds ProcessArray();
    std::chrono::milliseconds ProcessArrayCondVar();
    std::chrono::milliseconds ProcessArraySummator();
    std::vector<double> &GetC() { return c; }
    std::vector<double> &GetD() { return d; }
    std::vector<double> &GetCorrectAns() { return correctAns; }
    double *GetE() { return e; }
    double *GetSumCorrectAns() { return sumCorrectAns; }
};
 
#endif // !LONGARRAYPROCESSING
LongArrayProcessing.cpp
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#include <ctime>
#include <iostream>
#include <algorithm>
 
#include "LongArrayProcessing.h"
 
using namespace std;
 
LongArrayProcessing::LongArrayProcessing(unsigned int _cnt, unsigned int _eCnt)
    : cnt(_cnt), eCnt(_eCnt), maxArrIdx(cnt), a(cnt), b(cnt), c(cnt), d(cnt), correctAns(cnt)
{
    cout << "Start!" << endl;
 
    e = new double[eCnt];
    sumCorrectAns = new double[eCnt];
 
    cout << "End!" << endl;
}
 
LongArrayProcessing::~LongArrayProcessing()
{
    delete[] e;
    delete[] sumCorrectAns;
}
 
void LongArrayProcessing::Init()
{
    for (unsigned int i = 0; i < cnt; i++)
    {
        a[i] = 100.0 * MyRandom() - 50.0;
        b[i] = 100.0 * MyRandom() - 50.0;
        c[i] = 0;
        d[i] = 0;
        correctAns[i] = a[i] * b[i];
    }
 
    for (unsigned int i = 0; i < eCnt; i++)
    {
        e[i] = 0;
        sumCorrectAns[i] = a[i] + b[i];
    }
}
 
double LongArrayProcessing::MyRandom()
{
    return static_cast<double>(rand()) / RAND_MAX;
}
 
void LongArrayProcessing::MultiThreadTest(unsigned int startIdx, unsigned int endIdx)
{
    for (unsigned int i = startIdx; i < endIdx; i++)
    {
        c[i] = a[i] * b[i];
    }
}
 
chrono::milliseconds LongArrayProcessing::ProcessArray()
{
    unsigned int numCores = std::thread::hardware_concurrency();
    unsigned int numThreads = numCores - 1;
    unsigned int calcRange = (unsigned int)c.size() / numCores;
 
    auto begin = chrono::steady_clock::now();
 
    list<thread> ts;
    unsigned int startIdx = 0;
 
    for (unsigned int t = 0; t < numThreads; t++)
    {
        unsigned int endIdx = startIdx + calcRange;
        ts.push_back(thread([this, startIdx, endIdx]() {
            MultiThreadTest(startIdx, endIdx);
        }));
        startIdx = endIdx;
    }
 
    MultiThreadTest(startIdx, maxArrIdx);
 
    for (auto &el : ts)
        el.join();
 
    auto end = chrono::steady_clock::now();
    return chrono::duration_cast<chrono::milliseconds>(end - begin);
}
 
chrono::milliseconds LongArrayProcessing::ProcessArrayCondVar()
{
    auto begin = chrono::steady_clock::now();
 
    arrSize = d.size();
    LaunchPull(&LongArrayProcessing::ThreadMultipliar, this);
 
    auto end = chrono::steady_clock::now();
    return chrono::duration_cast<chrono::milliseconds>(end - begin);
}
 
void LongArrayProcessing::ThreadMultipliar(size_t &i, size_t &n)
{
    for (; i < n; ++i)
    {
        d[i] = a[i] * b[i];
    }
}
 
std::chrono::milliseconds LongArrayProcessing::ProcessArraySummator()
{
    auto begin = chrono::steady_clock::now();
 
 
    auto end = chrono::steady_clock::now();
    return chrono::duration_cast<chrono::milliseconds>(end - begin);
}
 
void LongArrayProcessing::ThreadSummator(size_t &i, size_t &n)
{
    for (; i < n; ++i)
    {
        e[i] = a[i] + b[i];
    }
}
Добавлено через 1 минуту
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
template <typename TP> там убрал, везде?
Да, просмотрел код, не вижу.
0
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
24.07.2019, 21:58
Цитата Сообщение от YagDen Посмотреть сообщение
LongArrayProcessing.h
Там у тебя вроде скомпилировалось. Линковка прошла?

Добавлено через 1 минуту
Цитата Сообщение от YagDen Посмотреть сообщение
Ошибка LNK1169 обнаружен многократно определенный символ - один или более TestThreads D:\CppProjects\TestThreads\Release\TestT hreads.exe 1
Поставь перед этими функциями inline
0
1 / 1 / 0
Регистрация: 06.02.2019
Сообщений: 217
24.07.2019, 21:58  [ТС]
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
Там у тебя вроде скомпилировалось. Линковка прошла?
Не проходит. Многократное переопределение символа.
0
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
24.07.2019, 22:00
Цитата Сообщение от YagDen Посмотреть сообщение
Не проходит. Многократное переопределение символа.
inline поставил?
0
1 / 1 / 0
Регистрация: 06.02.2019
Сообщений: 217
24.07.2019, 22:09  [ТС]
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
inline поставил?
Да, скомпилировалось, линковка тоже прошла, но теперь когда добавляю
C++
1
2
arrSize = (size_t)eCnt;
LaunchPull(&LongArrayProcessing::ThreadSummator, this);
прога вылетает.

Добавлено через 3 минуты
Такое ощущение, что
C++
1
arrSize = (size_t)eCnt;
не отрабатывает. Причем только функции ThreadSummator. В ThreadMultipliar все нормально.
0
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
24.07.2019, 22:09
Цитата Сообщение от YagDen Посмотреть сообщение
прога вылетает.
Запусти под отладчиком и посмотри, где именно
0
1 / 1 / 0
Регистрация: 06.02.2019
Сообщений: 217
24.07.2019, 22:11  [ТС]
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
Запусти под отладчиком и посмотри, где именно
Сейчас в деструкторе:
C++
1
delete[] e;
0
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
24.07.2019, 22:14
Цитата Сообщение от YagDen Посмотреть сообщение
Такое ощущение, что
Там у тебя вообще всё криво. Проще сделать с нуля, чем править.
Посмотри, сегодня написал блог здесь, по-моему по очень похожей теме, может поможет Параллельная обработка массива
2
1 / 1 / 0
Регистрация: 06.02.2019
Сообщений: 217
24.07.2019, 22:14  [ТС]
И кроме этого, у меня в мэйне моя проверка отрабатывает, т.е. сумма считается не верно.
0
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
24.07.2019, 22:17
Цитата Сообщение от YagDen Посмотреть сообщение
И кроме этого, у меня в мэйне моя проверка отрабатывает, т.е. сумма считается не верно.
Ну, мы решили только одну проблему - вызова метода. Там ещё других дофигища.
0
1 / 1 / 0
Регистрация: 06.02.2019
Сообщений: 217
25.07.2019, 06:43  [ТС]
На данном этапе я привел код к такому состоянию:
Файл ThreadPull.h
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#ifndef THREADPULL
#define THREADPULL
 
#include <list>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <algorithm>
#include <functional>
 
using namespace std::placeholders;
 
class ThreadPull
{
protected:
    const unsigned int numCores = std::thread::hardware_concurrency();
 
    unsigned int calcRange = 0;
    std::list<std::thread> threads;
    std::mutex mx;
    std::condition_variable cv;
    volatile size_t mi = 0;
    volatile size_t inuse = 0;
    volatile bool stop = false;
    size_t arrSize = 0;
 
    void MultiThreadTask(size_t id);
 
public:
    ThreadPull();
    ~ThreadPull();
 
    std::function<void(size_t &i, size_t &n)> ThreadFunc;
 
    template <typename TFunc, typename... TT>
    void LaunchPull(TFunc &&func, TT&&... args);
};
 
template <typename TFunc, typename... TT>
void ThreadPull::LaunchPull(TFunc &&func, TT&&... args)
{
    {
        std::lock_guard<std::mutex> lock(mx);
 
        mi = 0;
        //lambda();
        calcRange = arrSize / numCores;
        ThreadFunc = std::bind(std::forward<TFunc>(func), std::forward<TT>(args)..., _1, _2);
 
        cv.notify_all();
    }
 
    {
        std::unique_lock<std::mutex> lock(mx);
        while (mi < arrSize || inuse)
            cv.wait(lock);
    }
}
 
#endif // !THREADPULL
Файл ThreadPull.cpp
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#include "ThreadPull.h"
 
using namespace std;
 
ThreadPull::ThreadPull()
{
    for (size_t i = (size_t)numCores; i > 0; --i)
    {
        threads.push_back(std::thread([this, i]() {
            MultiThreadTask(i);
        }));
    }
}
 
ThreadPull::~ThreadPull()
{
    {
        std::lock_guard<std::mutex> lock(mx);
        stop = true;
        cv.notify_all();
    }
 
    for (auto &thread : threads)
        if (thread.joinable())
            thread.join();
}
 
void ThreadPull::MultiThreadTask(size_t id)
{
    while (true)
    {
        size_t i, n;
        {
            std::unique_lock<std::mutex> lock(mx);
            while (true)
            {
                if (stop)
                    return;
 
                if (mi < arrSize)
                {
                    i = mi;
                    n = mi = std::min(arrSize, mi + calcRange);
 
                    ++inuse;
                    break;
                }
                cv.wait(lock);
            }
        }
 
        ThreadFunc(i, n);
 
        std::lock_guard<std::mutex> lock(mx);
        --inuse;
        cv.notify_all();
    }
}
Файл LongArrayProcessing.h
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#ifndef LONGARRAYPROCESSING
#define LONGARRAYPROCESSING
 
#include <vector>
#include <list>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <ctime>
 
#include "ThreadPull.h"
 
class LongArrayProcessing : public ThreadPull
{
private:
    const unsigned int cnt;
    
    unsigned int maxArrIdx;
    std::vector<double> a;
    std::vector<double> b;
    std::vector<double> c;
    std::vector<double> d;
    std::vector<double> correctAns;
    double *e, *sumCorrectAns;
    unsigned int eCnt;
 
    double MyRandom();
    void MultiThreadTest(unsigned int startIdx, unsigned int endIdx);
 
    void ThreadMultipliar(size_t &i, size_t &n);
    void ThreadSummator(size_t &i, size_t &n);
 
public:
    void Init();
    LongArrayProcessing(unsigned int _cnt, unsigned int _eCnt);
    ~LongArrayProcessing();
    std::chrono::milliseconds ProcessArray();
    std::chrono::milliseconds ProcessArrayCondVar();
    std::chrono::milliseconds ProcessArraySummator();
    std::vector<double> &GetC() { return c; }
    std::vector<double> &GetD() { return d; }
    std::vector<double> &GetCorrectAns() { return correctAns; }
    double *GetE() { return e; }
    double *GetSumCorrectAns() { return sumCorrectAns; }
};
 
#endif // !LONGARRAYPROCESSING
Файл LongArrayProcessing.cpp
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
#include <iostream>
#include <algorithm>
 
#include "LongArrayProcessing.h"
 
using namespace std;
 
LongArrayProcessing::LongArrayProcessing(unsigned int _cnt, unsigned int _eCnt)
    : cnt(_cnt), eCnt(_eCnt), maxArrIdx(cnt), a(cnt), b(cnt), c(cnt), d(cnt), correctAns(cnt)
{
    cout << "Start!" << endl;
 
    e = new double[eCnt];
    sumCorrectAns = new double[eCnt];
 
    cout << "End!" << endl;
}
 
LongArrayProcessing::~LongArrayProcessing()
{
    delete[] e;
    delete[] sumCorrectAns;
}
 
void LongArrayProcessing::Init()
{
    for (unsigned int i = 0; i < cnt; i++)
    {
        a[i] = 100.0 * MyRandom() - 50.0;
        b[i] = 100.0 * MyRandom() - 50.0;
        c[i] = 0;
        d[i] = 0;
        correctAns[i] = a[i] * b[i];
    }
 
    for (unsigned int i = 0; i < eCnt; i++)
    {
        e[i] = 0;
        sumCorrectAns[i] = a[i] + b[i];
    }
}
 
double LongArrayProcessing::MyRandom()
{
    return static_cast<double>(rand()) / RAND_MAX;
}
 
void LongArrayProcessing::MultiThreadTest(unsigned int startIdx, unsigned int endIdx)
{
    for (unsigned int i = startIdx; i < endIdx; i++)
    {
        c[i] = a[i] * b[i];
    }
}
 
chrono::milliseconds LongArrayProcessing::ProcessArray()
{
    unsigned int numCores = std::thread::hardware_concurrency();
    unsigned int numThreads = numCores - 1;
    unsigned int calcRange = (unsigned int)c.size() / numCores;
 
    auto begin = chrono::steady_clock::now();
 
    list<thread> ts;
    unsigned int startIdx = 0;
 
    for (unsigned int t = 0; t < numThreads; t++)
    {
        unsigned int endIdx = startIdx + calcRange;
        ts.push_back(thread([this, startIdx, endIdx]() {
            MultiThreadTest(startIdx, endIdx);
        }));
        startIdx = endIdx;
    }
 
    MultiThreadTest(startIdx, maxArrIdx);
 
    for (auto &el : ts)
        el.join();
 
    auto end = chrono::steady_clock::now();
    return chrono::duration_cast<chrono::milliseconds>(end - begin);
}
 
chrono::milliseconds LongArrayProcessing::ProcessArrayCondVar()
{
    auto begin = chrono::steady_clock::now();
 
    arrSize = d.size();
    LaunchPull(&LongArrayProcessing::ThreadMultipliar, this);
 
    auto end = chrono::steady_clock::now();
    return chrono::duration_cast<chrono::milliseconds>(end - begin);
}
 
void LongArrayProcessing::ThreadMultipliar(size_t &i, size_t &n)
{
    for (; i < n; ++i)
    {
        d[i] = a[i] * b[i];
    }
}
 
std::chrono::milliseconds LongArrayProcessing::ProcessArraySummator()
{
    auto begin = chrono::steady_clock::now();
 
    arrSize = (size_t)eCnt;
    LaunchPull(&LongArrayProcessing::ThreadSummator, this);
 
    auto end = chrono::steady_clock::now();
    return chrono::duration_cast<chrono::milliseconds>(end - begin);
}
 
void LongArrayProcessing::ThreadSummator(size_t &i, size_t &n)
{
    for (; i < n; ++i)
    {
        e[i] = a[i] + b[i];
    }
}
Файл main.cpp
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#include <iostream>
#include <ctime>
 
#include "LongArrayProcessing.h"
 
using namespace std;
 
void main()
{
    //const unsigned int cnt = 9999999;
    const unsigned int cnt = 100;
    const unsigned int eCnt = cnt / 2;
 
    srand(static_cast<unsigned int>(time(NULL)));
 
    LongArrayProcessing lap(cnt, eCnt);
    unsigned int itrNum = 0;
 
    bool err, err2;
 
    do
    {
        lap.Init();
 
        for (int i = 0; i < 500; i++)
        {
            auto procTimeCondVar = lap.ProcessArrayCondVar();
            auto procTimeSummator = lap.ProcessArraySummator();
        }
        auto procTime = lap.ProcessArray();
        auto procTimeCondVar = lap.ProcessArrayCondVar();
        auto procTimeSummator = lap.ProcessArraySummator();
        
        cout << "Time Process Array: " << procTime.count() << " ms\n";
        cout << "Time Process Array Conditional Variable: " << procTimeCondVar.count() << " ms\n";
        cout << "Time Process Array Summator: " << procTimeSummator.count() << " ms\n";
        cout << endl;
 
        auto c = lap.GetC();
        auto d = lap.GetD();
        auto correctAns = lap.GetCorrectAns();
 
        auto e = lap.GetE();
        auto sumCorrectAns = lap.GetSumCorrectAns();
 
        err = false;
 
        for (unsigned int i = 0; i < cnt; i++)
        {
            if ((c[i] != correctAns[i]) || (d[i] != correctAns[i]))
            {
                err = true;
                break;
            }
        }
 
        if (err)
            break;
 
        err2 = false;
 
        for (unsigned int i = 0; i < eCnt; i++)
        {
            if (e[i] != sumCorrectAns[i])
            {
                err2 = true;
                break;
            }
        }
 
        if (err2)
            break;
 
        itrNum++;
 
        this_thread::sleep_for(chrono::milliseconds(6000));
    } while (true);
 
    if (err)
    {
        auto c = lap.GetC();
        auto d = lap.GetD();
        auto correctAns = lap.GetCorrectAns();
 
        for (unsigned int i = 0; i < cnt; i++)
        {
            if ((c[i] != correctAns[i]) || (d[i] != correctAns[i]))
                cout << "i = " << i << ", " << c[i] << " <> " << d[i] << " (" << correctAns[i] << ")" << endl;
        }
 
        cout << endl << "Multiply ERROR! Iteration: " << itrNum << endl;
    }
 
    if (err2)
    {
        auto e = lap.GetE();
        auto sumCorrectAns = lap.GetSumCorrectAns();
 
        for (unsigned int i = 0; i < eCnt; i++)
        {
            if (e[i] != sumCorrectAns[i])
                cout << "i = " << i << ", " << e[i] << " (" << sumCorrectAns[i] << ")" << endl;
        }
 
        cout << endl << "Summ ERROR! Iteration: " << itrNum << endl;
    }
    
 
    system("PAUSE");
}
Программа компилируется, но вызовы метода LaunchPull(); ломают кучу.
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
Ну, мы решили только одну проблему - вызова метода. Там ещё других дофигища.
Согласен, код не идеален. На звание самого пряморукого программиста в мире не претендую (да и на звание просто программиста тоже). Скорее, любитель. Но если в данном коде закомментировать все вызовы метода LaunchPull(), то код не вылетает с ошибкой. А так - вылетает с ошибкой о повреждении данных в куче. Так что, насколько я понимаю, мы не совсем решили проблему с вызовом метода.
0
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
25.07.2019, 08:54
Цитата Сообщение от YagDen Посмотреть сообщение
Но если в данном коде закомментировать все вызовы метода LaunchPull(), то код не вылетает с ошибкой. А так - вылетает с ошибкой о повреждении данных в куче. Так что, насколько я понимаю, мы не совсем решили проблему с вызовом метода
Вообще-то решили. Именно поэтому у тебя полезли другие ошибки, до которых раньше тупо не доходило.
Теперь по поводу arrSize - а нафига у тебя размер массива сделан общим для всех потоков? Если каждый поток обрабатывает свои данные, то и размер этих данных должен был у каждого свой. Это раз.
Второе - у тебя поток обращается к переменной ThreadProc в методе MultiThreadTask читает, в LaunchPull пишет. Эти методы работают в разных потоков, т.е. эти обращения должны быть синхронизтрованы.

Цитата Сообщение от YagDen Посмотреть сообщение
Скорее, любитель. Но если в данном коде закомментировать все вызовы метода LaunchPull(), то код не вылетает с ошибкой.
Попробуй закомментировать воообще все вызовы, тогда ещё лучше будет работать.
0
1 / 1 / 0
Регистрация: 06.02.2019
Сообщений: 217
25.07.2019, 10:07  [ТС]
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
Вообще-то решили. Именно поэтому у тебя полезли другие ошибки, до которых раньше тупо не доходило.
Логику методов я не менял. Единственное, что менял, это код, связанный с указателем на функцию и его вызовом. С шаблонным классом код работал корректно, а теперь перестал. Это значит, что ошибка была внесена уже после.
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
Теперь по поводу arrSize - а нафига у тебя размер массива сделан общим для всех потоков? Если каждый поток обрабатывает свои данные, то и размер этих данных должен был у каждого свой. Это раз.
size_t i, n; - диапазон обработки каждого потока. И он у каждого потока свой. arrSize - это глобальный размер массива. На основании него потоки контролируют область видимости.
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
Второе - у тебя поток обращается к переменной ThreadProc в методе MultiThreadTask читает, в LaunchPull пишет. Эти методы работают в разных потоков, т.е. эти обращения должны быть синхронизтрованы.
Вы имеете ввиду ThreadFunc? LaunchPull пишет в него до вызова cv.notify_all(), потоки в это время спят. А когда они работают, единственное, к чему обращается LaunchPull - это к мьютексу
C++
1
2
while (mi < arrSize || inuse)
            cv.wait(lock);
который атомарен по определению.
0
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
25.07.2019, 10:16
Цитата Сообщение от YagDen Посмотреть сообщение
size_t i, n; - диапазон обработки каждого потока. И он у каждого потока свой. arrSize - это глобальный размер массива. На основании него потоки контролируют область видимости.
Он одинаковый для всех?

Добавлено через 5 минут
Цитата Сообщение от YagDen Посмотреть сообщение
Вы имеете ввиду ThreadFunc? LaunchPull пишет в него до вызова cv.notify_all(), потоки в это время спят. А когда они работают, единственное, к чему обращается LaunchPull - это к мьютексу
Нет не спят. Во время выполнения потока может быть вызвана LaunchPull, тогда её значение поменяется.
В пуле потоков вообще не должно быть общих переменные для всех потоков, ну кроме мютекса, condition_variable и флажка stop. Всё остальное дожно передаваться в поток при запуске.

Добавлено через 1 минуту
Кстати, там в блоге, упростил пример и добавил коментарии к нему. Сейчас попробую сделать там ещё реализацию примитивного пула потоков
0
1 / 1 / 0
Регистрация: 06.02.2019
Сообщений: 217
25.07.2019, 10:29  [ТС]
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
Он одинаковый для всех?
Диапозон должен быть примерно одинаковый, а сами значения переменных, разумеется, разные.
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
Во время выполнения потока может быть вызвана LaunchPull, тогда её значение поменяется.
А в каком случае такое возможно? Я же вызываю LaunchPull только тогда, когда предыдущий вызов завершится. Да по факту, я и выйти из метода до того момента не смогу - cv.wait(lock); не выпустит.
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
Сейчас попробую сделать там ещё реализацию примитивного пула потоков
Интересно будет взглянуть. Надеюсь, для меня окажется не слишком сложно.
0
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
25.07.2019, 11:00
Цитата Сообщение от YagDen Посмотреть сообщение
Диапозон должен быть примерно одинаковый, а сами значения переменных, разумеется, разные.
"Примерно одинаковый" означает разный. Значит его надо передавать параметром функции, а не хранить глобальный.
Цитата Сообщение от YagDen Посмотреть сообщение
А в каком случае такое возможно? Я же вызываю LaunchPull только тогда, когда предыдущий вызов завершится. Да по факту, я и выйти из метода до того момента не смогу - cv.wait(lock); не выпустит.
У тебя несколько потоков выполняются одновременно (Иначе зачем это всё?), для них заданы разные объекты ThreadFunc

Цитата Сообщение от YagDen Посмотреть сообщение
Интересно будет взглянуть. Надеюсь, для меня окажется не слишком сложно.
Сделал, вроде достаточно просто получилось https://www.cyberforum.ru/blog... g5939.html
0
1 / 1 / 0
Регистрация: 06.02.2019
Сообщений: 217
25.07.2019, 12:06  [ТС]
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
"Примерно одинаковый" означает разный. Значит его надо передавать параметром функции, а не хранить глобальный.
Если я правильно понимаю этот код, каждый поток сам считает себе эти диапазоны.
C++
1
2
3
4
5
6
7
8
if (mi < arrSize)
                {
                    i = mi;
                    n = mi = std::min(arrSize, mi + calcRange);
 
                    ++inuse;
                    break;
                }
Единственная функция arrSize здесь - контроль, что бы не выйти за пределы массива.
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
У тебя несколько потоков выполняются одновременно (Иначе зачем это всё?), для них заданы разные объекты ThreadFunc
Что вы подразумеваете под объектами ThreadFunc? Это разве не указатель на функцию? По крайней мере, я его так понимаю.
0
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
25.07.2019, 12:16
Цитата Сообщение от YagDen Посмотреть сообщение
Если я правильно понимаю этот код, каждый поток сам считает себе эти диапазоны.
Это должно вызыватся перед запуском потока, а не внутри (посмотри как у меня сделано). В функции потока не нужно ничего знать об общем размере массива.

Добавлено через 1 минуту
Цитата Сообщение от YagDen Посмотреть сообщение
Что вы подразумеваете под объектами ThreadFunc? Это не указатель на функцию. По крайней мере, я его так понимаю.
Правильно понимаешь, не указатель. Когда ты делаешь ThreadFunc = std::bind..., то старое значение удаляется и присваивается новое. Если ты в это время попытаешься вызвать в другом потоке ThreadFunc(), то будет ошибка

Добавлено через 4 минуты
Вообще, убрал бы ты пока все эти обработки массива. Убедись сначала, что у тебя пул потоков работает.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
25.07.2019, 12:16

ООП в C++: Вызов родительского конструктора с параметром при создании объекта дочернего класса
Здравствуйте! Столкнулся с такой проблемой: если есть родительский класс с конструктором, то при создании дочернего объекта от этого...

Почему в списке инициализации конструктора дочернего класса нельзя вызывать конструктор родительского через его пространство имён?
Есть класс D и от него порождён класс Wd Тут вот например всё работает корректно (использую обращение ч/з пространство имён класса...

Как вызвать метод родительского класса;
Собственно вопрос; Есть класс a и b; Класс b унаследован от класса a; И как теперь из класса b вызвать функцию класса a;

Ссылка на метод класса
если кратко то задача такова надо передать адрес метода класа.как это можно сделать?

Завершение родительского процесса из дочернего
Всем доброго времени суток. Мне нужно из дочернего процесса закрыть родительский, но ничего не выходит. Вот исходник дочернего ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
Новые блоги и статьи
Как надо было делать правильно - вообще не слушать ИИ, его дело - текст.
Hrethgir 15.07.2026
А вообще надо было делать не так, чтобы не исправлять ошибку https:/ / www. cyberforum. ru/ blogs/ 223907/ 10996. html , правильно было : удалил кнопку, а потом добавил её. Всё это стресс конечно. Почему?. . .
Знаете, от чего появляется стресс?
kumehtar 15.07.2026
Стресс появляется оттого, что вы, зная как поступить правильно, делаете наоборот. Ларри Уингет
Нас бьют, а мы крепчаем? Какая чушь!
kumehtar 15.07.2026
Вот это вот бытующее мнение, что человек меняется только под действием проблем, всегда считал вредоносным. Поверь, от проблем у людей появляются не изменения, а нервное расстройство и ПТСР. А. . .
сукцессия 29. Переход от одних деревьев на другие делать более или менее вероятностным?
anaschu 12.07.2026
Насколько смена типов микоризы — исключительное событие в двухвековой сукцессии? Оценка вероятности в пространстве параметров В текущей версии модели успешно реализован ключевой механизм. . .
сукцессия 27. Думаю, как переделывать уже написанную статью с планами на сукцессию.
anaschu 12.07.2026
Анализ соответствия модели требованиям Реализованные компоненты: Механизм закисления почвы через протонную помпу Конкуренция между типами микориз pH как триггер сукцессии C/ P соотношение. . .
Сукцессия 26. Мат модель создана.
anaschu 12.07.2026
Модель смены растительных сукцессий посредством управления грибами работает внутри небольшой ячейки почвы, восстанавливающейся после пожара, где ненадолго бывшее царство хвойных снова захватили. . .
Решил проблему с ошибкой пагинации сообщений с сервера на алгоритме обхода дерева "Эстафета хвоста".
Hrethgir 12.07.2026
Проблема была в том, что удалялась именно новая кнопка, а не старая. Ни один ИИ не обнаружил это, а сам я смог только когда с работой стало попроще и когда заставил работать будущее автономное. . .
сукцессия 25. Хронология ошибок
anaschu 12.07.2026
# От 50-тонного гриба до устойчивого леса: хроника ошибок при построении модели вековой сукцессии микоризы ## О чём эта статья В процессе построения ОДУ-модели (система дифференциальных. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru