Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Абстрактная фабрика

311
27 июля 2017 года
plastictown
309 / / 08.01.2006
Доброго времени суток! Хочу создать абстрактную фабрику для объектов, реализующих некоторый функционал каждый в своем потоке, т.е. владеющих своим потоком и выполняемым методом.
Получается примерно так:
Абстрактный поток:
Код:
class Thread{
public:
    explicit Thread(int id);
    Thread(const Thread&)=delete;
    Thread()=delete;
    Thread(const Thread&&)=delete;
    virtual void start()=0;
    virtual void stop()=0;
    virtual ~Thread(){}
protected:
    unique_ptr<int>             m_id;
    unique_ptr<atomic<bool>>    m_stopflag;
    unique_ptr<std::thread>     m_thread;
    //virtual void run()=0;
};
Чуть менее абстрактный поток (реализующий запуск и остановку потока) реализацию не привожу, она довольно проста:
Код:
class Worker: public Thread
{
public:
    Worker(const Worker&)=delete;
    Worker(Worker&&)=delete;
    Worker()=delete;
    Worker(int id);
    void start();
    void stop();
    virtual ~Worker();
protected:
    virtual void run()=0;
};
Вот тут появляется вопрос. Как сделать так, чтобы исполняемый метод run() мог в каждом конкретном классе иметь свой набор аргуметнов или метод start() принимал бы необходимый метод с аргументами? Т.е. суть проблемы, в недостаточном понимании синтаксиса языка.

Пока что использую так:
Код:
class Printer: public Worker
{
public:
    Printer(int id, atomic<int>& val): Worker(id), m_val(val)
    {

    }
protected:
    atomic<int>& m_val;
    void run()
    {
        while(m_stopflag->load())
        {
           cout << m_val.load() << endl;
            this_thread::sleep_for(std::chrono::milliseconds(200));
        }
    }
};

Использование в main():
Код:
//...

atomic<int> ai;
    atomic_init(&ai, 0);

    unique_ptr<Worker> inc(new Incrementer(1, ai));
    unique_ptr<Worker> dcr(new Decrementer(2, ai));
    unique_ptr<Worker> prt(new Printer(3, ai));

    inc->start();
    dcr->start();
    prt->start();

//...
В этом примере необходимость фабрики неочевидна, однако, если это будут потоки обработки запросов клиента разного рода, тогда, учитывая "использование new непосредственно в коде не рекомендуется", фабрика будет очень кстати.
Заранее спасибо!
  • Я не профи в С#. Но могли бы вы сказать, что значит "=delete;" в строке: Thread(const Thread&)=delete; ? от Charley, 29 июля 2017 года
260
27 июля 2017 года
Ramon
1.1K / / 16.08.2003
А может стоит сначала определиться собственно какую задачу решаем?
Ибо ну наделали вы активных объектов, ок. А для чего?
Запросы обрабатывать? Ну завалят вас запросами, наплодите вы потоков, машина ляжет...
Это мы еще не говорим о том что синхронизировать эти потоки вы ляжете.
311
28 июля 2017 года
plastictown
309 / / 08.01.2006
Цитата: Ramon
А может стоит сначала определиться собственно какую задачу решаем?
Ибо ну наделали вы активных объектов, ок. А для чего?
Запросы обрабатывать? Ну завалят вас запросами, наплодите вы потоков, машина ляжет...
Это мы еще не говорим о том что синхронизировать эти потоки вы ляжете.

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

260
28 июля 2017 года
Ramon
1.1K / / 16.08.2003
Цитата: plastictown

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

Т.н. "паттерны" бесполезны, особенно для решения абстрактных задач.
А машина ляжет потому что планирование и диспетчеризация потоков - вещи не бесплатные.

PS: Но кого сейчас волнуют такие мелочи как планирование, диспетчеризация и прочая мутная шняга...

311
28 июля 2017 года
plastictown
309 / / 08.01.2006
Цитата: Ramon

Т.н. "паттерны" бесполезны, особенно для решения абстрактных задач.
А машина ляжет потому что планирование и диспетчеризация потоков - вещи не бесплатные.

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

Сегодня буду пытаться повесить машину.-)

И все-таки как же перегрузить виртуальный метод, чтобы в разных наследниках были разные аргументы? Безотносительно к моему коду. Я уже подумываю, не передавать ли vector<std::any> параметром или вроде того

311
29 июля 2017 года
plastictown
309 / / 08.01.2006
Цитата:
Я не профи в С#. Но могли бы вы сказать, что значит "=delete;" в строке: Thread(const Thread&)=delete;

Может быть, вы заметили, что это C++. Эти строчки нужны для указания, что данные конструкторы вызывать нельзя. Хотя в данном случае у меня определен конструктор с одним аргументом, соответственно, эти конструкторы автоматически отваливаются. Но это для ясности.

311
30 июля 2017 года
plastictown
309 / / 08.01.2006
Цитата: Ramon

Ну завалят вас запросами, наплодите вы потоков, машина ляжет...
Это мы еще не говорим о том что синхронизировать эти потоки вы ляжете.

Честно пытался повесить если не систему, то хотя бы приложение. Взял венду. Пытался создать 100000 потоков и не дождался их создания, ибо при ~45000 процесс ест 1,5 гига (всего 12) памяти и новые потоки создаются жутко медленно (по 10-15 в секунду). На работу остальной системы никак не повлияло. Единственные проблемы возникли с диспетчеризацией, потому что она отвратительна. Даже при 100 потоках, многие из них вообще не получают времени (конечно, если оставить это дело на пару суток, м/б диспетчер добрался бы до всех, однако, в течение нескольких минут дела довольно плохо). Наверное, придется писать менеджер, который будет запускать потоки по очереди. Короче говоря, положить машину не получается.

260
30 июля 2017 года
Ramon
1.1K / / 16.08.2003
Цитата: plastictown
Цитата: Ramon

Ну завалят вас запросами, наплодите вы потоков, машина ляжет...
Это мы еще не говорим о том что синхронизировать эти потоки вы ляжете.

Честно пытался повесить если не систему, то хотя бы приложение. Взял венду. Пытался создать 100000 потоков и не дождался их создания, ибо при ~45000 процесс ест 1,5 гига (всего 12) памяти и новые потоки создаются жутко медленно (по 10-15 в секунду). На работу остальной системы никак не повлияло. Единственные проблемы возникли с диспетчеризацией, потому что она отвратительна. Даже при 100 потоках, многие из них вообще не получают времени (конечно, если оставить это дело на пару суток, м/б диспетчер добрался бы до всех, однако, в течение нескольких минут дела довольно плохо). Наверное, придется писать менеджер, который будет запускать потоки по очереди. Короче говоря, положить машину не получается.

Пара вопросов из зала.
Потоки хоть что-то делали или тупо спали?
Ну и самое интересное: а для чего вам потоки? чего вы с их помощью пытаетесь добиться?

PS: Не влиять ни на что оно не может ибо в NT планировка system-wide.

311
30 июля 2017 года
plastictown
309 / / 08.01.2006
Цитата: Ramon

Пара вопросов из зала.
Потоки хоть что-то делали или тупо спали?
Ну и самое интересное: а для чего вам потоки? чего вы с их помощью пытаетесь добиться?
PS: Не влиять ни на что оно не может ибо в NT планировка system-wide.

• На самом деле я просто учусь тому, чего за свою АСУшную практику применять не приходилось. Сейчас есть время и желание отойти от АСУ ТП в сторону десктопа или системного програмирования под Линукс (на си, соответственно). Пока занимаюсь исключительно ООП и C++. Новые стандарты, boost по праздникам и т.д.

• Потоки у меня сортировали вектор интов (один на всех), синхронизировались мьютексом. Код процедуры потока:

 
Код:
while(m_stopflag->load())
        {
            mtx.lock();
            reverse(m_array.begin(), m_array.end());
            //cout << "id: " << *m_id << "t - tsort()" << endl;
            sort(m_array.begin(), m_array.end());
            mtx.unlock();
            //std::this_thread::yield();
        }
Ну и вот эта штука полностью занимает одно ядро, а все остальное, видимо, работает на втором, но, как я сказал, я не заметил снижения производительности по крайней мере визуально.
260
31 июля 2017 года
Ramon
1.1K / / 16.08.2003
В данном случае наличие одной блокировки на всех говорит о том, что все остальные потоки, кроме одного, ничего не делают, а именно спят и в процессах планировки/диспетчеризации участвуют, по большей части, только на момент создания.

PS: Мой вам совет, не лезьте в "системное", оно сдохло и уже даже не воняет. Смотрите лучше в сторону иных областей.
311
31 июля 2017 года
plastictown
309 / / 08.01.2006
Цитата: Ramon
В данном случае наличие одной блокировки на всех говорит о том, что все остальные потоки, кроме одного, ничего не делают, а именно спят и в процессах планировки/диспетчеризации участвуют, по большей части, только на момент создания.

PS: Мой вам совет, не лезьте в "системное", оно сдохло и уже даже не воняет. Смотрите лучше в сторону иных областей.

Дал каждому потоку свой вектор и убрал блкировки. Проц загрузился на 100%, памяти 3Гб и больше ~7000 потоков как-то не создается. Система подтормаживает, но работает, а новые потоки не создаются больше. Можно считать на этом месте, что софтина сдохла, но система со скрипом, но работает:)

ЗЫ: Не за идею же работаем (хотя всякое бывает. я за идею наработался, теперь хочу за деньги). Пусть будет дохлое, если будут достаточно платить - отчего бы не поработать. Вакансии редко, но бывают вроде создателя модулей ядра. Но в общем и целом, конечно, думаю, что стоит закончить с этим и заняться Qt, например. Можно даже отвалить 50 рублей в Специалист, чтобы за 8 дней популярно объяснили что к чему. Плюс бумажка.

74K
31 июля 2017 года
pressi
2 / / 31.07.2017
хм..
311
31 июля 2017 года
plastictown
309 / / 08.01.2006
Цитата: pressi
хм..

Трудно не согласиться:)

Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог