task_manager.cpp

Go to the documentation of this file.
00001 
00005 /* Copyright, 2000 Nevrax Ltd.
00006  *
00007  * This file is part of NEVRAX NEL.
00008  * NEVRAX NEL is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2, or (at your option)
00011  * any later version.
00012 
00013  * NEVRAX NEL is distributed in the hope that it will be useful, but
00014  * WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00016  * General Public License for more details.
00017 
00018  * You should have received a copy of the GNU General Public License
00019  * along with NEVRAX NEL; see the file COPYING. If not, write to the
00020  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00021  * MA 02111-1307, USA.
00022  */
00023 
00024 #include "stdmisc.h"
00025 
00026 #include "nel/misc/task_manager.h"
00027 #include "nel/misc/big_file.h"
00028 
00029 using namespace std;
00030 
00031 #define NLMISC_DONE_TASK_SIZE 20
00032 
00033 namespace NLMISC {
00034 
00035 /*
00036  * Constructor
00037  */
00038 CTaskManager::CTaskManager() : _RunningTask (""), _TaskQueue (""), _DoneTaskQueue ("")
00039 {
00040     _IsTaskRunning = false;
00041     _ThreadRunning = true;
00042     CSynchronized<string>::CAccessor currentTask(&_RunningTask);
00043     currentTask.value () = "";
00044     _Thread = IThread::create(this);
00045     _Thread->start();
00046     _ChangePriorityCallback = NULL;
00047 }
00048 
00049 /*
00050  * Destructeur
00051  */
00052 CTaskManager::~CTaskManager()
00053 {
00054     _ThreadRunning = false;
00055     while(!_ThreadRunning)
00056         nlSleep(10);
00057 
00058     // There should be no remaining Tasks
00059     CSynchronized<std::list<CWaitingTask> >::CAccessor acces(&_TaskQueue);
00060     nlassert(acces.value().empty());
00061     _Thread->wait();
00062     delete _Thread;
00063     _Thread = NULL;
00064 
00065 }
00066 
00067 // Manage TaskQueue
00068 void CTaskManager::run(void)
00069 {
00070     IRunnable *runnableTask;
00071     float priorityTask;
00072     while(_ThreadRunning)
00073     {
00074         {
00075             CSynchronized<list<CWaitingTask> >::CAccessor acces(&_TaskQueue);
00076             if(acces.value().empty())
00077             {
00078                 runnableTask = NULL;
00079             }
00080             else
00081             {
00082                 // Update task priorities
00083                 changeTaskPriority ();
00084 
00085                 // Get the best task
00086                 list<CWaitingTask> &taskList = acces.value();
00087                 list<CWaitingTask>::iterator ite = taskList.begin();
00088                 list<CWaitingTask>::iterator bestIte = ite;
00089                 while (ite != taskList.end())
00090                 {
00091                     if (ite->Priority < bestIte->Priority)
00092                         bestIte = ite;
00093 
00094                     // Next task;
00095                     ite++;
00096                 }
00097 
00098                 _IsTaskRunning = true;
00099                 runnableTask = bestIte->Task;
00100                 priorityTask = bestIte->Priority;
00101                 taskList.erase (bestIte);
00102             }
00103         }
00104         if(runnableTask)
00105         {
00106             {
00107                 CSynchronized<string>::CAccessor currentTask(&_RunningTask);
00108                 string temp;
00109                 runnableTask->getName(temp);
00110                 currentTask.value () = temp + " " + toString (priorityTask);
00111             }
00112             runnableTask->run();
00113             {
00114                 CSynchronized<string>::CAccessor currentTask(&_RunningTask);
00115                 CSynchronized<deque<string> >::CAccessor doneTask(&_DoneTaskQueue);
00116                 doneTask.value().push_front (currentTask.value ());
00117                 currentTask.value () = "";
00118                 if (doneTask.value().size () > NLMISC_DONE_TASK_SIZE)
00119                     doneTask.value().resize (NLMISC_DONE_TASK_SIZE);
00120             }
00121 
00122             _IsTaskRunning = false;
00123         }
00124         else
00125         {
00126             sleepTask();
00127         }
00128     }
00129     CBigFile::getInstance().currentThreadFinished();
00130     _ThreadRunning = true;
00131 }
00132 
00133 // Add a task to TaskManager
00134 void CTaskManager::addTask(IRunnable *r, float priority)
00135 {
00136     CSynchronized<std::list<CWaitingTask> >::CAccessor acces(&_TaskQueue);
00137     acces.value().push_back(CWaitingTask(r, priority));
00138 }
00139 
00141 bool CTaskManager::deleteTask(IRunnable *r)
00142 {
00143     CSynchronized<list<CWaitingTask> >::CAccessor acces(&_TaskQueue);
00144     for(list<CWaitingTask>::iterator it = acces.value().begin(); it != acces.value().end(); it++)
00145     {
00146         if(it->Task == r)
00147         {
00148             acces.value().erase(it);
00149             return true;
00150         }
00151     }
00152     return false;
00153 }
00154 
00156 uint CTaskManager::taskListSize(void)
00157 {
00158     CSynchronized<list<CWaitingTask> >::CAccessor acces(&_TaskQueue);
00159     return acces.value().size();
00160 }
00161 
00162 
00163 void    CTaskManager::waitCurrentTaskToComplete ()
00164 {
00165     while (_IsTaskRunning)
00166         sleepTask();
00167 }
00168 
00169 // ***************************************************************************
00170 
00171 void CTaskManager::dump (std::vector<std::string> &result)
00172 {
00173     CSynchronized<string>::CAccessor accesCurrent(&_RunningTask);
00174     CSynchronized<list<CWaitingTask> >::CAccessor acces(&_TaskQueue);
00175     CSynchronized<deque<string> >::CAccessor accesDone(&_DoneTaskQueue);
00176 
00177     const list<CWaitingTask> &taskList = acces.value();
00178     const deque<string> &taskDone = accesDone.value();
00179     const string &taskCurrent = accesCurrent.value();
00180 
00181     // Resize the destination array
00182     result.clear ();
00183     result.reserve (taskList.size () + taskDone.size () + 1);
00184 
00185     // Add the done strings
00186     deque<string>::const_reverse_iterator iteDone = taskDone.rbegin ();
00187     while (iteDone != taskDone.rend ())
00188     {
00189         result.push_back ("Done : " + *iteDone);
00190 
00191         // Next task
00192         iteDone++;
00193     }
00194 
00195     // Add the current string
00196     if (!taskCurrent.empty())
00197     {
00198         result.push_back ("Current : " + taskCurrent);
00199     }
00200 
00201     // Add the waiting strings
00202     list<CWaitingTask>::const_iterator ite = taskList.begin ();
00203     while (ite != taskList.end ())
00204     {
00205         string name;
00206         ite->Task->getName (name);
00207         result.push_back ("Waiting : " + name + " " + toString(ite->Priority));
00208 
00209         // Next task
00210         ite++;
00211     }
00212 }
00213 
00214 // ***************************************************************************
00215 void CTaskManager::clearDump()
00216 {
00217     CSynchronized<deque<string> >::CAccessor accesDone(&_DoneTaskQueue);
00218     accesDone.value().clear();
00219 }
00220 
00221 // ***************************************************************************
00222 
00223 uint CTaskManager::getNumWaitingTasks()
00224 {
00225     CSynchronized<list<CWaitingTask> >::CAccessor acces(&_TaskQueue);
00226     return acces.value().size();
00227 }
00228 
00229 // ***************************************************************************
00230 
00231 void CTaskManager::changeTaskPriority ()
00232 {
00233     if (_ChangePriorityCallback)
00234     {
00235         CSynchronized<list<CWaitingTask> >::CAccessor acces(&_TaskQueue);
00236         list<CWaitingTask> &taskList = acces.value();
00237 
00238         list<CWaitingTask>::iterator ite = taskList.begin();
00239         while(ite != taskList.end())
00240         {
00241             // Get the new priority
00242             ite->Priority = _ChangePriorityCallback->getTaskPriority(*(ite->Task));
00243 
00244             // Next task
00245             ite++;
00246         }
00247     }
00248 }
00249 
00250 // ***************************************************************************
00251 
00252 void CTaskManager::registerTaskPriorityCallback (IChangeTaskPriority *callback)
00253 {
00254     _ChangePriorityCallback = callback;
00255 }
00256 
00257 // ***************************************************************************
00258 
00259 } // NLMISC

Generated on Thu Jan 7 08:26:34 2010 for NeL by  doxygen 1.6.1