Okay this meight be a bit off for Stack but ill try to keep it as short as possible.
I got thread which takes tasks out of a list and executes them. Simple as this (The worker class has its own thread and runs doTask m_thread(&Worker::doTask, this)):
void Worker::doTask()
{
while (m_running)
{
auto task = m_tasks.pop_front();
task->execute();
if (task->isContinuous())
m_tasks.push_pack(task);
}
}
The list itself is/should be threadsafe:
Header:
class TaskQueue
{
public:
void push_pack(std::shared_ptr<Task> t);
std::shared_ptr<Task> pop_front();
private:
std::list<std::shared_ptr<Task>> m_tasks;
std::condition_variable m_cond;
std::mutex m_mutex;
void TaskQueue::push_pack(std::shared_ptr<Task> t)
}
Impls of the importand part:
void TaskQueue::push_pack(std::shared_ptr<Task> t)
{
m_tasks.push_back(t);
//notify that there is one more task, so one thread can work now
m_cond.notify_one();
}
std::shared_ptr<Task> TaskQueue::pop_front()
{
//regular lock so noone else acces this area now
std::unique_lock<std::mutex> lock(m_mutex);
while (m_tasks.size() == 0)
m_cond.wait(lock);
auto task = m_tasks.front();
m_tasks.pop_front();
return task;
}
last but not least the tasks:
class Task
{
public:
virtual ~Task()
{
}
virtual void execute() = 0;
virtual bool isContinuous()
{
return false;
};
};
So if i try to add this Task:
class NetworkRequestTask:public Task
{
public:
NetworkRequestTask(TaskQueue &q);
~NetworkRequestTask();
void execute() override;
bool isContinuous() override;
private:
TaskQueue &m_tasks;
};
Impl:
NetworkRequestTask::NetworkRequestTask(TaskQueue& q): m_tasks(q)
{
}
NetworkRequestTask::~NetworkRequestTask()
{
}
void NetworkRequestTask::execute()
{
while(dosomething)
{
//do something here
}
}
bool NetworkRequestTask::isContinuous()
{
return true;
}
Main:
int main(int argc, char* argv[])
{
TaskQueue tasks;
tasks.push_pack(std::make_shared<NetworkRequestTask>(tasks));
}
it gets into a bad state:
Expression: list iterator not derefercable
I am Confused. This only happens if i override continouse and this only happens at this task. If i add the queue to a other continouse task as reference it does not get into that bad state.
So whats going wrong here and more importand what have i done wrong?
As from the comments, i already tried to lock the push_back method which did not change anything to the behaviour. (You can exchange it for a regular mutex it doesnt matter.)
void TaskQueue::push_pack(std::shared_ptr<Task> t)
{
std::lock_guard<SpinLock> lock(m_spin);
m_tasks.push_back(t);
//notify that there is one more task, so one thread can work now
m_cond.notify_one();
}
Related
I have an very delicate deadlock bug when I use the shared_ptr with custom Deleter and boost::share_mutex:
First there is an WorkManager class to manage Work object:
class Work;
class WorkManager {
public:
static WorkManager& instance() {
static WorkManager instance;
return instance;
}
std::shared_ptr<Work> get(int id);
std::shared_ptr<Work> create(int id);
void update(unsigned int diff);
private:
void _remove(int id, Work* t);
WorkManager();
mutable boost::shared_mutex _mutex;
std::map<int, std::weak_ptr<Work>> _works;
};
void WorkManager::_remove(int id, Work* t)
{
BOOST_ASSERT(t);
std::lock_guard<boost::shared_mutex> lock(_mutex);
_works.erase(id);
delete t;
}
std::shared_ptr<Work> WorkManager::get(int id) {
boost::shared_lock<boost::shared_mutex> lock(_mutex);
auto iter = _works.find(id);
if(iter == _works.end())
return nullptr;
return iter->second.lock();
}
std::shared_ptr<Work> WorkManager::create(int id) {
Work* t = new Work(id);
std::shared_ptr<Work> res;
res.reset(t, std::bind(&WorkManager::_remove, this, t->id(), std::placeholders::_1));
std::lock_guard<boost::shared_mutex> lock(_mutex);
_works[res->id()] = res;
return res;
}
void WorkManager::update(unsigned int diff) {
boost::shared_lock<boost::shared_mutex> lock(_mutex);
for(auto& t : _works)
{
if(std::shared_ptr<Work> work = t.second.lock())
work->update(diff);
}
}
WorkManager::update() is triggered by a timer, called at a fixed interval like 100ms. Because WorkManager doesn't hold shared_ptr<Work> but only weak_ptr<Work>, after work->update(diff); returns the work may be destroyed because there may be no shared_ptr<Work> holding this particular work any more. Then the WorkManager::_remove() will be called via the custom deleter for the shared_ptr<Work>. Notice the update thread already hold a read lock, in _remove(), it needs to acquire a write lock. However it must release the read lock before it can acquire this write lock. So this thread is dead.
This problem means that I cannot write any Manager's function do things like:
boost::shared_lock<boost::shared_mutex> lock(_mutex);
for(auto& t : _works)
{
if(std::shared_ptr<Work> w = t.second.lock())
w->do_something();
}
How to solve this? I figure out a solution is:
std::vector<std::shared_ptr<Work>> tmp;
{
boost::shared_lock<boost::shared_mutex> lock(_mutex);
for(auto& t : _works)
{
if(std::shared_ptr<Work> w = t.second.lock())
{
w->do_something();
tmp.push_back(w); //prevent w destroy before the read lock unlock
}
}
}
However this is error-prone, if someone forget this trick.
I'm using this class for producer-consumer setup in C++:
#pragma once
#include <queue>
#include <mutex>
#include <condition_variable>
#include <memory>
#include <atomic>
template <typename T> class SafeQueue
{
public:
SafeQueue() :
_shutdown(false)
{
}
void Enqueue(T item)
{
std::unique_lock<std::mutex> lock(_queue_mutex);
bool was_empty = _queue.empty();
_queue.push(std::move(item));
lock.unlock();
if (was_empty)
_condition_variable.notify_one();
}
bool Dequeue(T& item)
{
std::unique_lock<std::mutex> lock(_queue_mutex);
while (!_shutdown && _queue.empty())
_condition_variable.wait(lock);
if(!_shutdown)
{
item = std::move(_queue.front());
_queue.pop();
return true;
}
return false;
}
bool IsEmpty()
{
std::lock_guard<std::mutex> lock(_queue_mutex);
return _queue.empty();
}
void Shutdown()
{
_shutdown = true;
_condition_variable.notify_all();
}
private:
std::mutex _queue_mutex;
std::condition_variable _condition_variable;
std::queue<T> _queue;
std::atomic<bool> _shutdown;
};
And I use it like this:
class Producer
{
public:
Producer() :
_running(true),
_t(std::bind(&Producer::ProduceThread, this))
{ }
~Producer()
{
_running = false;
_incoming_packets.Shutdown();
_t.join();
}
SafeQueue<Packet> _incoming_packets;
private:
void ProduceThread()
{
while(_running)
{
Packet p = GetNewPacket();
_incoming_packets.Enqueue(p);
}
}
std::atomic<bool> _running;
std::thread _t;
}
class Consumer
{
Consumer(Producer* producer) :
_producer(producer),
_t(std::bind(&Consumer::WorkerThread, this))
{ }
~Consumer()
{
_t.join();
}
private:
void WorkerThread()
{
Packet p;
while(producer->_incoming_packets.Dequeue(p))
ProcessPacket(p);
}
std::thread _t;
Producer* _producer;
}
This works most of the time. But once in a while when I delete the producer (and causing it's deconstructor to call SafeQueue::Shutdown, the _t.join() blocks forever.
My guess is the that the problem is here (in SafeQueue::Dequeue):
while (!_shutdown && _queue.empty())
_condition_variable.wait(lock);
SafeQueue::Shutdown from thread #1 gets called while thread #2 finished checking _shutdown but before it executed _condition_variable.wait(lock), so it "misses" the notify_all(). Can this happen?
If that's the problem, what's the best way to solve it?
Since the SafeQueue object is owned by the producer, deleting the producer causes a race condition between the consumer being notified and the SafeQueue being deleted out from under it when ~Producer completes.
I suggest having the shared resource being owned by neither the producer nor consumer, but passed as a reference to the constructor of each.
Change the Producer and Consumer constructors;
Producer( SafeQueue<Packet> & queue ) :
_running(false), _incoming_packets(queue) {}
Consumer( SafeQueue<Packet> & queue ) :
_running(false), _incoming_packets(queue) {}
Use your instances this way;
SafeQueue<Packet> queue;
Producer producer(queue);
Consumer consumer(queue);
...do stuff...
queue.shutdown();
This also resolves a poor design issue you have in the Consumer class being so tightly coupled to the Producer class.
Also, it's probably a bad idea to kill and join threads in a destructor, as you do for ~Producer. Better to add a Shutdown() method to each thread class, and call them explicitly;
producer.shutdown();
consumer.shutdown();
queue.shutdown();
Shutdown order doesn't really matter, unless you are concerned about losing unprocessed packets that are still in the queue when you stop the consumer.
In your SafeQueue::Dequeue, you are probably using std::condition_variable the wrong way... Change this:
bool Dequeue(T& item)
{
std::unique_lock<std::mutex> lock(_queue_mutex);
while (!_shutdown && _queue.empty())
_condition_variable.wait(lock);
if(!_shutdown)
{
item = std::move(_queue.front());
_queue.pop();
return true;
}
return false;
}
to
bool Dequeue(T& item)
{
std::unique_lock<std::mutex> lock(_queue_mutex);
_condition_variable.wait(lock, []{ return _shutdown || !_queue.empty() });
if(!_shutdown)
{
item = std::move(_queue.front());
_queue.pop();
return true;
}
return false;
}
Secondly, the order of initialization of the data members in Consumer isn't right with regards to its constructor
class Consumer
{
Consumer(Producer* producer) :
_producer(producer),
_t(std::bind(&Consumer::WorkerThread, this))
{ }
......
// _t will be constructed first, regardless of your constructor initializer list
// Meaning, the thread can even start running using an unintialized _producer
std::thread _t;
Producer* _producer;
}
It should be reordered to:
class Consumer
{
Consumer(Producer* producer) :
_producer(producer),
_t(std::bind(&Consumer::WorkerThread, this))
{ }
......
Producer* _producer;
std::thread _t;
}
Another part of your problem is covered by CAB's answer
I'm new to C++11 threading and I'm trying to do something as follows:
class Something {
public:
void start() {
this->task_ = std::thread(&Something::someTask, this);
this->isRunning_ = true;
this->task_.detach(); // I read detach will stop it from hanging
}
void stop() {
this->isRunning = false;
}
~Something() {
this->stop();
}
private:
std::atomic<bool> isRunning_;
std::thread task_;
void someTask()
{
while(this->isRunning_) {
// do something forever
}
}
};
Something whatever;
whatever.start();
However, the thread keeps getting blocked. Like nothing after whatever.start() executes. It just hangs while the loop runs.
The usual pattern to do this is
class Something {
public:
void start() {
this->task_ = std::thread(&Something::someTask, this);
// this->task_.detach(); <<<<<< Don't do that.
}
void stop() {
this->isRunning_ = false;
task_.join(); // <<< Instead of detaching the thread, join() it.
}
~Something() {
this->stop();
}
private:
std::atomic<bool> isRunning_;
std::thread task_;
void someTask()
{
this->isRunning_ = true;
while(this->isRunning_) {
// do something forever
}
}
};
Detaching a std::thread usually isn't a good idea, unless there's some kind of synchronization set up, that allows to wait for the thread execution to end before the process ends as a whole.
Demonizing a process usually is realized with a fork() to create a background child process, and leave the parent process to return control to the caller.
I recently wrote a generic class that does just this
#include<functional>
#include<thread>
//do action asynchronously until condition is false
class do_async_until{
public:
do_async_until(std::function<void(void)> action,
std::function<bool(void)> condition);
~do_async_until();
void start();
void stop();
private:
void _do();
std::thread _worker;
std::function<void(void)> _action;
std::function<bool(void)> _condition;
};
//implementation
do_async_until::do_async_until(std::function<void(void)> action,
std::function<bool(void)> condition):_action(action),
_condition(condition){
}
do_async_until::~do_async_until(){
stop();
}
void do_async_until::start(){
_worker = std::thread(std::bind(&do_async_until::_do,this));
}
void do_async_until::stop(){
if(_worker.joinable()){
_worker.join();
}
}
void do_async_until::_do(){
while (_condition())
{
_action();
}
}
this will run any function with the signiture void(void) until the condition function bool(void) returns true
example usage:
int main(int agrc,char** argv){
bool running = true;
auto do_this = [](){
std::cout<<"hello world"<<std::endl;
};
auto condition = [&](){
return running;
};
do_async_until async(do_this,condition);
async.start();
std::this_thread::sleep_for(std::chrono::seconds(1));
running=false;
return 0;
}
The example should print "hello world" a bunch of times for one seconds then exit.
EDIT: to make this work with a member function you simply need to have an instance of do_async_until inside you class and pass the member function to the constructor of do_async_until using std::bind(&foo::func,this)
In Java we can create a class
class Test {
public synchronized void fn1() {
}
public synchronized void fn2() {
}
public synchronized void fn3() {
fn1(); // Calling another method
}
}
In C++ if I want to mimic the functionality one way is
class Test {
private:
mutex obj;
public:
void fn1(bool calledFromWithinClass = false) {
if(calledFromWithinClass)
fn1Helper();
else
unique_lock<mutex> lock(obj);
fn1Helper();
}
void fn2(bool calledFromWithinClass = false) {
if(calledFromWithinClass)
fn2Helper();
else
unique_lock<mutex> lock(obj);
fn2Helper();
}
void fn3(bool calledFromWithinClass = false) {
if(calledFromWithinClass)
fn3Helper();
else {
unique_lock<mutex> lock(obj);
fn3Helper();
}
}
private:
void fn1Helper() {
}
void fn2Helper() {
}
void fn3Helper() {
fn1(true);
}
}
int main() {
Test obj;
obj.fn1();
obj.fn2();
// i.e from outside the class the methods are called with calledFromWithinClass as false.
}
In short all I am trying to do is to use RAII for locking as well as allow functions to call each other. In C++ without the calledFromWithinClass flag if the outer function has acquired the lock the inner function can't acquire the lock and the code gets stuck.
As you can see the code is complicated, is there any other way to do this in C++.
I can only use C++98 and you can assume that all methods in the class are synchronized (i.e need the lock)
I can suggest two options:
Just use boost::recursive_mutex instead (or std::recursive_mutex in C++11).
(better) Always call non-synchronized private implementations from your synchronized code:
class Test {
private:
mutex obj;
public:
void fn1() {
unique_lock<mutex> lock(obj);
fn1Helper();
}
void fn2(bool calledFromWithinClass = false) {
unique_lock<mutex> lock(obj);
fn2Helper();
}
private:
void fn1Helper() {
}
void fn2Helper() {
fn1Helper();
}
}
I am running function Foo from somebody else's library in a single-threaded application currently. Most of the time, I make a call to Foo and it's really quick, some times, I make a call to Foo and it takes forever. I am not a patient man, if Foo is going to take forever, I want to stop execution of Foo and not call it with those arguments.
What is the best way to call Foo in a controlled manner (my current environment is POSIX/C++) such that I can stop execution after a certain number of seconds. I feel like the right thing to do here is to create a second thread to call Foo, while in my main thread I create a timer function that will eventually signal the second thread if it runs out of time.
Is there another, more apt model (and solution)? If not, would Boost's Signals2 library and Threads do the trick?
You can call Foo on a second thread with a timeout. For example:
#include <boost/date_time.hpp>
#include <boost/thread/thread.hpp>
boost::posix_time::time_duration timeout = boost::posix_time::milliseconds(500);
boost::thread thrd(&Foo);
if (thrd.timed_join(timeout))
{
//finished
}
else
{
//Not finished;
}
You can use the following class:
class timer
{
typedef boost::signals2::signal<void ()> timeout_slot;
public:
typedef timeout_slot::slot_type timeout_slot_t;
public:
timer() : _interval(0), _is_active(false) {};
timer(int interval) : _interval(interval), _is_active(false) {};
virtual ~timer() { stop(); };
inline boost::signals2::connection connect(const timeout_slot_t& subscriber) { return _signalTimeout.connect(subscriber); };
void start()
{
boost::lock_guard<boost::mutex> lock(_guard);
if (is_active())
return; // Already executed.
if (_interval <= 0)
return;
_timer_thread.interrupt();
_timer_thread.join();
timer_worker job;
_timer_thread = boost::thread(job, this);
_is_active = true;
};
void stop()
{
boost::lock_guard<boost::mutex> lock(_guard);
if (!is_active())
return; // Already executed.
_timer_thread.interrupt();
_timer_thread.join();
_is_active = false;
};
inline bool is_active() const { return _is_active; };
inline int get_interval() const { return _interval; };
void set_interval(const int msec)
{
if (msec <= 0 || _interval == msec)
return;
boost::lock_guard<boost::mutex> lock(_guard);
// Keep timer activity status.
bool was_active = is_active();
if (was_active)
stop();
// Initialize timer with new interval.
_interval = msec;
if (was_active)
start();
};
protected:
friend struct timer_worker;
// The timer worker thread.
struct timer_worker
{
void operator()(timer* t)
{
boost::posix_time::milliseconds duration(t->get_interval());
try
{
while (1)
{
boost::this_thread::sleep<boost::posix_time::milliseconds>(duration);
{
boost::this_thread::disable_interruption di;
{
t->_signalTimeout();
}
}
}
}
catch (boost::thread_interrupted const& )
{
// Handle the thread interruption exception.
// This exception raises on boots::this_thread::interrupt.
}
};
};
protected:
int _interval;
bool _is_active;
boost::mutex _guard;
boost::thread _timer_thread;
// Signal slots
timeout_slot _signalTimeout;
};
An example of usage:
void _test_timer_handler()
{
std::cout << "_test_timer_handler\n";
}
BOOST_AUTO_TEST_CASE( test_timer )
{
emtorrus::timer timer;
BOOST_CHECK(!timer.is_active());
BOOST_CHECK(timer.get_interval() == 0);
timer.set_interval(1000);
timer.connect(_test_timer_handler);
timer.start();
BOOST_CHECK(timer.is_active());
std::cout << "timer test started\n";
boost::this_thread::sleep<boost::posix_time::milliseconds>(boost::posix_time::milliseconds(5500));
timer.stop();
BOOST_CHECK(!timer.is_active());
BOOST_CHECK(_test_timer_count == 5);
}
You can also set an alarm right before calling that function, and catch SIGALRM.
Vlad, excellent post! Your code compiled and works beautifully. I implemented a software watchdog timer with it. I made a few modifications:
To prevent pointer decay, store the signal in boost::shared_ptr and pass this to the thread worker instead of a weak pointer to the timer class. This eliminates the need for the thread worker to be a friend struct and guarantees the signal is in memory.
Add parameter _is_periodic to allow the caller to select whether or not the worker thread is periodic or if it terminates after expiration.
Store _is_active, _interval and _is_periodic in boost::atomic to allow thread-safe access.
Narrow the scope of mutex locking.
Add reset() method to "kick" the timer, preventing it from issuing the expiration signal.
With these changes applied:
#include <atomic>
#include <boost/signals2.hpp>
#include <boost/thread.hpp>
class IntervalThread
{
using interval_signal = boost::signals2::signal<void(void)>;
public:
using interval_slot_t = interval_signal::slot_type;
IntervalThread(const int interval_ms = 60)
: _interval_ms(interval_ms),
_is_active(false),
_is_periodic(false),
_signal_expired(new interval_signal()) {};
inline ~IntervalThread(void) { stop(); };
boost::signals2::connection connect(const interval_slot_t &subscriber)
{
// thread-safe: signals2 obtains a mutex on connect()
return _signal_expired->connect(subscriber);
};
void start(void)
{
if (is_active())
return; // Already executed.
if (get_interval_ms() <= 0)
return;
boost::lock_guard<boost::mutex> lock(_timer_thread_guard);
_timer_thread.interrupt();
_timer_thread.join();
_timer_thread = boost::thread(timer_worker(),
static_cast<int>(get_interval_ms()),
static_cast<bool>(is_periodic()),
_signal_expired);
_is_active = true;
};
void reset(void)
{
if (is_active())
stop();
start();
}
void stop(void)
{
if (!is_active())
return; // Already executed.
boost::lock_guard<boost::mutex> lock(_timer_thread_guard);
_timer_thread.interrupt();
_timer_thread.join();
_is_active = false;
};
inline bool is_active(void) const { return _is_active; };
inline int get_interval_ms(void) const { return _interval_ms; };
void set_interval_ms(const int interval_ms)
{
if (interval_ms <= 0 || get_interval_ms() == interval_ms)
return;
// Cache timer activity state.
const bool was_active = is_active();
// Initialize timer with new interval.
if (was_active)
stop();
_interval_ms = interval_ms;
if (was_active)
start();
};
inline bool is_periodic(void) const { return _is_periodic; }
inline void set_periodic(const bool is_periodic = true) { _is_periodic = is_periodic; }
private:
// The timer worker for the interval thread.
struct timer_worker {
void operator()(const int interval_ms, const bool is_periodic, boost::shared_ptr<interval_signal> signal_expired)
{
boost::posix_time::milliseconds duration(interval_ms);
try {
do {
boost::this_thread::sleep<boost::posix_time::milliseconds>(duration);
{
boost::this_thread::disable_interruption di;
signal_expired->operator()();
}
} while (is_periodic);
} catch (const boost::thread_interrupted &) {
// IntervalThread start(), stop() and reset() throws boost::this_thread::interrupt,
// which is expected since this thread is interrupted. No action neccessary.
}
};
};
std::atomic<int> _interval_ms; // Interval, in ms
std::atomic<bool> _is_active; // Is the timed interval active?
std::atomic<bool> _is_periodic; // Is the timer periodic?
boost::mutex _timer_thread_guard;
boost::thread _timer_thread;
// The signal to call on interval expiration.
boost::shared_ptr<interval_signal> _signal_expired;
};