i have the next code listing-6.1.cpp:
#include <stack>
#include <mutex>
#include <memory>
#include <future>
#include <iostream>
#include <exception>
using namespace std;
struct empty_stack: std::exception
{
const char* what() const throw();
};
template<typename T>
class threadsafe_stack
{
private:
std::stack<T> data;
mutable std::mutex m;
public:
threadsafe_stack(){}
threadsafe_stack(const threadsafe_stack& other)
{
std::lock_guard<std::mutex> lock(other.m);
data=other.data;
}
threadsafe_stack& operator=(const threadsafe_stack&) = delete;
void push(T new_value)
{
std::lock_guard<std::mutex> lock(m);
data.push(std::move(new_value));
}
std::shared_ptr<T> pop()
{
std::lock_guard<std::mutex> lock(m);
if(data.empty()) throw empty_stack();
std::shared_ptr<T> const res(
std::make_shared<T>(std::move(data.top())));
data.pop();
return res;
}
void pop(T& value)
{
std::lock_guard<std::mutex> lock(m);
if(data.empty()) throw empty_stack();
value=std::move(data.top());
data.pop();
}
bool empty() const
{
std::lock_guard<std::mutex> lock(m);
return data.empty();
}
};
struct Msg {
size_t a;size_t b;size_t c;size_t d;
};
bool isCorrupted(const Msg& m) {
return !(m.a == m.b && m.b == m.c && m.c == m.d);
}
int main()
{
threadsafe_stack<Msg> stack;
auto prod = std::async(std::launch::async, [&]() {
for (size_t i = 0; i < 1000000; ++i){
Msg m = { i, i, i, i };
stack.push(m);
//std::this_thread::sleep_for(std::chrono::microseconds(1));
if (i % 1000 == 0) {
std::cout << "stack.push called " << i << " times " << std::endl;
}
}
});
auto cons = std::async(std::launch::async, [&]() {
for (size_t i = 0; i < 1000000; ++i){
try {
Msg m;
stack.pop(m);
if (isCorrupted(m)) {
std::cout << i <<" ERROR: MESSAGE WAS CORRUPED:" << m.a << "-" << m.b << "-" << m.c << "-" << m.d << std::endl;
}
if (i % 1000 == 0) {
std::cout << "stack.pop called " << i << " times " << std::endl;
}
}
catch (empty_stack e) {
std::cout << i << " Stack was empty!" << std::endl;
}
}
});
prod.wait();
cons.wait();
return 0;
}
After it is compile with:
g++ -o exe.out listing-6.1.cpp -pthread -lboost_system -lboost_thread -std=c++0x
I have the next result:
/tmp/ccqQnqlf.o: In function empty_stack::empty_stack(empty_stack const&)':
listing-6.1.cpp:(.text._ZN11empty_stackC2ERKS_[_ZN11empty_stackC5ERKS_]+0x1d): undefined reference to
vtable for empty_stack'
/tmp/ccqQnqlf.o:(.gcc_except_table+0x20): undefined reference to typeinfo for empty_stack'
/tmp/ccqQnqlf.o: In function
empty_stack::empty_stack()':
listing-6.1.cpp:(.text._ZN11empty_stackC2Ev[_ZN11empty_stackC5Ev]+0x16): undefined reference to vtable for empty_stack'
/tmp/ccqQnqlf.o: In function
threadsafe_stack::pop(Msg&)':
listing-6.1.cpp:(.text._ZN16threadsafe_stackI3MsgE3popERS0_[_ZN16threadsafe_stackI3MsgE3popERS0_]+0x53): undefined reference to typeinfo for empty_stack'
/tmp/ccqQnqlf.o: In function
empty_stack::~empty_stack()':
listing-6.1.cpp:(.text._ZN11empty_stackD2Ev[_ZN11empty_stackD5Ev]+0xb): undefined reference to `vtable for empty_stack'
collect2: error: ld returned 1 exit status