LINUX.ORG.RU

Кортежи Boost. Каждому рабочему классу свой тред!

 ,


0

2

Доброго времени суток!

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

template<class... Childrens> class TChild
{
    private:
        boost::tuple<Childrens*...> tupChild;
        boost::thread* all_childs[sizeof...(Childrens)];
        void RunThreads();
        void StopThreads();
    public:
        ....
}
template<class... Childrens> 
void TChild<Childrens...>::RunThreads()
{
    for(uint8_t i=0; i<sizeof...(Childrens);++i)
    {
        all_childs[i]=new boost::thread(
                                    [this, i](){
                                        tupChild.get<i>()=new *(boost::tuples::element<i,tupChild>::type);
                                        });
    }
}

error: expected expression
                                        tupChild.get<i>()=new *(boost::tuples::element<i,tupChild>::type);
                                                        ^
error: expected a type
                                        tupChild.get<i>()=new *(boost::tuples::element<i,tupChild>::type);
                                                              ^
★★

экземпляр каждого класса должен создаваться в своем потоке

Так не бывает. В одном процессе все объекты создаются внутри одного адресного пространства.

BRE ★★
()
Ответ на: комментарий от Begemoth

О! спасибо! Получилось.

Оказалось, что я снова забыл, что когда выполняется - шаблоны на этапе компиляции (и for тут не к месту).

aido ★★
() автор топика
Ответ на: комментарий от aido

объекты у тебя все в общем адресном пространстве. создавать их в одном потоке или в разных - дело вкуса.
но for в шаблонах всё-таки можно реализовать. чота меня прикололо, я накатала ради развлечения тестик с шаблончиком:

#include <iostream>
#include <typeinfo>
#include <boost/thread.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/utility/enable_if.hpp>
/* for demangle */
#include <cstdlib>
#include <memory>
#include <cxxabi.h>

using namespace std;

template<class... Children> class TChild
{
    public:
        boost::tuple<Children*...> tupChild;
        size_t len;
        boost::thread* all_children[sizeof...(Children)];

        template<std::size_t I = 0>
        typename std::enable_if<I == sizeof...(Children), void>::type
        RunThreads() {
        }

        template<std::size_t I = 0>
        typename std::enable_if<I < sizeof...(Children), void>::type
        RunThreads() {
            all_children[I]=new boost::thread(
              [this](){
                  tupChild.get<I>() = new typename
                        boost::tuples::element<I,boost::tuple<Children...>>::type;
               });
            RunThreads< I+1 >();
        }

        void StopThreads();
        TChild() : len(sizeof...(Children)) {}
};

/* demangle for GCC */
std::string demangle(const char* name) {

    int status = 0;

    std::unique_ptr<char, void(*)(void*)> res {
        abi::__cxa_demangle(name, NULL, NULL, &status),
        std::free
    };

    return (status==0) ? res.get() : name ;
}

class bar {
    string value;
public:
    bar(): value("") {}
    bar(string val):value(val){}
    operator string() const { return value; }
};

int main()
{
    cout << "Hello, crazy world!" << endl;

    TChild<int,float,bar> foo;

    foo.RunThreads();

    for(size_t i=0; i<foo.len; i++)
        foo.all_children[i]->join();

    *foo.tupChild.get<0>()=10;
    *foo.tupChild.get<1>()=0.123;
    *foo.tupChild.get<2>()=bar("abc");

    cout << demangle(typeid(*(foo.tupChild.get<0>())).name())
        << " " << foo.tupChild.get<0>()
        << " " << *foo.tupChild.get<0>() << endl;
    cout << demangle(typeid(*(foo.tupChild.get<1>())).name())
        << " " << foo.tupChild.get<1>()
        << " " << *foo.tupChild.get<1>() << endl;
    cout << demangle(typeid(*(foo.tupChild.get<2>())).name())
        << " " << foo.tupChild.get<2>()
        << " " << string(*foo.tupChild.get<2>()) << endl;
    return 0;
}
на самом деле, и thread, и tuple можно невозбранно брать из std уже давно.

Iron_Bug ★★★★★
()
Ответ на: комментарий от Iron_Bug

Я решил пойти по пути наименьшего сопротивления и воспользовался Boost.Fusion, но встала проблема - как передать в тред параметры?

Вот мой код (вместо знака "?" нужно придумать, что подставить, чтобы сработало):

template<class T>struct TRunningClass
{
    boost::thread* thr;
    T* worker;
};
template<class... Childrens> class TChild
{
    private:
        boost::fusion::vector<TRunningClass<Childrens>...> tupChild;
        void RunThreads();
        void StopThreads();
        ....
    public:
        ....
}

struct RunThread
{
    template<class T>
        void operator()(TRunningClass<T> &obj, void* params) const
    {
        obj.thr= new boost::thread([&]()
                                        {
                                            obj.worker=new T(params);
                                        });
    }
};

template<class... Childrens> 
void TChild<Childrens...>::RunThreads()
{
    boost::fusion::for_each(tupChild, boost::bind<?>(RunThread,_1,log_));
}

struct StopThread
{
    template<class T>
        void operator()(TRunningClass<T> &obj) const
    {
        obj.thr->join();
    }
};

template<class... Childrens> 
void TChild<Childrens...>::StopThreads()
{
    boost::fusion::for_each(tupChild, StopThread());
}
aido ★★
() автор топика
Последнее исправление: aido (всего исправлений: 1)
Ответ на: комментарий от Iron_Bug

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

aido ★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.