2013-11-27 5 views
3

Из вывода этого образца проекта я вижу три копии моего объекта, созданные, когда я ожидаю только одного. И хочу только одного. Как мне это исправить?Как остановить std/boost :: thread копирование моего объекта вместо передачи ссылок?

В моем реальном коде ThreadedThing - это значительно больший/тяжелый класс, который сидит в threadpool, и я предпочел бы иметь только столько, сколько мне действительно нужно. Но я написал небольшое демо-приложение (ниже), демонстрирующее поведение. Я скопировал базовый код из выборочной последовательности потоков, поэтому я ожидал, что он будет работать правильно, поэтому я боюсь, что это вопрос начинающего C++.

Я написал многопоточный код раньше, но в Delphi, а не в C++. Для этого кода valgrind говорит, что утечек нет, и все это очень хорошо, но есть еще три объекта, созданных там, где я бы предпочёл их.

#include <iostream> 
#include <boost/thread.hpp> 

using namespace std; 

class ThreadedThing { 
public: 
    ThreadedThing() { 
     cout << "ThreadedThing created" << endl; 
    } 
    ThreadedThing(const ThreadedThing &orig) { 
     cout << "ThreadedThing copy created" << endl; 
    } 
    ~ThreadedThing() { 
     cout << "ThreadedThing destroyed" << endl; 
    } 
    void operator()() { 
     cout << "ThreadedThing running" << endl; 
     sleep(2); 
    } 
}; 

int main() { 
    std::vector < shared_ptr <boost::thread>> threads; 
    cout << "Started" << endl; 

    ThreadedThing thing; 
    std::shared_ptr<boost::thread> thread(new boost::thread(thing)); 
    threads.push_back(thread); 

    for (std::vector < std::shared_ptr <boost::thread>> ::iterator it = threads.begin(); it != threads.end(); ++it) { 
     (*it)->join(); 
     cout << "joined" << endl; 
    } 
    cout << "stopped" << endl; 
    return 0; 
} 

/* output 
Started 
ThreadedThing created 
ThreadedThing copy created 
ThreadedThing copy created 
ThreadedThing destroyed 
ThreadedThing running 
ThreadedThing destroyed 
joined 
stopped 
ThreadedThing destroyed 
*/ 

ответ

7

std::ref Просто используйте в C++ 11 или boost::ref, когда не имея доступа к C++ 11 ,

-1

Это хорошо документирована, что конструктор boost::thread, то же самое с std::thread, не принимает ссылки в качестве аргумента. Чтобы преодолеть эту проблему, вы можете написать небольшой объект оболочки, который включает ссылку и сохраняет ее даже при копировании.

Это, как я это сделал:

/* container to allow passing an object reference to std::thread() 
* without this std::thread() would run on a copy 
*/ 
template<typename T> 
struct holder { 
    holder(T& payload) : payload(payload) {} 
    void operator()() { payload(); } 

    T& payload; 
}; 

Затем используйте его как этот:

BackgroundTaskQueue queue; 

// start worker thread 
holder<BackgroundTaskQueue> h(queue); 
queuethread = new std::thread(h); 
// h is not needed anymore 
+0

Отлично, спасибо. Это именно то, что я хотел знать. –

+7

Или используйте 'std :: ref' /' std :: cref', если доступен C++ 11. –

+0

Теперь я использую лучшие поисковые термины. Я нахожу много ответов на этот вопрос. И std :: ref выглядит так, как я хочу, вместо добавления шаблона в свой код. Благодарю. ... https://www.google.com.au/search?q=constructor+of+boost%3A%3Athread+copy+reference –