//////////////////////////////////////////////////////////////////
//
// job.h
//
// Abstraction of threads' jobs
//
// Copyright (c) Citron Network Inc. 2002-2003
//
// This work is published under the GNU Public License (GPL)
// see file COPYING for details.
// We also explicitely grant the right to link this code
// with the OpenH323 library.
//
// initial author: Chin-Wei Huang <cwhuang@linux.org.tw>
// initial version: 04/21/2003
//
//////////////////////////////////////////////////////////////////
#ifndef JOB_H
#define JOB_H "@(#) $Id: job.h,v 1.7 2006/04/14 13:56:19 willamowius Exp $"
#include "name.h"
/** The base abstract class that represents job objects.
This class implements the way to execute the job.
Derived classes implement actual jobs (override Run()).
Jobs are executed and managed by internal Job managment system
consisting of the singleton Agent object and Worker threads
that accept and execute new Jobs.
Specialized Job examples are:
Jobs - executes series of Tasks
RegularJob - executes a Task again and again until stopped
SimpleJob - calls some funtion with one pointer-type argument
SimpleJobA - calls some funtion with two arguments : pointer-type and reference
SimpleClassJob - calls a member function of some class that takes no arguments
SimpleClassJobA - calls a member function of some class that takes one
argument of reference type
*/
class Job : public NamedObject
{
public:
virtual ~Job();
/// Perform the actual job, return when it is done
virtual void Run() = 0;
/// Stop a running job
virtual void Stop();
/** Execute the job in a first idle Worker thread.
The function returns immediatelly and this object
is delete automatically, when the job is finished.
*/
void Execute();
/// Stop all jobs being currently executed by Worker threads
static void StopAll();
};
/** Similar to the Job, but is even more abstract. It does not contain
any Task management routines. Main purpose of this class it to provide
a way to represent a serie of Tasks that are to be executed one after another.
*/
class Task
{
public:
Task() : m_next(NULL), m_done(false) {}
virtual ~Task();
/// Perform the actual task and return when it is finished
virtual void Exec() = 0;
/** @return
true if the task is done and a next task is being processed.
*/
bool IsDone() const { return m_done; }
/// Setup a task to be executed when this one is done
void SetNext(
/// next task to be executed
Task* next
)
{
if (m_next != NULL && m_next != this)
m_next->SetNext(next);
else
m_next = next;
}
/** @return
true if this is not the last task.
*/
bool HasNext() const { return m_next != NULL; }
/** Get a next task and mark this one as done.
@return
The task that is next or NULL if this is the last task.
*/
Task* DoNext()
{
Task* next = m_next;
if (next != this) // do not set m_done flag for circular task
m_done = true;
return next;
}
private:
/// next task to be executed when this one is done
Task* m_next;
/// true if the task is finished
bool m_done;
};
/// Execute a task or a serie of tasks
class Jobs : public Job
{
public:
Jobs(
/// task to be executed
Task* task
) : m_current(task) {}
/// process the associated task (override from Job)
virtual void Run();
private:
/// task (or a serie of tasks) to be executed
Task* m_current;
};
/** Regular job - executes the same task until it is stopped
(by calling Stop()). The actual work is to be done in the virtual
Exec() method in derived classes. RegularJob is an abstract class.
*/
class RegularJob : public Job
{
public:
RegularJob();
/** @return
true if the job has not been yet stopped
*/
bool IsRunning() const { return !m_stop; }
/// override from Job
virtual void Run();
/// repeated activity to be executed by this RegularJob
virtual void Exec() = 0;
/** Stop this job. NOTE: Acquire m_deletionPreventer mutex first
to make sure this object is not deleted before the method that
called Stop returns (if Stop is called from a derived class).
*/
virtual void Stop();
protected:
// new virtual function
/// Callback function that is called before the job is started.
virtual void OnStart();
/** Callback function that is called when the job is stopped.
NOTE: This function is called with m_deletionPreventer mutex acquired.
*/
virtual void OnStop();
/// Wait for a signal (Signal())
void Wait() { m_sync.Wait(); }
/** Wait for a signal (Signal()).
@return
true if the sync point has been signalled.
*/
bool Wait(
/// time to wait for the sync point to be signalled
const PTimeInterval& timeout
)
{
return m_sync.Wait(timeout) ? true : false;
}
/// Send a signal to the waiting task
void Signal() { m_sync.Signal(); }
protected:
/// can be used when calling Stop to prevent the job to be deleted
/// (and invalid object being referenced) before the function
/// that called Stop returns
PMutex m_deletionPreventer;
private:
/// used by Wait and Signal member functions
PSyncPoint m_sync;
/// true if the job should be stopped
bool m_stop;
};
template<class F, class T>
class SimpleJob : public Job {
public:
SimpleJob(const F & _f, T *_t) : f(_f), t(_t) {}
virtual void Run() { f(t); }
private:
const F f;
T *t;
};
template<class F, class T, class A>
class SimpleJobA : public Job {
public:
SimpleJobA(const F & _f, T *_t, const A & _a) : f(_f), t(_t), a(_a) {}
virtual void Run() { f(t, a); }
private:
const F f;
T *t;
A a;
};
template<class T>
class SimpleClassJob : public Job {
public:
SimpleClassJob(T *_t, void (T::*_j)()) : t(_t), j(_j) {}
virtual void Run() { (t->*j)(); }
private:
T *t;
void (T::*j)();
};
template<class T, class A>
class SimpleClassJobA : public Job {
public:
typedef void (T::*CJob)(A);
SimpleClassJobA(T *_t, CJob _j, A _a) : t(_t), j(_j), a(_a) {}
virtual void Run() { (t->*j)(a); }
private:
T *t;
CJob j;
A a;
};
template<class T>
void CreateJob(T *t, void (T::*j)(), const char *n)
{
Job *newjob = new SimpleClassJob<T>(t, j);
newjob->SetName(n);
newjob->Execute();
}
template<class T, class A>
void CreateJob(T *t, void (T::*j)(A), A a, const char *n)
{
Job *newjob = new SimpleClassJobA<T, A>(t, j, a);
newjob->SetName(n);
newjob->Execute();
}
#endif // JOB_H
syntax highlighted by Code2HTML, v. 0.9.1