I have a small test project that when I try to build complains
% sh compile.sh
-- Conan: Adjusting output directories
-- Conan: Using cmake targets configuration
-- Conan: Adjusting default RPATHs Conan policies
-- Conan: Adjusting language standard
-- Current conanbuildinfo.cmake directory: /cpp-multithreading-in-action/ch4_threadsafe_queue/build
-- Configuring done
-- Generating done
-- Build files have been written to: /cpp-multithreading-in-action/ch4_threadsafe_queue/build
Scanning dependencies of target test_cpp_multi
[ 33%] Building CXX object CMakeFiles/test_cpp_multi.dir/src/helloworld.cpp.o
[ 66%] Linking CXX executable bin/test_cpp_multi
Undefined symbols for architecture x86_64:
"threadsafe_queue<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >::wait_and_pop(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&)", referenced from:
prepare_data() in helloworld.cpp.o
data_preparation_thread() in helloworld.cpp.o
data_processing_thread() in helloworld.cpp.o
"threadsafe_queue<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >::push(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >)", referenced from:
data_preparation_thread() in helloworld.cpp.o
_main in helloworld.cpp.o
"threadsafe_queue<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >::threadsafe_queue()", referenced from:
__GLOBAL__sub_I_helloworld.cpp in helloworld.cpp.o
"threadsafe_queue<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >::empty() const", referenced from:
data_preparation_thread() in helloworld.cpp.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[2]: *** [bin/test_cpp_multi] Error 1
make[1]: *** [CMakeFiles/test_cpp_multi.dir/all] Error 2
make: *** [all] Error 2
CMakeLists.txt
cmake_minimum_required(VERSION 2.8.12)
project(test_cpp_multi)
add_compile_options(-std=c++11)
# Using the "cmake" generator
include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
conan_basic_setup(TARGETS)
add_executable(test_cpp_multi src/threadsafe_queue.cpp src/helloworld.cpp )
Helloworld.cpp
#include <mutex>
#include <condition_variable>
#include <thread>
#include <iostream>
#include <chrono>
#include <unistd.h>
#include "threadsafe_queue.h"
threadsafe_queue<std::string> source_queue;
threadsafe_queue<std::string> data_queue;
std::string prepare_data(){
std::string top_value;
source_queue.wait_and_pop(top_value);
return top_value;
}
void data_preparation_thread()
{
while(!source_queue.empty())
{
std::string const data=prepare_data();
data_queue.push(data);
}
}
bool is_last_chunk(std::string data){
if (data.compare(std::string("ENDOFLINE"))==0){
return true;
} else {
return false;
}
}
void process(std::string data){
std::cout << data;
}
void data_processing_thread()
{
while(true)
{
std::string data;
data_queue.wait_and_pop(data);
process(data);
if(is_last_chunk(data)) {
break;
}
}
}
int main(){
for (int i=0 ; i<3; i++){
std::string const data = "TEST";
source_queue.push(data);
}
std::string const data = "ENDOFLINE";
source_queue.push(data);
std::thread data_proc_thread(data_processing_thread);
std::thread data_prep_thread(data_preparation_thread);
data_proc_thread.join();
data_prep_thread.join();
}
threadsafe_queue.cpp
#include <queue>
#include <mutex>
#include <memory>
#include <condition_variable>
template <typename T>
class threadsafe_queue
{
private:
std::mutex mut;
std::queue<T> data_queue;
std::condition_variable data_cond;
public:
threadsafe_queue()
{
}
threadsafe_queue(threadsafe_queue const &other)
{
std::lock_guard<std::mutex> lk(other.mut);
data_queue = other.data_queue;
}
void push(T new_value)
{
std::lock_guard<std::mutex> lk(mut);
data_queue.push(new_value);
data_cond.notify_one();
}
void wait_and_pop(T &value)
{
std::unique_lock<std::mutex> lk(mut);
data_cond.wait(lk, [this] { return !data_queue.empty(); });
value = data_queue.front();
data_queue.pop();
}
std::shared_ptr<T> wait_and_pop()
{
std::unique_lock<std::mutex> lk(mut);
data_cond.wait(lk, [this] { return !data_queue.empty(); });
std::shared_ptr<T> res(std::make_shared<T>(data_queue.front()));
data_queue.pop();
return res;
}
bool try_pop(T &value)
{
std::lock_guard<std::mutex> lk(mut);
if (data_queue.empty())
return false;
value = data_queue.front();
data_queue.pop();
return true;
}
std::shared_ptr<T> try_pop()
{
std::lock_guard<std::mutex> lk(mut);
if (data_queue.empty())
return std::shared_ptr<T>();
std::shared_ptr<T> res(std::make_shared<T>(data_queue.front()));
data_queue.pop();
return res;
}
bool empty() const
{
std::lock_guard<std::mutex> lk(mut);
return data_queue.empty();
}
};
threadsafe_queue.h
#include <memory>
template<typename T>
class threadsafe_queue {
public:
threadsafe_queue();
threadsafe_queue(const threadsafe_queue&);
threadsafe_queue& operator=(const threadsafe_queue&) = delete;
void push(T new_value);
bool try_pop(T& value);
std::shared_ptr<T> try_pop();
void wait_and_pop(T& value);
std::shared_ptr<T> wait_and_pop();
bool empty() const;
};
Any help is appreciated.
Aucun commentaire:
Enregistrer un commentaire