@ProCxx

Страница 2256 из 2477
Azoyan
03.08.2018
16:30:28
Мопед не мой

Ilia
03.08.2018
16:31:11
ты мне? примерно так) http://cpp.sh/9ovox
Легче сделать новый блок и там сделать ссылку на новую переменную с именем старой переменной.

Erik
03.08.2018
17:48:46
Всем добрый вечер. Нужна ваша помощь. Битый час сижу голову ломаю. Вот есть пример пула задачь: https://github.com/mtrebi/thread-pool В все вроде достаточно знакомо. Ни разу с подобными пулами небыло проблем, пока не захотел вставить туда shared_ptr. Вот мини пример. void func(std::shared_ptr<uint64_t> ptr) { std::cout << "func: " << *ptr << "; " << "ptr use count: " << ptr.use_count() << std::endl; } int main() { ThreadPool pool(2); pool.init(); auto ptr = std::make_shared<uint64_t>(20); std::cout << "First use count: " << ptr.use_count() << std::endl; auto res = pool.submit(func, ptr); res.get(); std::cout << "Last use count: " << ptr.use_count() << std::endl; pool.shutdown(); }Что умудряется тут увеличить счетчик у ptr на 1 лишний раз? Может и не лишний, но почему-то счетчик не возвращается снова к 1 после выполнения задачи из очереди и успешного ее извлечения. Подозрение падает именно на то, что происходит функции submit. Вывод программы: First use count: 1 func: 20; ptr use count: 3 Last use count: 2

---------------------------------- А вот сама функция submit: template<typename F, typename...Args> auto submit(F&& f, Args&&... args) -> std::future<decltype(f(args...))> { std::function<decltype(f(args...))()> func = std::bind(std::forward<F>(f), std::forward<Args>(args)...); auto task_ptr = std::make_shared<std::packaged_task<decltype(f(args...))()>>(func); std::function<void()> wrapper_func = [task_ptr]() { (*task_ptr)(); }; m_queue.enqueue(wrapperfunc); m_conditional_lock.notify_one(); return task_ptr->get_future(); }

Google
Erik
03.08.2018
18:15:21
в каком месте смущает use_count? там где 3?
И там где 2. Задача то выполнилась и была извлечена из очереди.

Alexander
03.08.2018
18:16:47
И там где 2. Задача то выполнилась и была извлечена из очереди.
при создании функтора копируется std::shared_ptr

std::function<decltype(f(args...))()> func = std::bind(std::forward<F>(f), std::forward<Args>(args)...);

Mikhail Voronov
03.08.2018
18:19:13
std::function<void()> wrapper_func = [task_ptr]() { (*task_ptr)(); }; m_queue.enqueue(wrapperfunc); в последней строчке _ не пропущено случайно?

Erik
03.08.2018
18:20:11
при создании функтора копируется std::shared_ptr
Да, согласен. Этот функтор потом попадает в очередь. Когда задача выполниться, из очереди функтор в packaged_task извлекается. Почему счетчик остается равный 2-м? Вот что непонятно.

Alexander
03.08.2018
18:20:52
так то есть уже вас 3ка не смущает?

окей, теперь разбираемся с 2-кой

Erik
03.08.2018
18:33:04
bool dequeue(T& t) { std::unique_lock<std::mutex> lock(m_mutex); if (m_queue.empty()) { return false; } t = std::move(m_queue.front()); m_queue.pop(); return true; }

Mikhail Voronov
03.08.2018
18:35:16
а он точно перед последним std::cout вызывается?

Google
/dev
03.08.2018
18:40:59
ну-у-у-у, так не интересно
foo bar; if(bla) { undefine bar; } foo /// wtf???

Dmitry
03.08.2018
18:41:22
я пока что не понял мотивации для ввода такого синтаксиса, если честно. Потому что хочу?
Ну вроде как даже Страуструп высказывался по поводу move что он не совсем move а просто cast. Т.е. без borrow check язык позволяет использовать moved переменную.

Erik
03.08.2018
18:42:02
а он точно перед последним std::cout вызывается?
Это происходит внутри ThreadPool. Если есть задача в очереди - она автоматически извлекается dequeue. Потом она уже выполняется. И результат записывается в std::future. (В примере это переменная `res`). Также в примере стоит ожидание результата в std::future ( res.get() ). Вывод уже после этого - значит извлечение точно уже было из очереди. :)

Dmitry
03.08.2018
18:43:53
Erik
03.08.2018
18:47:24
Если написать вот такой код, то все работает как и должно было бы работать в хорошем случае. ? void func(std::shared_ptr<uint64_t> ptr){ std::cout << "func: " << *ptr << "; " << "ptr use count: " << ptr.use_count() << std::endl; } int main() { auto ptr = std::make_shared<uint64_t>(20); { ThreadPool pool(2); pool.init(); std::cout << "First use count: " << ptr.use_count() << std::endl; auto res = pool.submit(func, ptr); //.post(func, ptr); res.wait(); pool.shutdown(); } std::cout << "Last use count: " << ptr.use_count() << std::endl; }

First use count: 1 func: 20; ptr use count: 3 Last use count: 1

Но это явно какой-то странный метод борьбы с утечкой :)

Alexander
03.08.2018
18:54:35
то есть тредпул у себя всё же прихранивает?

Azoyan
03.08.2018
18:59:57
foo bar; if(bla) { undefine bar; } foo /// wtf???
Да как бы я в курсе

Aidar
03.08.2018
19:00:58
Какой нахрен init

Я знаю почему там 3

Aidar
03.08.2018
19:05:44
Почему 2 хз

3 потомучто bind хранит значение

Erik
03.08.2018
19:08:11
похоже проблема всё-таки из-за локальной переменной std::function<void()> func в ThreadWorker::operator() - она вполне может быть не удалена на момент вызова последнего std::cout
Это срорее всего не так. Вот такое изменение сделать если if (dequeued) { func(); std::function<void()> f_tmp; std::swap(func, f_tmp); }то func точно уже ничего хранить не будет :) Но пример выдает тоже самое.

Constantine
03.08.2018
19:10:31
Хочу объявить базовый класс, по сути являющийся концептом для policy (инстанцирование запрещено), как это нормально сделать? delete на деструктор дает варнинги у потомков

Aidar
03.08.2018
19:10:56
packaged_task умирает после того как в future появилось знаение

Erik
03.08.2018
19:11:45
packaged_task умирает после того как в future появилось знаение
Если так, то тогда где потеряный экземпляр std::sharead_ptr не понятно :(\

Google
Mikhail Voronov
03.08.2018
19:11:54
Это срорее всего не так. Вот такое изменение сделать если if (dequeued) { func(); std::function<void()> f_tmp; std::swap(func, f_tmp); }то func точно уже ничего хранить не будет :) Но пример выдает тоже самое.
так многопоточность же. get() вернёт управление, когда будет готов результат - если позапускать несколько раз то в Ваешм случае будут результаты и 1 тоже, особенно если слип добавить

Aidar
03.08.2018
19:11:55
Какой потерянный?

Constantine
03.08.2018
19:12:17
protected конструктор?
никакой потомок не создается

Constantine
03.08.2018
19:12:47
protected destructor
это точно аналогично deleted деструктору? подумай, айдар

Aidar
03.08.2018
19:12:52
Нет

Это не аналогично

Constantine
03.08.2018
19:13:12
я хочу эффект удаленного приватного деструктора - класс и никакой потомок не может быть инстанцирован

Aidar
03.08.2018
19:13:20
Хм

Erik
03.08.2018
19:13:29
Какой потерянный?
std::cout << "Last use count: " << ptr.use_count() << std::endl;возвращает 2, после тогда как уже был вызван .get()

Aidar
03.08.2018
19:13:31
А от полиси ващето надо наследоваться

По александреску

Так что хз

Aidar
03.08.2018
19:14:01
Пекеджед

У тебя нет ожидания умирания таска

У тебя есть ожидание получения значения

Erik
03.08.2018
19:14:40
Тогда ещё не сдох таск
Да, но только, как? Если из очереди уже прошло извлечение .pop

Google
Aidar
03.08.2018
19:14:49
Где

Constantine
03.08.2018
19:15:46
Хм... можно объявить чисто виртуальную final функцию

Erik
03.08.2018
19:17:27
Где
ThreadPool извлекает задачу из очереди командой dequeue. Эта функция сразу вызывает .pop.

Dmitry
03.08.2018
19:17:38
Да, сочетание virtual final и abstract та ещё загадка для компилятора :)))

Aidar
03.08.2018
19:17:41
Покажи где ты ожидаешь dequeue

Я не увидел

/dev
03.08.2018
19:18:45
Да, сочетание virtual final и abstract та ещё загадка для компилятора :)))
Для компилятора загадки тут нет. Есть загадка для коллег, что курил товарищ

Erik
03.08.2018
19:18:49
Покажи где ты ожидаешь dequeue
Это в реализации ThreadPool -а - точнее ThreadWorker.

Aidar
03.08.2018
19:18:54
Покажи где

Ты ждёшь фьючер из пекеджед таск

Но не dequeue

Mikhail Voronov
03.08.2018
19:20:27
Это в реализации ThreadPool -а - точнее ThreadWorker.
попробуйте оставить swap и Sleep(1000) перед последним std::cout - мат ожидание результата будет -> 1

Aidar
03.08.2018
19:20:32
Потенциально dequeue может завершиться позже а может и раньше того что второй поток просигналится

Erik
03.08.2018
19:22:39
Покажи где
https://github.com/mtrebi/thread-pool/blob/master/include/ThreadPool.h строка 33 Да, submit мне возвращает соответсвующий std::future. В main.cpp я жду когда в std::future появится результат res.get(). К этому моменту из очереди dequeue уже точно должен был извлечь и выполнить нужную операцию.

Aidar
03.08.2018
19:22:52
Ну ок тут это не dequeue а кусок цикла воркера

Несуть

Google
Mikhail Voronov
03.08.2018
19:25:13
Aidar
03.08.2018
19:25:19
Молодец

Mikhail Voronov
03.08.2018
19:25:53
тут не я молодец, а автор вопроса теряет время)

Aidar
03.08.2018
19:26:08
Либа так себе

Какой нахрен init

Руки оторвать

Dmitry
03.08.2018
19:26:46
Может проблема в том что get future зовётся с гонкой?

Constantine
03.08.2018
19:26:49
Для компилятора загадки тут нет. Есть загадка для коллег, что курил товарищ
Для коллег не загадка, что я предпочитаю не писать комментарии "пожалуйста, не инстанцируйте этот класс" :)

Dmitry
03.08.2018
19:31:36
Флаг остановки не атомик

И ещё future overdesign

Aidar
03.08.2018
19:32:18
decltype(f(args...)) Foo=f(forward(args)...)

Dmitry
03.08.2018
19:32:40
Это опция которую можно в таск завернуть снаружи.

Constantine
03.08.2018
19:37:35

Страница 2256 из 2477