我是多线程新手,我使用线程池机制来同步两个类之间的交互。
编译时我无法理解错误。
课程如下:
InstrumentProcessor.h
1 #ifndef INSTRUMENTPROCESSOR_H
2 #define INSTRUMENTPROCESSOR_H
3
4 #include <boost/thread/thread.hpp>
5 #include <boost/thread/mutex.hpp>
6 #include <boost/algorithm/string.hpp>
7 #include <boost/lexical_cast.hpp>
8 #include "Semaphore.h"
9 #include "Instrument.h"
10 #include <queue>
11 #include <string>
12 #include <vector>
13
14
15 class InstrumentProcessor
16 {
17 public:
18 InstrumentProcessor(unsigned int const numThreads);
19 ~InstrumentProcessor();
20 bool Start();
21 bool Stop();
22 void AddLine(const std::string& LineRead); // Producer
23
24 private:
25 void Process(); // Worker Function
26 void ProcessLine(std::string& line); // Consumer
27
28 private:
29 unsigned int const numThreads_;
30 boost::mutex ProcessorMutex_;
31 boost::thread_group ProcessorGroup_;
32 Semaphore taskCount_;
33 std::queue<std::string> Line_;
34 bool stop_;
35 std::vector<std::string> elements_;
36 std::vector<Instrument> Instruments_;
37 };
38
39 #endif /* INSTRUMENTPROCESSOR_H */
InstrumentProcessor.cpp
1 #include "InstrumentProcessor.h"
2
3 InstrumentProcessor::InstrumentProcessor(unsigned int const numThreads)
4 : numThreads_(numThreads), stop_(false)
5 {
6 Instruments_.reserve(25);
7 }
8
9 InstrumentProcessor::~InstrumentProcessor()
10 {
11
12 }
13
14 bool InstrumentProcessor::Start()
15 {
16 std::cout << "\nParallel Processing Started ...." << std::endl;
17 for(unsigned int i=0; i<numThreads_; i++)
18 {
19 ProcessorGroup_.create_thread(boost::bind(&InstrumentProcessor ::Process, this));
20 }
21
22 return true;
23 }
24
25 bool InstrumentProcessor::Stop()
26 {
27 stop_ = true;
28 ProcessorGroup_.join_all();
29 std::cout << "\n Parallel Processing Stopped ...." << std::endl;
30 return stop_;
31 }
32
33
34 void InstrumentProcessor::Process()
35 {
36 while(!stop_)
37 {
38 --taskCount_;
39 std::string currentLine;
40 {
41 boost::mutex::scoped_lock lock(ProcessorMutex_);
42 currentLine = Line_.front();
43 Line_.pop();
44 }
45 ProcessLine(currentLine);
46 }
47 }
48
49 void InstrumentProcessor::AddLine(const std::string& LineRead)
50 {
51 boost::mutex::scoped_lock lock(ProcessorMutex_);
52 Line_.push(LineRead);
53 ++taskCount_;
54 }
55
56 void InstrumentProcessor::ProcessLine(std::string& line)
57 {
58 boost::algorithm::split(elements_, line, boost::is_any_of("\t "), boos t::token_compress_on);
59 for(unsigned int i=1; i<elements_.size(); i++)
60 {
61 if (elements_[i].compare("nan") == 0)
62 continue;
63 else
64 {
65 double data = boost::lexical_cast<double>(elements_[i] );
66 Instruments_[i-1].CleanData(data); // This function makes a call to the Insrument Class member function
67 }
68 }
69 }
Instrument.h
1 #ifndef INSTRUMENT_H
2 #define INSTRUMENT_H
3
4 #include <iostream>
5 #include <boost/thread/mutex.hpp>
6 #include <cmath>
7
8 class Instrument
9 {
10 public:
11 Instrument();
12 ~Instrument();
13 bool PopulateData(double& data);
14 bool CleanData(double& data);
15 bool PrintData();
16
17 private:
18 bool getMeanAndStandardDeviation();
19
20 private:
21 double data_;
22 int N_;
23 double Mean_;
24 double M2_;
25 double stdDev_;
26 double InitialValue_;
27 bool Init_;
28 boost::mutex InstrumentMutex_;
29 };
30
31 #endif /* INSTRUMENT_H */
Instrument.cpp
1 #include "Instrument.h"
2
3 Instrument::Instrument()
4 : Init_(false), data_(0.0), Mean_(0.0), stdDev_(0.0), InitialValue_(0.0), N_(0 ), M2_(0.0)
5 {
6
7 }
8
9 Instrument::~Instrument()
10 {
11
12 }
13
14 bool Instrument::PopulateData(double& data)
15 {
16 data_ = data;
17 if(!Init_)
18 {
19 InitialValue_ = data_;
20 Init_ = true;
21 std::cout << "The initial value is: " << InitialValue_ << std: :endl;
22 }
23 return true;
24 }
25
26 /* Cleaning Part 2:
27 * Each data point will be represented as the % change from the initial value.
28 * This will then be added by 101 so as to get uniform positive value with the
29 * origin of the data shifted to init_origin + 101
30 */
31
32 bool Instrument::CleanData(double& data)
33 {
34
35 std::cout << "\nData begin inserted: " << data << std::endl;
36 boost::mutex::scoped_lock lock(InstrumentMutex_);
37 PopulateData(data);
38 data_ = ((data_-InitialValue_)/InitialValue_)*100;
39 data_ += 101;
40 getMeanAndStandardDeviation();
41 return true;
42 }
43
44 // Welford recurrence relation for tick based mean and standard deviation calc ulation
45 bool Instrument::getMeanAndStandardDeviation()
46 {
47 ++N_;
48 double delta = data_ - Mean_;
49 Mean_ += delta/N_;
50 M2_ += delta*(data_ - Mean_);
51
52 if(N_ >= 2)
53 {
54 double variance = M2_/(N_-1);
55 stdDev_ = std::sqrt(variance);
56 }
57 return true;
58 }
59
60 bool Instrument::PrintData()
61 {
62 std::cout << "\nMean: " << Mean_ << "Std Dev: " << stdDev_ << std::end l;
63 return true;
64 }
我正在使用以下编译行编译上述内容:
g++ -std=c++11 -I /usr/lib/x86_64-linux-gnu -lboost_thread -c InstrumentProcessor.cpp
产生以下错误。
In file included from /usr/include/c++/4.8/memory:64:0,
from /usr/include/boost/config/no_tr1/memory.hpp:21,
from /usr/include/boost/smart_ptr/shared_ptr.hpp:27,
from /usr/include/boost/shared_ptr.hpp:17,
from /usr/include/boost/date_time/time_clock.hpp:17,
from /usr/include/boost/thread/thread_time.hpp:9,
from /usr/include/boost/thread/lock_types.hpp:18,
from /usr/include/boost/thread/pthread/thread_data.hpp:12,
from /usr/include/boost/thread/thread_only.hpp:17,
from /usr/include/boost/thread/thread.hpp:12,
from InstrumentProcessor.h:4,
from InstrumentProcessor.cpp:1:
/usr/include/c++/4.8/bits/stl_construct.h: In instantiation of ‘void std::_Construct(_T1*, _Args&& ...) [with _T1 = Instrument; _Args = {Instrument}]’:
/usr/include/c++/4.8/bits/stl_uninitialized.h:75:53: required from ‘static _ForwardIterator std::__uninitialized_copy<_TrivialValueTypes>::__uninit_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = std::move_iterator<Instrument*>; _ForwardIterator = Instrument*; bool _TrivialValueTypes = false]’
/usr/include/c++/4.8/bits/stl_uninitialized.h:117:41: required from ‘_ForwardIterator std::uninitialized_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = std::move_iterator<Instrument*>; _ForwardIterator = Instrument*]’
/usr/include/c++/4.8/bits/stl_uninitialized.h:258:63: required from ‘_ForwardIterator std::__uninitialized_copy_a(_InputIterator, _InputIterator, _ForwardIterator, std::allocator<_Tp>&) [with _InputIterator = std::move_iterator<Instrument*>; _ForwardIterator = Instrument*; _Tp = Instrument]’
/usr/include/c++/4.8/bits/stl_vector.h:1142:29: required from ‘std::vector<_Tp, _Alloc>::pointer std::vector<_Tp, _Alloc>::_M_allocate_and_copy(std::vector<_Tp, _Alloc>::size_type, _ForwardIterator, _ForwardIterator) [with _ForwardIterator = std::move_iterator<Instrument*>; _Tp = Instrument; _Alloc = std::allocator<Instrument>; std::vector<_Tp, _Alloc>::pointer = Instrument*; std::vector<_Tp, _Alloc>::size_type = long unsigned int]’
/usr/include/c++/4.8/bits/vector.tcc:75:70: required from ‘void std::vector<_Tp, _Alloc>::reserve(std::vector<_Tp, _Alloc>::size_type) [with _Tp = Instrument; _Alloc = std::allocator<Instrument>; std::vector<_Tp, _Alloc>::size_type = long unsigned int]’
InstrumentProcessor.cpp:6:25: required from here
/usr/include/c++/4.8/bits/stl_construct.h:75:7: error: use of deleted function ‘Instrument::Instrument(const Instrument&)’
{ ::new(static_cast<void*>(__p)) _T1(std::forward<_Args>(__args)...); }
^
In file included from InstrumentProcessor.h:9:0,
from InstrumentProcessor.cpp:1:
Instrument.h:8:7: note: ‘Instrument::Instrument(const Instrument&)’ is implicitly deleted because the default definition would be ill-formed:
class Instrument
^
Instrument.h:8:7: error: use of deleted function ‘boost::mutex::mutex(const boost::mutex&)’
In file included from /usr/include/boost/thread/lock_guard.hpp:11:0,
from /usr/include/boost/thread/pthread/thread_data.hpp:11,
from /usr/include/boost/thread/thread_only.hpp:17,
from /usr/include/boost/thread/thread.hpp:12,
from InstrumentProcessor.h:4,
from InstrumentProcessor.cpp:1:
/usr/include/boost/thread/pthread/mutex.hpp:96:9: error: declared here
BOOST_THREAD_NO_COPYABLE(mutex)
^
对此有任何帮助将不胜感激。
答案 0 :(得分:2)
方法vector::reserve()
的实现需要来自Instrument
类的 move-constructor 或 copy-constructor 。
但是这两个构造函数可能不会自动为类生成,因为它的成员InstrumentMutex_
既不可复制也不可移动(互斥既不能复制也不能移动)。
您需要手动为Instrument
class 声明move-constructor ,以便在向量操作中使用它。对于互斥成员来说,这不是 true 移动构造函数(互斥锁无法移动),但是对于给定的用法,简单地初始化互斥锁就足够了。
或者,不是在创建向量_Instruments
之后调用.reserve()方法,而是可以使用精确大小初始化此向量:
InstrumentProcessor::InstrumentProcessor(unsigned int const numThreads)
: numThreads_(numThreads), stop_(false), _Instruments(25)
{
}
此初始化仅需要来自Instrument
类的默认构造函数,该构造函数已经声明。
大小的向量构造函数与.reserve()
的不同之处在于,所有向量的元素都是创建的(与已分配的相反),这可能不适合您的情况。但是如果所有元素的创建都是正确的,那么这个初始化应该优先于前一个,因为它避免了没有明确定义的语义的移动构造函数的定义(互斥成员不会被移动但是被重新创建)。