mirror of https://github.com/sipwise/sems.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
191 lines
4.0 KiB
191 lines
4.0 KiB
/*
|
|
* Copyright (C) 2002-2003 Fhg Fokus
|
|
*
|
|
* This file is part of SEMS, a free SIP media server.
|
|
*
|
|
* SEMS is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version. This program is released under
|
|
* the GPL with the additional exemption that compiling, linking,
|
|
* and/or using OpenSSL is allowed.
|
|
*
|
|
* For a license to use the SEMS software under conditions
|
|
* other than those described here, or to purchase support for this
|
|
* software, please contact iptel.org by e-mail at the following addresses:
|
|
* info@iptel.org
|
|
*
|
|
* SEMS is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*/
|
|
/** @file AmThread.h */
|
|
#ifndef _AmThread_h_
|
|
#define _AmThread_h_
|
|
|
|
#include <sys/time.h>
|
|
#include <time.h>
|
|
#include <errno.h>
|
|
|
|
#include <list>
|
|
#include <mutex>
|
|
#include <atomic>
|
|
#include <condition_variable>
|
|
#include <thread>
|
|
|
|
using std::lock_guard;
|
|
using std::atomic_bool;
|
|
|
|
/**
|
|
* \brief Wrapper class for std::mutex
|
|
*/
|
|
class AmMutex : public std::mutex
|
|
{
|
|
public:
|
|
AmMutex() : std::mutex() {}
|
|
AmMutex(const AmMutex &) : std::mutex() {}
|
|
void operator=(const AmMutex &) {}
|
|
};
|
|
|
|
/**
|
|
* \brief Wrapper class for std::condition_variable
|
|
*/
|
|
class AmCondition
|
|
{
|
|
bool t = false;
|
|
std::mutex m;
|
|
std::condition_variable cond;
|
|
|
|
public:
|
|
AmCondition() = default;
|
|
AmCondition(const bool& _t) : t(_t) {}
|
|
|
|
/** Change the condition's value. */
|
|
void set(const bool newval)
|
|
{
|
|
std::lock_guard<std::mutex> l(m);
|
|
t = newval;
|
|
if(t)
|
|
cond.notify_all();
|
|
}
|
|
|
|
bool get()
|
|
{
|
|
std::lock_guard<std::mutex> l(m);
|
|
return t;
|
|
}
|
|
|
|
/** Waits for the condition to be true. */
|
|
void wait_for()
|
|
{
|
|
std::unique_lock<std::mutex> l(m);
|
|
while(!t){
|
|
cond.wait(l);
|
|
}
|
|
}
|
|
|
|
/** Waits for the condition to be true or a timeout. */
|
|
bool wait_for_to(unsigned long msec)
|
|
{
|
|
auto timeout = std::chrono::system_clock::now();
|
|
timeout += std::chrono::milliseconds(msec);
|
|
|
|
std::unique_lock<std::mutex> l(m);
|
|
while(!t){
|
|
auto retcode = cond.wait_until(l, timeout);
|
|
if (retcode == std::cv_status::timeout)
|
|
break;
|
|
}
|
|
|
|
return t;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* \brief Wrapper class for std::thread
|
|
*/
|
|
class AmThread
|
|
{
|
|
std::thread _td;
|
|
|
|
enum state {
|
|
idle, // not started yet
|
|
running,
|
|
stopping, // waiting to stop
|
|
stopped, // after stop
|
|
};
|
|
|
|
std::atomic<state> _state;
|
|
|
|
std::mutex _join_mt;
|
|
bool _joined;
|
|
|
|
void _start();
|
|
|
|
protected:
|
|
virtual void run()=0;
|
|
virtual void on_stop() {};
|
|
|
|
/** @return true if this thread ought to stop. */
|
|
bool stop_requested() { return _state == stopping; }
|
|
|
|
public:
|
|
unsigned long _pid;
|
|
|
|
AmThread()
|
|
: _state(state::idle),
|
|
_joined(false)
|
|
{}
|
|
|
|
virtual ~AmThread();
|
|
|
|
/** Start it ! */
|
|
void start();
|
|
|
|
/** Stop it ! */
|
|
void stop();
|
|
|
|
/** Wait for this thread to finish */
|
|
void join();
|
|
|
|
/** @return true if this thread has finished. */
|
|
bool is_stopped() { return _state == stopped; }
|
|
};
|
|
|
|
/**
|
|
* \brief Container/garbage collector for threads.
|
|
*
|
|
* AmThreadWatcher waits for threads to stop
|
|
* and delete them.
|
|
* It gets started automatically when needed.
|
|
* Once you added a thread to the container,
|
|
* there is no mean to get it out.
|
|
*/
|
|
class AmThreadWatcher: public AmThread
|
|
{
|
|
static AmThreadWatcher* _instance;
|
|
static AmMutex _inst_mut;
|
|
|
|
std::list<AmThread*> thread_list;
|
|
AmMutex q_mut;
|
|
|
|
AmThreadWatcher() {}
|
|
void run();
|
|
|
|
public:
|
|
static AmThreadWatcher* instance();
|
|
void add(AmThread*);
|
|
};
|
|
|
|
#endif
|
|
|
|
// Local Variables:
|
|
// mode:C++
|
|
// End:
|
|
|