Click
Loading...
Searching...
No Matches
Public Types | Public Member Functions | List of all members
Task Class Reference

Represents a frequently-scheduled computational task. More...

Inherits TaskLink.

Public Types

enum  { STRIDE1 = 1U<<16 , MAX_STRIDE = 1U<<31 }
 
enum  { MAX_TICKETS = 1<<15 , DEFAULT_TICKETS = 1<<10 }
 

Public Member Functions

 Task (TaskCallback f, void *user_data, int tid=-2)
 Construct a task that calls f with user_data argument.
 
 Task (Element *e)
 Construct a task that calls e ->run_task().
 
 ~Task ()
 Destroy a task.
 
TaskCallback callback () const
 Return the task's callback function.
 
void * user_data () const
 Return the task callback function's user data.
 
Element * element () const
 Return the task's owning element.
 
bool initialized () const
 Return true iff the task has been initialize()d.
 
int home_thread_id () const
 Return the task's home thread ID.
 
RouterThread * thread () const
 Return the thread on which this task is currently scheduled, or would be scheduled.
 
Router * router () const
 Return the router to which this task belongs.
 
Master * master () const
 Return the master where this task will be scheduled.
 
void initialize (Element *owner, bool schedule)
 Initialize the Task, and optionally schedule it.
 
void initialize (Router *router, bool schedule)
 Initialize the Task, and optionally schedule it.
 
bool scheduled () const
 Return true iff the task is currently scheduled to run.
 
void unschedule ()
 Unschedule the task.
 
void unschedule_notify (Element *e)
 Unschedule the task, sending a notification.
 
void reschedule ()
 Reschedule the task.
 
void reschedule_notify (Element *e)
 Reschedule the task, sending thread migration messages.
 
void fast_reschedule ()
 Reschedule a task from the task's callback function.
 
void strong_unschedule ()
 Unschedule the Task until strong_reschedule().
 
void strong_reschedule ()
 Reschedule the Task, undoing a prior strong_unschedule().
 
void move_thread (int new_thread_id)
 Move the Task to a new home thread.
 
int tickets () const
 Return the task's number of tickets.
 
void set_tickets (int n)
 Set the task's ticket count.
 
void adjust_tickets (int delta)
 Add delta to the Task's ticket count.
 
bool fire ()
 Fire the task by calling its callback function.
 

Detailed Description

Represents a frequently-scheduled computational task.

Click schedules a router's CPU or CPUs with one or more task queues. These queues are simply lists of tasks, which represent functions that would like unconditional access to the CPU. Tasks are generally associated with elements. When scheduled, most tasks call some element's run_task() method.

Click tasks are represented by Task objects. An element that would like special access to a router's CPU should include and initialize a Task instance variable.

Tasks are called very frequently, up to tens of thousands of times per second. Elements generally use Tasks for frequent tasks, and implement their own algorithms for scheduling and unscheduling the tasks when there's work to be done. For infrequent events, it is far more efficient to use Timer objects.

A Task's callback function, which is called when the task fires, has bool return type. The callback should return true if the task did useful work, and false if it was not able to do useful work (for example, because there were no packets in the configuration to return). Adaptive algorithms may use this information to fine-tune Click's scheduling behavior.

Since Click tasks are cooperatively scheduled, executing a task should not take a long time. Slow tasks can inappropriately delay timers and other periodic events.

This code shows how Task objects tend to be used. For fuller examples, see InfiniteSource and similar elements.

class InfiniteSource { ...
bool run_task(Task *t);
private:
Task _task;
};
InfiniteSource::InfiniteSource() : _task(this) {
}
int InfiniteSource::initialize(ErrorHandler *errh) {
ScheduleInfo::initialize_task(this, &_task, errh);
return 0;
}
bool InfiniteSource::run_task(Task *) {
Packet *p = ... generate packet ...;
output(0).push(p);
if (packets left to send)
_task.fast_reschedule();
return true; // the task did useful work
}
Error reporting class.
Definition error.hh:90
A network packet.
Definition packet.hh:68
Represents a frequently-scheduled computational task.
Definition task.hh:49

Constructor & Destructor Documentation

◆ Task() [1/2]

Task::Task ( TaskCallback  f,
void *  user_data,
int  tid = -2 
)
inline

Construct a task that calls f with user_data argument.

Parameters
fcallback function
user_dataargument for callback function

Constructs a task that, when fired, calls f like so:

bool work_done = f(task, user_data);
void * user_data() const
Return the task callback function's user data.
Definition task.hh:103

where task is a pointer to this task. f should return true if the task accomplished some meaningful work, and false if it did not. For example, a task that polls a network driver for packets should return true if it emits at least one packet, and false if no packets were available.

◆ Task() [2/2]

Task::Task ( Element *  e)
inline

Construct a task that calls e ->run_task().

Parameters
eelement to call

Constructs a task that, when fired, calls the element e's run_task() method, passing this Task as an argument.

See also
Task(TaskCallback, void *)

◆ ~Task()

Task::~Task ( )

Destroy a task.

Unschedules the task if necessary.

Member Function Documentation

◆ callback()

TaskCallback Task::callback ( ) const
inline

Return the task's callback function.

Returns null if the task was constructed with the Task(Element *) constructor.

◆ user_data()

void * Task::user_data ( ) const
inline

Return the task callback function's user data.

◆ element()

Element * Task::element ( ) const
inline

Return the task's owning element.

◆ initialized()

bool Task::initialized ( ) const
inline

Return true iff the task has been initialize()d.

◆ home_thread_id()

int Task::home_thread_id ( ) const
inline

Return the task's home thread ID.

This is the thread_id() of the thread on which this Task would run if it were scheduled. This need not equal the ID of the current thread(), since changes in home_thread_id() aren't always implemented immediately (because of locking issues).

never

◆ thread()

RouterThread * Task::thread ( ) const
inline

Return the thread on which this task is currently scheduled, or would be scheduled.

Usually, task->thread()->thread_id() == task->home_thread_id(). They can differ, however, if move_thread() was called but the task hasn't yet been moved to the new thread.

◆ router()

Router * Task::router ( ) const
inline

Return the router to which this task belongs.

◆ master()

Master * Task::master ( ) const

Return the master where this task will be scheduled.

◆ initialize() [1/2]

void Task::initialize ( Element *  owner,
bool  schedule 
)

Initialize the Task, and optionally schedule it.

Parameters
ownerspecifies the element owning the Task
scheduleif true, the Task will be scheduled immediately

This function must be called on every Task before it is used. The corresponding router's ThreadSched, if any, is used to determine the task's initial thread assignment. The task initially has the default number of tickets, and is scheduled iff schedule is true.

An assertion will fail if a Task is initialized twice.

Most elements call ScheduleInfo::initialize_task() to initialize a Task object. The ScheduleInfo method additionally sets the task's scheduling parameters, such as ticket count and thread preference, based on a router's ScheduleInfo. ScheduleInfo::initialize_task() calls Task::initialize().

◆ initialize() [2/2]

void Task::initialize ( Router *  router,
bool  schedule 
)

Initialize the Task, and optionally schedule it.

Parameters
routerspecifies the router owning the Task
scheduleif true, the Task will be scheduled immediately

This function is shorthand for Task::initialize(router ->root_element(), scheduled). However, it is better to explicitly associate tasks with real elements.

◆ scheduled()

bool Task::scheduled ( ) const
inline

Return true iff the task is currently scheduled to run.

Note
A scheduled task will usually run very soon, but not always; due to locking issues, the effects of some reschedule() requests may be delayed. Although a task unscheduled with strong_unschedule() may appear scheduled(), it will not run until strong_reschedule() is called.

◆ unschedule()

void Task::unschedule ( )
inline

Unschedule the task.

After unschedule() returns, the task will not run until it is rescheduled with reschedule().

See also
reschedule, strong_unschedule

◆ unschedule_notify()

void Task::unschedule_notify ( Element *  e)

Unschedule the task, sending a notification.

◆ reschedule()

void Task::reschedule ( )
inline

Reschedule the task.

The task is rescheduled on its home thread. It will eventually run, unless its home thread is quiescent or it has been strong_unschedule()d.

See also
unschedule, strong_reschedule

◆ reschedule_notify()

void Task::reschedule_notify ( Element *  e)

Reschedule the task, sending thread migration messages.

◆ fast_reschedule()

void Task::fast_reschedule ( )
inline

Reschedule a task from the task's callback function.

Warning
Only call task.fast_reschedule() while task is being fired, i.e., in its callback function. It is an error to call @task.fast_reschedule() at other times – the task may not actually be rescheduled.

Here's a typical, correct use of fast_reschedule():

class MyElement : public Element {
... Task _task; ... bool run_task(Task *t); ...
};
bool MyElement::run_task(Task *) {
do_some_work();
_task.fast_reschedule();
return true;
}
Base class for Click elements.
Definition element.hh:42

This assumes, however, that run_task() is only called directly by the driver. If you call run_task() from another context, _task may not actually be scheduled.

void MyElement::run_timer(Timer *) {
run_task(); // XXX might not reschedule _task!
}
Triggers execution at a given time.
Definition timer.hh:14

◆ strong_unschedule()

void Task::strong_unschedule ( )
inline

Unschedule the Task until strong_reschedule().

Like unschedule(), but in addition, future reschedule() calls will not actually schedule the task. Only after strong_reschedule() will the task run again.

See also
strong_reschedule, unschedule

◆ strong_reschedule()

void Task::strong_reschedule ( )
inline

Reschedule the Task, undoing a prior strong_unschedule().

This function undoes any previous strong_unschedule() and reschedules the task.

See also
reschedule, strong_unschedule

◆ move_thread()

void Task::move_thread ( int  new_thread_id)

Move the Task to a new home thread.

The home thread ID is set to new_thread_id. The task, if it is currently scheduled, is rescheduled on thread new_thread_id (which generally takes some time to take effect). If new_thread_id is less than zero or greater than the number of threads on the router, the task is scheduled on a quiescent thread that never actually runs.

◆ tickets()

int Task::tickets ( ) const
inline

Return the task's number of tickets.

Tasks with larger numbers of tickets are scheduled more often. Tasks are initialized with tickets() == DEFAULT_TICKETS.

See also
set_tickets, adjust_tickets

◆ set_tickets()

void Task::set_tickets ( int  n)
inline

Set the task's ticket count.

Parameters
nthe ticket count

The ticket count n is pinned to the range [1, MAX_TICKETS].

See also
tickets, adjust_tickets

◆ adjust_tickets()

void Task::adjust_tickets ( int  delta)
inline

Add delta to the Task's ticket count.

Parameters
deltaadjustment to the ticket count

The ticket count cannot be adjusted below 1 or above MAX_TICKETS.

See also
set_tickets

◆ fire()

bool Task::fire ( )
inline

Fire the task by calling its callback function.

This function is generally called by the RouterThread implementation; there should be no need to call it yourself.


The documentation for this class was generated from the following files: