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.
264 lines
4.8 KiB
264 lines
4.8 KiB
#include "TaskLoop.h"
|
|
#include <unknown/obj-ref-impl.hpp>
|
|
#include <algorithm>
|
|
#include <cassert>
|
|
#include <deque>
|
|
#include <limits>
|
|
|
|
namespace SOUI
|
|
{
|
|
|
|
STaskLoop::RunnableDisposer STaskLoop::kRunnableDisposer;
|
|
|
|
STaskLoop::STaskLoop() :
|
|
m_taskListLock(),
|
|
m_runningLock(),
|
|
m_thread(),
|
|
m_itemsSem(),
|
|
m_items(),
|
|
m_hasRunningItem(false),
|
|
m_runningItem(NULL,0),
|
|
m_nextTaskID(0)
|
|
{
|
|
}
|
|
|
|
STaskLoop::~STaskLoop()
|
|
{
|
|
stop();
|
|
}
|
|
|
|
void STaskLoop::start(const char * pszName,Priority priority)
|
|
{
|
|
{
|
|
SAutoLock autoLock(m_taskListLock);
|
|
m_items.clear();
|
|
if(pszName) m_strName = pszName;
|
|
}
|
|
_start(this, &STaskLoop::runLoopProc, priority);
|
|
}
|
|
|
|
void STaskLoop::stop()
|
|
{
|
|
int taskNum = getTaskCount();
|
|
|
|
m_thread.stop();
|
|
m_itemsSem.notify();
|
|
m_thread.waitForStop();
|
|
}
|
|
|
|
bool STaskLoop::isRunning()
|
|
{
|
|
return !m_thread.isStopped();
|
|
}
|
|
|
|
long STaskLoop::postTask(const IRunnable *runnable, bool waitUntilDone, int priority)
|
|
{
|
|
if (m_thread.isStopped())
|
|
{
|
|
return -1;
|
|
}
|
|
IRunnable *pCloneRunnable = runnable->clone();
|
|
if (Thread::getCurrentThreadID() == m_thread.getThreadID() && waitUntilDone)
|
|
{
|
|
pCloneRunnable->run();
|
|
pCloneRunnable->destroy();
|
|
return -1;
|
|
}
|
|
|
|
SSemaphore semaphore;
|
|
TaskItem item(pCloneRunnable,priority);
|
|
|
|
if (waitUntilDone)
|
|
{
|
|
item.semaphore = &semaphore;
|
|
}
|
|
|
|
m_taskListLock.Enter();
|
|
|
|
item.taskID = m_nextTaskID;
|
|
m_nextTaskID = (m_nextTaskID + 1) & ((std::numeric_limits<long>::max)());
|
|
std::list<TaskItem>::reverse_iterator it= m_items.rbegin();
|
|
while(it != m_items.rend())
|
|
{
|
|
if(it->nPriority>=priority)
|
|
{
|
|
m_items.insert(it.base(),item);
|
|
break;
|
|
}
|
|
it ++;
|
|
}
|
|
if(it==m_items.rend())
|
|
m_items.push_front(item);
|
|
|
|
m_taskListLock.Leave();
|
|
m_itemsSem.notify();
|
|
|
|
if (waitUntilDone)
|
|
{
|
|
int ret = semaphore.wait();
|
|
|
|
if (ret == RETURN_ERROR)
|
|
{
|
|
}
|
|
}
|
|
|
|
return item.taskID;
|
|
}
|
|
|
|
void STaskLoop::runLoopProc()
|
|
{
|
|
while (true)
|
|
{
|
|
if (m_thread.isStopping())
|
|
{
|
|
break;
|
|
}
|
|
|
|
m_itemsSem.wait(INFINITE);
|
|
|
|
{
|
|
SAutoLock autoLock(m_taskListLock);
|
|
SAutoLock autoRunningLock(m_runningLock);
|
|
SAutoLock autoRuningInfoLock(m_runningInfoLock);
|
|
m_hasRunningItem = false;
|
|
m_runingItemInfo.clear();
|
|
m_runningItem = TaskItem(NULL,0);
|
|
if (!m_items.empty())
|
|
{
|
|
m_hasRunningItem = true;
|
|
m_runningItem = m_items.front();
|
|
m_runingItemInfo = m_runningItem.getRunnableInfo();
|
|
m_items.pop_front();
|
|
}
|
|
}
|
|
|
|
|
|
{
|
|
SAutoLock autoRunningLock(m_runningLock);
|
|
if (m_hasRunningItem)
|
|
{
|
|
TaskItem item = m_runningItem;
|
|
item.runnable->run();
|
|
if (item.semaphore)
|
|
{
|
|
//通知一个task执行完毕
|
|
item.semaphore->notify();
|
|
}
|
|
}
|
|
{
|
|
SAutoLock autoRuningInfoLock(m_runningInfoLock);
|
|
m_hasRunningItem = false;
|
|
m_runingItemInfo.clear();
|
|
m_runningItem = TaskItem(NULL,0);
|
|
}
|
|
}
|
|
}// end of while
|
|
|
|
SAutoLock autoLock(m_taskListLock);
|
|
|
|
size_t itemsSize = m_items.size();
|
|
while (itemsSize > 0)
|
|
{
|
|
TaskItem item = m_items.front();
|
|
m_items.pop_front();
|
|
itemsSize--;
|
|
|
|
if (item.semaphore)
|
|
{
|
|
item.semaphore->notify();
|
|
}
|
|
}
|
|
|
|
m_items.clear();
|
|
}
|
|
|
|
bool STaskLoop::getName(char * pszBuf, int nBufLen)
|
|
{
|
|
SAutoLock autoLock(m_taskListLock);
|
|
if (m_strName.length() >= (size_t)nBufLen)
|
|
return false;
|
|
strcpy_s(pszBuf, nBufLen, m_strName.c_str());
|
|
return true;
|
|
}
|
|
|
|
void STaskLoop::cancelTasksForObject(void *object)
|
|
{
|
|
if (object == NULL)
|
|
{
|
|
return;
|
|
}
|
|
|
|
{
|
|
SAutoLock autoLock(m_taskListLock);
|
|
std::list<TaskItem>::iterator iter = m_items.begin();
|
|
|
|
while (iter != m_items.end())
|
|
{
|
|
TaskItem &item = *iter;
|
|
|
|
if (item.runnable->getObject() == object)
|
|
{
|
|
iter = m_items.erase(iter);
|
|
}
|
|
else
|
|
{
|
|
++iter;
|
|
}
|
|
}
|
|
}
|
|
{
|
|
SAutoLock autoLock(m_runningLock);
|
|
SAutoLock autoLockRunningInfo(m_runningInfoLock);
|
|
if(m_hasRunningItem)
|
|
{//make sure the running item is not belong to the to be canceled object.
|
|
m_hasRunningItem = false;
|
|
m_runingItemInfo.clear();
|
|
m_runningItem = TaskItem(NULL,0);
|
|
}
|
|
}
|
|
}
|
|
|
|
bool STaskLoop::cancelTask(long taskId)
|
|
{
|
|
SAutoLock autoLock(m_taskListLock);
|
|
std::list<TaskItem>::iterator itemIt = m_items.begin();
|
|
|
|
while (itemIt != m_items.end())
|
|
{
|
|
if (itemIt->taskID == taskId)
|
|
{
|
|
itemIt = m_items.erase(itemIt);
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
++itemIt;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
int STaskLoop::getTaskCount() const
|
|
{
|
|
SAutoLock autoLock(m_taskListLock);
|
|
|
|
return (int)m_items.size();
|
|
}
|
|
|
|
bool STaskLoop::getRunningTaskInfo(char *buf, int bufLen)
|
|
{
|
|
SAutoLock autoLock(m_runningInfoLock);
|
|
if(!m_hasRunningItem)
|
|
return false;
|
|
strcat_s(buf,bufLen-1,m_runingItemInfo.c_str());
|
|
return true;
|
|
}
|
|
|
|
|
|
SOUI_COM_C BOOL SOUI_COM_API TASKLOOP::SCreateInstance(IObjRef **ppTaskLoop)
|
|
{
|
|
*ppTaskLoop = new STaskLoop();
|
|
return TRUE;
|
|
}
|
|
|
|
}
|
|
|