Commit 6ea82531 authored by Alejandro Homs Puron's avatar Alejandro Homs Puron

Merge branch 'improve_cmdthread' into 'master'

Improve CmdThread

See merge request !53
parents 01d25c2d a7d48e8c
Pipeline #2952 passed with stages
in 2 minutes and 21 seconds
......@@ -25,6 +25,8 @@
#include "lima/LimaCompatibility.h"
#include "lima/AutoObj.h"
#include <pthread.h>
#include <bitset>
#include <queue>
namespace lima
{
......@@ -141,11 +143,11 @@ class LIMACORE_API CmdThread
{
public:
enum { // Status
InInit, Stopped, Finished, MaxThreadStatus,
InInit = 0, Finished, MaxThreadStatus,
};
enum { // Cmd
None, Init, Stop, Abort, MaxThreadCmd,
None, Init, Abort, MaxThreadCmd,
};
CmdThread();
......@@ -155,7 +157,7 @@ class LIMACORE_API CmdThread
virtual void abort();
void sendCmd(int cmd);
void sendCmdIf(int cmd,bool (*if_test)(int,int));
void sendCmdIf(int cmd, bool (*if_test)(int, int));
int getStatus() const;
int getNextCmd() const;
void waitStatus(int status);
......@@ -183,9 +185,17 @@ class LIMACORE_API CmdThread
};
friend class AuxThread;
void cmdLoop();
void doSendCmd(int cmd);
int m_status;
//No need to have dll-interface for private variables
#pragma warning( push )
#pragma warning( disable : 4251 )
std::bitset<16> m_status_history;
std::queue<int> m_cmd;
#pragma warning( pop )
volatile int m_status;
volatile int m_cmd;
mutable Cond m_cond;
AuxThread m_thread;
};
......
......@@ -281,8 +281,8 @@ void *Thread::staticThreadFunction(void *data)
} catch (...) {
if (!thread->m_exception_handled) {
ostream& os = cerr;
unsigned int thread_id = (unsigned int) pthread_self();
int w = os.width();
long long thread_id = (long long) pthread_self();
std::streamsize w = os.width();
os << "***** Thread "
<< setw(8) << hex << thread_id << setw(w) << dec
<< " function exited due to an exception "
......@@ -313,26 +313,31 @@ CmdThread::CmdThread()
: m_thread(*this)
{
m_status = InInit;
m_cmd = None;
m_status_history.set(InInit);
}
CmdThread::~CmdThread()
{
if(m_thread.hasStarted())
{
using namespace std;
if (!m_thread.hasStarted())
return;
if (getStatus() != Finished) {
cerr << "***** Error: CmdThread did not call abort "
<< "in the derived class destructor! *****";
abort();
waitStatus(Finished);
}
}
AutoMutex CmdThread::lock() const
{
return AutoMutex(m_cond.mutex(), AutoMutex::Locked);
return AutoMutex(m_cond.mutex(), AutoMutex::Locked);
}
AutoMutex CmdThread::tryLock() const
{
return AutoMutex(m_cond.mutex(), AutoMutex::TryLocked);
return AutoMutex(m_cond.mutex(), AutoMutex::TryLocked);
}
int CmdThread::getStatus() const
......@@ -343,28 +348,32 @@ int CmdThread::getStatus() const
int CmdThread::getNextCmd() const
{
AutoMutex l = lock();
return m_cmd;
AutoMutex l = lock();
return m_cmd.empty() ? None : m_cmd.front();
}
void CmdThread::setStatus(int status)
{
AutoMutex l = lock();
m_status = status;
m_status_history.set(status);
m_cond.signal();
}
void CmdThread::waitStatus(int status)
{
AutoMutex l = lock();
while (m_status != status)
while (!m_status_history.test(status))
m_cond.wait();
}
int CmdThread::waitNotStatus(int status)
{
std::bitset<16> mask(0xffff);
mask.reset(status);
AutoMutex l = lock();
while (m_status == status)
while ((m_status_history & mask).none())
m_cond.wait();
return m_status;
}
......@@ -372,49 +381,60 @@ int CmdThread::waitNotStatus(int status)
void CmdThread::sendCmd(int cmd)
{
AutoMutex l = lock();
m_cmd = cmd;
m_cond.signal();
doSendCmd(cmd);
}
/** @brief send a command only if the return of if_test is true.
*
* function if_test get as argument the command and status
*/
void CmdThread::sendCmdIf(int cmd,bool (*if_test)(int,int))
void CmdThread::sendCmdIf(int cmd, bool (*if_test)(int,int))
{
AutoMutex l = lock();
bool sendFlag = true;
if(if_test)
sendFlag = if_test(m_cmd,m_status);
if(sendFlag)
{
m_cmd = cmd;
m_cond.signal();
}
AutoMutex l = lock();
if (if_test && if_test(cmd, m_status))
doSendCmd(cmd);
}
void CmdThread::doSendCmd(int cmd)
{
if (m_status == Finished)
throw LIMA_HW_EXC(Error, "Thread has Finished");
// Assume that we will have a call to waitStatus somewhere after the new command
m_status_history.reset();
m_cmd.push(cmd);
m_cond.signal();
}
void CmdThread::start()
{
if (m_thread.hasStarted())
throw LIMA_COM_EXC(InvalidValue, "Thread already started");
m_cmd = Init;
m_cmd.push(Init);
m_thread.start();
}
void CmdThread::abort()
{
if (getStatus() != Finished)
sendCmd(Abort);
if (getStatus() == Finished)
return;
sendCmd(Abort);
waitStatus(Finished);
}
int CmdThread::waitNextCmd()
{
AutoMutex l = lock();
while (m_cmd == None)
m_cond.wait();
while (m_cmd.empty())
m_cond.wait();
int cmd = m_cmd;
m_cmd = None;
int cmd = m_cmd.front();
m_cmd.pop();
return cmd;
}
......@@ -428,9 +448,6 @@ void CmdThread::cmdLoop()
case Init:
init();
break;
case Stop:
setStatus(Stopped);
break;
case Abort:
setStatus(Finished);
break;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment