Russian Qt Forum
Ноябрь 22, 2024, 09:19 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: 1 2 [3] 4 5 ... 17   Вниз
  Печать  
Автор Тема: Igors, это ты? :)  (Прочитано 131939 раз)
_Bers
Бывалый
*****
Offline Offline

Сообщений: 486


Просмотр профиля
« Ответ #30 : Август 21, 2018, 12:51 »


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

Не нужно. До какой-то версии QThread::run был вообще pure virtual.

приведите пример "не нужности"
я сам помниццо, наступил на эти грабли, и пинал вручную евент-луп.


1. http://doc.qt.io/qt-5/qthread.html#create
2. берете и переопреляете run() и не нужен никакой эвентлуп из 7 залуп

и этот новый тред не получает сигналов.

а что бы получал, придется мало мало залупиццо.

вообще, даже вот по этой ссылке видно,
как черезжопно завязанно все в куте на системе сообщений.

мне что б тупо сделать отдельный тред нужно от чего то там наследоваться?
и пинать в ручную евент-луп.

вместо одной простоq строки: std::thread(threadFunction).detach();

сама по себе технология слотов-сигналов - ущербное унылое г.

если я захочу послать объектам сообщение, я сделаю:

Код:
struct message { /* любые поля и методы */ };

const message msg{ /*intialization*/ };

send_message(msg); // <--- все кто подписан на message (или на имена мемберов посылки)
// получат это сообщение

разруливается времени компиляции. и для этого мне не нужны никакие моки.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #31 : Август 21, 2018, 14:51 »

Пример

- сделать 2 нитки, одна принимает символ с клавы, другая печатает

Сделать это пуляя Qt сигналами - не вопрос, а вот на std - придется изрядно попыхтеть.
попыхтеть?

Код:
std::thread(processKeyboard).detach();
std::thread(processPrinter).detach();

это конечно неиллюзорно трудно!
А что делает этот detach? Теперь нитка не может быть joined - зачем? И что это дает? Да ничего, наоборот, добавляет проблем

зачем вообщще нужны нитки вы в курсе?
чем более они независимые в контексте решаемой задачи - тем лучше.
это как бе азбука "фри-лок" алгоритмов.
Ну а lock-free то здесь причем? И что это за (не)зависимость такая? Разве команды не выполняются параллельно (simultaneously как говорят буржуи) при наличии 2 и более ядер?

На всякий случай повторю задачку
Цитировать
- сделать 2 нитки, одна принимает символ с клавы, другая печатает
Прошу исполнить на чудесном std
Записан
_Bers
Бывалый
*****
Offline Offline

Сообщений: 486


Просмотр профиля
« Ответ #32 : Август 21, 2018, 15:21 »

А что делает этот detach?
детачит тред. внезапно, да?

Теперь нитка не может быть joined - зачем? И что это дает? Да ничего, наоборот, добавляет проблем
если вам ничего не дает - можете и не детачить.
никто как бе и не заставляет.
однако в большинстве случаев одиночные треды как раз таки юзают в свободном плаваньи.
а там, где все таки нужен объект связанный с тредом, уже просится тред-пул,
а не тред-одиночка.



Ну а lock-free то здесь причем? И что это за (не)зависимость такая?

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

очевидно, что чем больше в программе встречаются вот таких вот мутексов,
тем медленнее будет работать вся система.

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

структуры данных и алгоритмы, которые обеспечивают безопасную работу в условиях многопоточности,
без использования примитивов синхронизации,
в простонорадье называют "lock-free"

На всякий случай повторю задачку
сделать 2 нитки, одна принимает символ с клавы, другая печатает
Прошу исполнить на чудесном std


я же уше выше показал как это можно сделать:
Код:
std::thread(processKeyboard).detach();
std::thread(processPrinter).detach();

и не нужно ничего ни от кого наследовать,
и переопределять какоё то дураццкий run,
и завязываться на дураццкие не нужные слоты-сигналы,
только для того, что бы тред заработал.

QT - слишком многословный.
приходится печатать много буковок за ради простых вещей.
« Последнее редактирование: Август 21, 2018, 15:23 от _Bers » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #33 : Август 21, 2018, 16:16 »

я же уше выше показал как это можно сделать:
Код:
std::thread(processKeyboard).detach();
std::thread(processPrinter).detach();

и не нужно ничего ни от кого наследовать,
и переопределять какоё то дураццкий run,
и завязываться на дураццкие не нужные слоты-сигналы,
только для того, что бы тред заработал.
И что  Непонимающий Как это поможет? Напр "печатающей" нитке нужно знать что символ "готов" и его можно печатать. В Qt c помощью тех самых "дураццких" сигналов это легко сделать и новичку (кстати и перекрывать ничего не надо). А вот как на std - покажите
Записан
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3260


Просмотр профиля
« Ответ #34 : Август 21, 2018, 16:53 »


и этот новый тред не получает сигналов.

а что бы получал, придется мало мало залупиццо.

вообще, даже вот по этой ссылке видно,
как черезжопно завязанно все в куте на системе сообщений.

мне что б тупо сделать отдельный тред нужно от чего то там наследоваться?
и пинать в ручную евент-луп.

вместо одной простоq строки: std::thread(threadFunction).detach();

сама по себе технология слотов-сигналов - ущербное унылое г.

если я захочу послать объектам сообщение, я сделаю:

Вы сами себе противоречите, то вам нужны сигнал-слоты и приходится чо-то там делать с эвентлупом, то не нужны. Какие слоты в std::thread??
Записан
_Bers
Бывалый
*****
Offline Offline

Сообщений: 486


Просмотр профиля
« Ответ #35 : Август 22, 2018, 11:47 »

И что  Непонимающий Как это поможет? Напр "печатающей" нитке нужно знать что символ "готов" и его можно печатать.
печатающая нитка сама знает, когда готовы её данные
потому что она отвечает за их подготовку.
« Последнее редактирование: Август 22, 2018, 11:53 от _Bers » Записан
_Bers
Бывалый
*****
Offline Offline

Сообщений: 486


Просмотр профиля
« Ответ #36 : Август 22, 2018, 11:53 »


и этот новый тред не получает сигналов.

а что бы получал, придется мало мало залупиццо.

вообще, даже вот по этой ссылке видно,
как черезжопно завязанно все в куте на системе сообщений.

мне что б тупо сделать отдельный тред нужно от чего то там наследоваться?
и пинать в ручную евент-луп.

вместо одной простоq строки: std::thread(threadFunction).detach();

сама по себе технология слотов-сигналов - ущербное унылое г.

если я захочу послать объектам сообщение, я сделаю:

Вы сами себе противоречите, то вам нужны сигнал-слоты и приходится чо-то там делать с эвентлупом, то не нужны. Какие слоты в std::thread??


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

Какие слоты в std::thread??

std::function<type> должно хватить всем.
для особых ценителей есть boost::signals2

мне он не нра. слишком многословный.
предпочитаю свою собственную event-system,
которая разруливает всю коммуникацию времени компиляции,
и не вынуждает хранить какие то объекты, или от чего то там наследоваццо.

но на практике в 99% за глаза хватает std::function<type>
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #37 : Август 22, 2018, 13:12 »

печатающая нитка сама знает, когда готовы её данные
потому что она отвечает за их подготовку.
Похоже "включается непонималка".
Цитировать
- сделать 2 нитки, одна принимает символ с клавы, другая печатает
Разумеется "печатает тот самый символ что первая приняла с клавы" (неудобно разжевывать). Поэтому ничего она не знает, символ надо как-то передавать. Как Вы это сделаете средствами std ?
Записан
_Bers
Бывалый
*****
Offline Offline

Сообщений: 486


Просмотр профиля
« Ответ #38 : Август 22, 2018, 14:06 »

Похоже "включается непонималка".
Цитировать
- сделать 2 нитки, одна принимает символ с клавы, другая печатает
Разумеется "печатает тот самый символ что первая приняла с клавы" (неудобно разжевывать). Поэтому ничего она не знает, символ надо как-то передавать. Как Вы это сделаете средствами std ?

это что за бред?
вам нафига два потока, если согласно вашему алгоритму,
юзаться потоки должны последовательно?


ну ок. тогда так:

Код:
tools::thread_pool pool;

const auto proccessKey = [](const auto& key) { /*...*/ };

const auto inputKey = [&pool]()
{
    const auto key = keyboard();

    if(check_need_exit(key))
        pool.stop();
    else
        pool.add_task(proccessKey, key);
};

pool.add_task(inputKey);
pool.start();

pool.wait_stop_all();
« Последнее редактирование: Август 22, 2018, 14:24 от _Bers » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #39 : Август 23, 2018, 16:29 »

ну ок. тогда так:
По меньшей мере трижды было сказано "сделать 2 нитки" - а Вы лепите пул, это совсем не одно и то же. И разве tools::thread_pool - штатное средство std? Где же богатырская сила если для студенческой лабы "производитель-потребитель" уже приходится привлекать сторонние зависимости?

вам нафига два потока, если согласно вашему алгоритму,
юзаться потоки должны последовательно?
Профессионал не спрашивает отчего да почему и не критикует задачу, он просто ее делает. А умельцев типа "как не делать (и обосновать)" всегда было и будет с избытком и без нас  Улыбающийся

это что за бред?
Грубость ни к чему
Записан
_Bers
Бывалый
*****
Offline Offline

Сообщений: 486


Просмотр профиля
« Ответ #40 : Август 27, 2018, 11:49 »

По меньшей мере трижды было сказано "сделать 2 нитки" - а Вы лепите пул, это совсем не одно и то же. И разве tools::thread_pool - штатное средство std? Где же богатырская сила если для студенческой лабы "производитель-потребитель" уже приходится привлекать сторонние зависимости?
вы можете хоть 10 раз сказать: "мне нужны именно нитки",
но лично я не полезу на первый этаж через чердак,
если могу зайти через парадные двери.

tools::thread_pool - тонкая обертка над std::thread и std::conditional_variable.

если вам хочется глянуть, что там под капотом:
https://en.cppreference.com/w/cpp/thread/condition_variable


Код:
#include <iostream>
#include <string>
#include <thread>
#include <mutex>
#include <condition_variable>
 
std::mutex m;
std::condition_variable cv;
std::string data;
bool ready = false;
bool processed = false;
 
void worker_thread()
{
    // Wait until main() sends data
    std::unique_lock<std::mutex> lk(m);
    cv.wait(lk, []{return ready;});
 
    // after the wait, we own the lock.
    std::cout << "Worker thread is processing data\n";
    data += " after processing";
 
    // Send data back to main()
    processed = true;
    std::cout << "Worker thread signals data processing completed\n";
 
    // Manual unlocking is done before notifying, to avoid waking up
    // the waiting thread only to block again (see notify_one for details)
    lk.unlock();
    cv.notify_one();
}
 
int main()
{
    std::thread worker(worker_thread);
 
    data = "Example data";
    // send data to the worker thread
    {
        std::lock_guard<std::mutex> lk(m);
        ready = true;
        std::cout << "main() signals data ready for processing\n";
    }
    cv.notify_one();
 
    // wait for the worker
    {
        std::unique_lock<std::mutex> lk(m);
        cv.wait(lk, []{return processed;});
    }
    std::cout << "Back in main(), data = " << data << '\n';
 
    worker.join();
}

как видите - смысл принципиально не изменился.
вообще, по опыту заметил: есть два класса задач для мультипоточности.
там где нужен одиночно-детачнутый тред, или там где нужен тред-пул.

Профессионал не спрашивает отчего да почему и не критикует задачу, он просто ее делает.

нет. профессионал всегда исходит из "отчего и почему",
он именно что критикует задачу.
вырабатывая наименее трудозатратное по времени и деньгам решение.

"написать код не сложно. сложно понять какую на самом деле задачу нужно решить"
(ц) Макконелл. "Идеальный код"

это что за бред?
Грубость ни к чему

бред - неадекватное, не соответствующее (либо противоречиещее объективной реальности)
виденье положения вещей.

в данном случае: притянутая за уши попытка навязать мультипоточное решение,
для алгоритма, которому это нафиг не нужно.
потому что согласно изначальной постановки задачи,
исполнение алгоритма должно быть последовательным,
а не параллельным.

правильно ваша задача решается так:
Код:
for(auto key = waitKey(); !needExit(key); key = waitKey())
    print(key);

подождали, распечатали. ждем дальше
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #41 : Август 27, 2018, 13:09 »

но лично я не полезу на первый этаж через чердак,
При работе с пользователями чердак - еще не худший вариант  Улыбающийся

если вам хочется глянуть, что там под капотом:
https://en.cppreference.com/w/cpp/thread/condition_variable


Код:
#include <iostream>
#include <string>
#include <thread>
#include <mutex>
#include <condition_variable>
 
std::mutex m;
std::condition_variable cv;
std::string data;
bool ready = false;
bool processed = false;
 
void worker_thread()
{
    // Wait until main() sends data
    std::unique_lock<std::mutex> lk(m);
    cv.wait(lk, []{return ready;});
 
    // after the wait, we own the lock.
    std::cout << "Worker thread is processing data\n";
    data += " after processing";
 
    // Send data back to main()
    processed = true;
    std::cout << "Worker thread signals data processing completed\n";
 
    // Manual unlocking is done before notifying, to avoid waking up
    // the waiting thread only to block again (see notify_one for details)
    lk.unlock();
    cv.notify_one();
}
 
int main()
{
    std::thread worker(worker_thread);
 
    data = "Example data";
    // send data to the worker thread
    {
        std::lock_guard<std::mutex> lk(m);
        ready = true;
        std::cout << "main() signals data ready for processing\n";
    }
    cv.notify_one();
 
    // wait for the worker
    {
        std::unique_lock<std::mutex> lk(m);
        cv.wait(lk, []{return processed;});
    }
    std::cout << "Back in main(), data = " << data << '\n';
 
    worker.join();
}

как видите - смысл принципиально не изменился.
По-моему этот пример так же неверен как и этот

Допустим thread стартует с солидной задержкой и главная нитка успела выполнить  cv.notify_one() - но на мутексе еще никто не ждет. Или worker был вытеснен и не успел с cv.wait, Тогда побудка notify_one не имеет эффекта. А когда worker наконец получит управление и отдастся на мутекс - его будет некому будить.

Ну это как я знаю - а может в std это уже не так? Глянул доку

Цитировать
The effects of notify_one()/notify_all() and each of the three atomic parts of wait()/wait_for()/wait_until() (unlock+wait, wakeup, and lock) take place in a single total order that can be viewed as modification order of an atomic variable: the order is specific to this individual condition_variable. This makes it impossible for notify_one() to, for example, be delayed and unblock a thread that started waiting just after the call to notify_one() was made.

The notifying thread does not need to hold the lock on the same mutex as the one held by the waiting thread(s); in fact doing so is a pessimization, since the notified thread would immediately block again, waiting for the notifying thread to release the lock.
С собсно переводом - проблем нет, но смысл доходит плохо. Хреново сформулировано (язык ни при чем)

Или я где-то ошибаюсь?
« Последнее редактирование: Август 27, 2018, 13:11 от Igors » Записан
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3260


Просмотр профиля
« Ответ #42 : Август 27, 2018, 14:59 »

В код особо не вчитывался, но навскидку возможно тут надо два cv а с одним могут быть баги\дедлоки.
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #43 : Август 27, 2018, 19:52 »

Допустим thread стартует с солидной задержкой и главная нитка успела выполнить  cv.notify_one() - но на мутексе еще никто не ждет. Или worker был вытеснен и не успел с cv.wait, Тогда побудка notify_one не имеет эффекта. А когда worker наконец получит управление и отдастся на мутекс - его будет некому будить.
Вы так и не разобрались как работают условные переменные? Мы же это несколько раз разбирали. Улыбающийся

Ничего не будет из-за того, что главная нитка успеет выполнить cv.notify_one(), когда его никто не ждет. Если это произойдет, воркер даже не станет на wait, а сразу пойдет дальше.
Записан
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3260


Просмотр профиля
« Ответ #44 : Август 27, 2018, 21:59 »

А, там прекондишн проверяется через эти модные лямбды. Ну ок.
Записан
Страниц: 1 2 [3] 4 5 ... 17   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.063 секунд. Запросов: 23.