/***************************** LICENSE START ***********************************

 Copyright 2012 ECMWF and INPE. This software is distributed under the terms
 of the Apache License version 2.0. In applying this license, ECMWF does not
 waive the privileges and immunities granted to it by virtue of its status as
 an Intergovernmental Organization or submit itself to any jurisdiction.

 ***************************** LICENSE END *************************************/

//
// .NAME:
//  Task
//
// .AUTHOR:
//  Gilberto Camara, Baudouin Raoult and Fernando Ii
//
// .SUMMARY:
//  Provide support for handling a list of tasks. 
//  The idea is that there are some lengthy tasks which should
//  better be delayed. Therefore, these tasks are placed in a queue
//  and are executed at a covenient moment.
//
//  A task consists of an object and a called procedure. 
//  Executing a task is done by calling "object->Proc()"
// .CLIENTS:
//  Page, SubPage (which ask for a new drawing)
//
//
// .RESPONSABILITIES:
//
//  1. Put tasks in a task list 
//
//  2. Execute all tasks in the list  
//     when the "Flush" method is called
//
// .COLLABORATORS:
//
//
// .BASE CLASS:
//
//
// .DERIVED CLASSES:
//
//
// .REFERENCES:
//
//
#ifndef TaskList_H
#define TaskList_H

#include <inc_stl.h>

class TaskBase;

typedef list < TaskBase* > PendingTaskList;

class TaskBase {

public:

	// Contructors
	TaskBase();

	// Destructor
	virtual ~TaskBase(); // Change to virtual if base class

	// Abstract method which should be supplied by the derived class
	virtual void Execute() = 0;

	// Execute all tasks in the list
	static void Flush();

	// Execute all pending tasks (called first)
	static void FlushPending();

	// Execute all clean up tasks (called in the end)
	static void FlushCleanUp();

	// Register a task on the pending list
	static void RegisterTask ( TaskBase* );

	// Register a task on the cleanup list
	static void RegisterCleanUpTask ( TaskBase* );

private:

	// List of tasks to be executed first
	static PendingTaskList     pendingTaskList_;

	// List of tasks to be executed on cleanup
	static PendingTaskList     cleanupTaskList_;

	// Method used when in multi_thread mode
	static void* Run(void*);
};

template <class T>
class Task : public TaskBase
{
	T&        calledObject_;
	typedef void(T::* Procedure)();
	Procedure calledProc_;

public:
	Task ( T& object, Procedure proc) : 
		calledObject_( object ), calledProc_( proc ) {}

	// Execute - calls object->procedure
	virtual void Execute ()
		{ (calledObject_.*calledProc_)(); }
};

template<class T>
void AddTask ( T& object, void(T::*proc)() )
{
	TaskBase::RegisterTask ( new Task<T>(object,proc));
}

template<class T>
void AddCleanUpTask ( T& object, void(T::*proc)() )
{
	TaskBase::RegisterCleanUpTask ( new Task<T>(object,proc));
}

#endif
