Форум программистов, компьютерный форум, киберфорум
C++
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.73/11: Рейтинг темы: голосов - 11, средняя оценка - 4.73
21 / 19 / 7
Регистрация: 14.03.2014
Сообщений: 249

Универсальная передача аргументов в потоках boost::thread

07.10.2017, 23:58. Показов 2031. Ответов 6
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Пишу обертку для потока и не могу организовать универсальную передачу аргументов, чтоб когда надо передовался по ссылке, а когда надо по значению. С stl потоками работает, если делать как сказано тут
а с бустом не хочет. Может кто знает где собака зарыта. Для краткости определение деструктора не привожу.

C++ (Qt)
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
class ManagedThread
{
   using bthread = boost::thread;
public:
   explicit ManagedThread():mActive( false) {}
   template<typename Function,typename... Args>
   void Binder( Function&& f,Args&&... _args);
   ~ManagedThread();
   bool isActive() const { return mActive; }
   bool isRunning() const
   {
       return atomic_load(&m_isRunning);
   }
   //ManagedThread() = delete;
   ManagedThread(const ManagedThread&) = delete;
   ManagedThread(const ManagedThread &&) = delete;
   ManagedThread& operator=(const ManagedThread&) = delete;
   ManagedThread& operator=(const ManagedThread&&) = delete;
private:
   volatile bool  mActive;
   //std::thread    mThread;
   /// Указатель на объект потока
   bthread * m_pthread;
   /// Флаг работы основного цикла потока
   std::atomic<bool> m_isRunning;
   void stop()
   {
       atomic_store(&m_isRunning, false);
   }
};
 
template< class Function, class... Args>
   void threadFunction( volatile bool& active_flag, Function& f, Args&&... args)
{
   active_flag = true;
   //f( std::forward<Args...>(args...));
   active_flag = false;
}
 
template<typename Function,typename... Args>
void   ManagedThread::Binder( Function&& f,Args&&... _args)
{
 
    m_pthread = new bthread(threadFunction<Function,Args...>,
                boost::ref(mActive),
                boost::ref(f),
                _args...);
    //std::thread * t1 = new std::thread(threadFunction<typename std::decay<Function>::type>,
    //                  std::ref(mActive),
    //                  std::forward<Function>(f));
    //threadFunction<Function>(mActive,std::forward<Function>(f));
}
0
Лучшие ответы (1)
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
07.10.2017, 23:58
Ответы с готовыми решениями:

Boost::thread std::thread
чем отличается boost::thread( ) от std::thread (с++17)? я спрашиваю не о способе реализации потоков в целом, а конкретно о этих функциях....

Boost::thread vs std::thread
Доброго времени суток, решил углубить свои знания, и решил почитать про потоки, бустовые и те что в 11 стандарте приняли, с бустом все ясно...

boost::thread
Здравствуйте. Есть два класса. Членом первого из классов является объект второго класса. В первом классе есть метод, в котором я хочу...

6
495 / 209 / 70
Регистрация: 27.05.2016
Сообщений: 557
08.10.2017, 17:50
С бустом не проверял, но мне кажется, что правильная реализация должна быть примерно такая:
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
#include <iostream>
#include <thread>
#include <functional>
#include <utility>
 
class ManagedThread
{
public:
    ManagedThread() = default;
    ManagedThread(const ManagedThread&) = delete;
    ManagedThread(const ManagedThread&&) = delete;
    ManagedThread& operator=(const ManagedThread&) = delete;
    ManagedThread& operator=(const ManagedThread&&) = delete;
 
    ~ManagedThread()
    {
        if (mThread.joinable())
            mThread.join();
    }
 
    template <typename Function, typename... Args>
    void Binder(Function&&, Args&&...);
 
private:
    std::thread mThread;
    volatile bool  mActive {false};
};
 
template <class Function, class... Args>
void threadFunction(volatile bool& active_flag, Function&& f, Args&&... args)
{
    active_flag = true;
    f(std::forward<Args>(args)...);
    active_flag = false;
}
 
template <typename Function, typename... Args>
void ManagedThread::Binder(Function&& f, Args&&... _args)
{
 
    mThread = std::move(std::thread(threadFunction<Function, Args...>, std::ref(mActive),
                                    std::forward<Function>(f), std::forward<Args>(_args)...));
 
}
 
void foo(int i, const std::string& text)
{
    std::cout << i << " " << text << "\n";
}
 
 
int main()
{
    ManagedThread mt;
    mt.Binder(&foo, 42, std::string("Hello"));
}
0
21 / 19 / 7
Регистрация: 14.03.2014
Сообщений: 249
10.10.2017, 11:47  [ТС]
Проблема решена.
Дело не в коде было.
Но конечный вариант привожу ниже
C++ (Qt)
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
#ifndef THREAD_H
#define THREAD_H
#include "common.h"
#include "error.h"
/// Таймаут ожидания при удаления потока
#define THREAD_TIMEOUT 250
 
class ManagedThread
{
   using bthread = boost::thread;
public:
   explicit ManagedThread():mActive( false) {m_pthread = nullptr;}
   template<typename Function,class Class, typename... Args>
   void Binder( Function&& f,Class&& obj, Args&&... _args);
   ~ManagedThread();
   bool isActive() const { return mActive; }
   bool isRunning() const
   {
       return atomic_load(&m_isRunning);
   }
   void Start()
   {
       atomic_store(&m_isRunning, true);
   }
   ManagedThread(const ManagedThread&) = delete;
   ManagedThread(const ManagedThread &&) = delete;
   ManagedThread& operator=(const ManagedThread&) = delete;
   ManagedThread& operator=(const ManagedThread&&) = delete;
private:
   volatile bool  mActive;
   /// Указатель на объект потока
   bthread * m_pthread;
   /// Флаг работы основного цикла потока
   std::atomic<bool> m_isRunning;
   void stop()
   {
       atomic_store(&m_isRunning, false);
   }
};
 
template< class Function, class Class, class... Args>
   void threadFunction(Function&& f,  Class&& obj, Args&&... _args)
{
   //active_flag = true;
   (obj->*f)(boost::forward<Args>(_args)...);
   //active_flag = false;
}
 
template<typename Function,class Class, typename... Args>
void   ManagedThread::Binder(Function&& f,Class&& obj, Args&&... _args)
{
 
    m_pthread = new bthread(threadFunction<Function, Class, Args...>,
                boost::forward<Function>(f),
                boost::forward<Class>(obj),
                boost::forward<Args>(_args)...);
}
 
#endif // THREAD_H
Добавлено через 7 часов 51 минуту
Для решения проблемы пришлось сделать 4 вещи:
1)Установить версию mingw32-64 4.8.3 так как полноценная поддержка вариативных шаблонов в буст потоках начиная с 4.8.1
2)Заново откомпилировать буст новым компилятором
3)Изменить натройки IDE Qt creator под новый компилятор
4)Изменить параметр BOOST_THREAD_VERSION в файле ./boost/thread/detail/config.hpp значение 4 (по умолчанию 2)
Программа компилируется со ВТОРОГО раза, а на первый получаю вот такую бяку:

D:\work\build-exness\lib\libboost_thread-mgw48-mt-1_55.a(thread.o):-1: ошибка: duplicate section `.data$_ZZN5boost16exception_detail27get _static_exception_objectINS0_14bad_excep tion_EEENS_13exception_ptrEvE2ep[__ZZN5boost16exception_detail27get_stati c_exception_objectINS0_14bad_exception_E EENS_13exception_ptrEvE2ep]' has different size
D:\work\build-exness\lib\libboost_thread-mgw48-mt-1_55.a(thread.o):-1: ошибка: duplicate section `.data$_ZZN5boost16exception_detail27get _static_exception_objectINS0_10bad_alloc _EEENS_13exception_ptrEvE2ep[__ZZN5boost16exception_detail27get_stati c_exception_objectINS0_10bad_alloc_EEENS _13exception_ptrEvE2ep]' has different size
D:\work\build-exness\lib\libboost_thread-mgw48-mt-1_55.a(thread.o):-1: ошибка: duplicate section `.data$_ZGVN5boost16exception_detail37ex ception_ptr_static_exception_objectINS0_ 14bad_exception_EE1eE[__ZGVN5boost16exception_detail37exceptio n_ptr_static_exception_objectINS0_14bad_ exception_EE1eE]' has different size

Уже устал ковыряться в бустовской канализации.
0
183 / 181 / 66
Регистрация: 15.02.2015
Сообщений: 515
10.10.2017, 12:40
В поток (std::thread / boost::thread) нельзя передавать параметры по ссылке (хоть универсальной), только по значению.
0
21 / 19 / 7
Регистрация: 14.03.2014
Сообщений: 249
10.10.2017, 12:58  [ТС]
Operok, Обоснуйте пожалуйста. Ваше утверждение выглядит нелепым.
boost/thread.hpp:
C++
1
2
3
4
5
6
7
8
9
10
11
12
#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
        template <class F, class Arg, class ...Args>
        thread(F&& f, Arg&& arg, Args&&... args) :
          thread_info(make_thread_info(
              thread_detail::decay_copy(boost::forward<F>(f)),
              thread_detail::decay_copy(boost::forward<Arg>(arg)),
              thread_detail::decay_copy(boost::forward<Args>(args))...)
          )
 
        {
          start_thread();
        }
0
183 / 181 / 66
Регистрация: 15.02.2015
Сообщений: 515
10.10.2017, 16:10
Лучший ответ Сообщение было отмечено Pechkin80 как решение

Решение

М.б. неверно выразился, передавать вы можете как вам угодно, только это всё будет скопировано в объект потока.
Boost.Thread tutorial
Для std::thread искать не буду, для этой темы не актуально.
1
21 / 19 / 7
Регистрация: 14.03.2014
Сообщений: 249
10.10.2017, 17:45  [ТС]
Operok, Ну так для этого классы обертки и существуют: boost::forward, boost::ref, boost::cref
Так как речь идёт о универсальной передачи, то используется boost::forward.

Добавлено через 13 минут
Operok, Я вам открою секрет, я использую в качестве аргумента Args... args ссылку на объект класса с удалённым конструктором копирования и содержащим внутри атомарные переменные. Если это по значению передавать, то будет мат перемат))))

Добавлено через 2 минуты
Operok, Пардон, не только там классы обертки, но и функции обертки.

Добавлено через 16 минут
Operok, По поводу вами приведённой ссылки, то хорошо читать до конца:
C++
1
2
3
4
5
6
7
Thread Constructor with arguments
 
template <class F,class A1,class A2,...>
thread(F f,A1 a1,A2 a2,...);
 
Preconditions:
F and each An must be copyable or [B]movable[/B].
Добавлено через 22 минуты
Operok, Хотя конечно есть правда в ваших словах. но практика критерий истины. У меня работает. Возможно при перемещении задействуется както передача по ссылке. Я глубоко в потрохах не копался.

Добавлено через 10 минут
Возможно, я недокументированные возможности использую, так как я менял значение BOOST_THREAD_VERSION в коде. Он нигде не описан.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
10.10.2017, 17:45
Помогаю со студенческими работами здесь

Boost thread
Здравствуйте! Помогите разобраться пожалуйста. Задача будет заключаться в том чтобы, создать поток и передать туда функцию и параметр,...

queue boost thread
#define BOOST_THREAD_VERSION 2 #include &lt;boost/thread/thread.hpp&gt; #include &lt;boost/thread/xtime.hpp&gt; #include &lt;iostream&gt; #include...

boost::thread синхронизация с VCL
Здравствуйте, подскажите, как работать с VCL компонентами из boost::thread потока

Исключения в потоке Boost::thread
Имеется функция, которая вызывается в потоке. Внутри функции есть try-catch. Вне потока, если функцию вызывать из main(), исключения...

boost::thread() проблема с потоками.
Собственно создается два потока и запускаются следующим образом int main(). { thread1.join(); thread2.join(); ...


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

Или воспользуйтесь поиском по форуму:
7
Ответ Создать тему
Новые блоги и статьи
Подключение Box2D v3 к SDL3 для Android: физика и отрисовка коллайдеров
8Observer8 29.01.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами. Версия v3 была полностью переписана на Си, в. . .
Инструменты COM: Сохранение данный из VARIANT в файл и загрузка из файла в VARIANT
bedvit 28.01.2026
Сохранение базовых типов COM и массивов (одномерных или двухмерных) любой вложенности (деревья) в файл, с возможностью выбора алгоритмов сжатия и шифрования. Часть библиотеки BedvitCOM Использованы. . .
Загрузка PNG с альфа-каналом на SDL3 для Android: с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 28.01.2026
Содержание блога SDL3 имеет собственные средства для загрузки и отображения PNG-файлов с альфа-каналом и базовой работы с ними. В этой инструкции используется функция SDL_LoadPNG(), которая. . .
Загрузка PNG с альфа-каналом на SDL3 для Android: с помощью SDL3_image
8Observer8 27.01.2026
Содержание блога SDL3_image - это библиотека для загрузки и работы с изображениями. Эта пошаговая инструкция покажет, как загрузить и вывести на экран смартфона картинку с альфа-каналом, то есть с. . .
Влияние грибов на сукцессию
anaschu 26.01.2026
Бифуркационные изменения массы гриба происходят тогда, когда мы уменьшаем массу компоста в 10 раз, а скорость прироста биомассы уменьшаем в три раза. Скорость прироста биомассы может уменьшаться за. . .
Воспроизведение звукового файла с помощью SDL3_mixer при касании экрана Android
8Observer8 26.01.2026
Содержание блога SDL3_mixer - это библиотека я для воспроизведения аудио. В отличие от инструкции по добавлению текста код по проигрыванию звука уже содержится в шаблоне примера. Нужно только. . .
Установка Android SDK, NDK, JDK, CMake и т.д.
8Observer8 25.01.2026
Содержание блога Перейдите по ссылке: https:/ / developer. android. com/ studio и в самом низу страницы кликните по архиву "commandlinetools-win-xxxxxx_latest. zip" Извлеките архив и вы увидите. . .
Вывод текста со шрифтом TTF на Android с помощью библиотеки SDL3_ttf
8Observer8 25.01.2026
Содержание блога Если у вас не установлены Android SDK, NDK, JDK, и т. д. то сделайте это по следующей инструкции: Установка Android SDK, NDK, JDK, CMake и т. д. Сборка примера Скачайте. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru