#ifndef OS_TASKLIB_H
#define OS_TASKLIB_H

#include "ossync.h"

///////////////////////////////////
//OS task typedefines
///////////////////////////////////
// Task states
typedef enum TaskState
{
	taskempty,
	taskinitialized,
	taskrunning,
	taskreset,
	taskshutdown
};

typedef int TaskId;
typedef int (*FUNCPTR)(...);

// This is for C++ static methods.
# ifdef _VXWORKS_
typedef FUNCPTR THR_FUNC;  // where typedef int (*FUNCPTR) (...)
# else
typedef void *(*THR_FUNC)(void *);
# endif /* VXWORKS */

extern "C"{
# ifdef _VXWORKS_
	typedef FUNCPTR THR_C_FUNC;  
# else
	typedef void *(*THR_C_FUNC)(void *);
# endif
}
#define TASK_READY	0
#define TASK_PEND	1
#define TASK_DELAY	2
#define	TASK_SUSPEND	3

// task creation/deletion defines 
#ifdef _VXWORKS_
	#define THR_SUSPENDED  	      0x01
	#define VX_UNBREAKABLE        0x0002  /* breakpoints ignored */
	#define VX_FP_TASK            0x0008  /* floating point coprocessor */
	#define VX_PRIVATE_ENV        0x0080  /* private environment support */
	#define VX_NO_STACK_FILL      0x0100  /* do not stack fill for
                                             checkstack () */
	#define THREAD_PRIORITY_HIGHEST			10
	#define THREAD_PRIORITY_TIME_CRITICAL	60	
	#define THREAD_PRIORITY_ABOVE_NORMAL    80	
	#define THREAD_PRIORITY_NORMAL			100	
	#define THREAD_PRIORITY_BELOW_NORMAL    150	
	#define THREAD_PRIORITY_IDLE			250
	#define DEFAULT_STACK_SIZE	20000	/* default stack size of spawned task */
	#define DEFAULT_TASK_OPTIONS    VX_FP_TASK 
#else
	# pragma once
	#include <afxwin.h>
	#define THR_SUSPENDED  CREATE_SUSPENDED  
#endif /* VXWORKS */

#ifdef _VXWORKS_
	typedef int TaskHandle;
	# define TASKNULL 0
#else
	typedef HANDLE TaskHandle;
#endif /* VXWORKS */

///////////////////////////////////
//OS task defines and task functions
//the underlying implementation uses the
//_WIN32_, and _VXWORKS_ define
///////////////////////////////////
unsigned int sleep(unsigned int secs);
#ifdef _WIN32_
	int sysClkRateGet();
#endif//_WIN32_

// Forward declaration
class TaskBase;
class ThreadMutex;

// The thread entry point.  This must be an extern "C" to 
// run on Visual C++ compiler ver. 5.0
extern "C" void *taskAdapter (void *args);

/*----------------------------------------------------------
CLASS TaskAdapter
	
AUTHOR
	This is based on the ACE_Thread_Adapter	class developed by Doug Schmidt. 
	Copyright Washington University, St. Louis.  
	This has been modified to meet the MBARI coding conventions
    and all OS support except WINNT and VxWorks has been removed.

DESCRIPTION
	Converts a C++ function into a function that can be called 
	from a <_beginthreadex>) that expects an extern "C" entry point. 
	This class is used in <TaskWrapper::create>.  In general, the
	thread that creates an object of this class is different from
	the thread that calls <invoke> on this object.  Therefore,
	the <invoke> method is responsible for deleting itself.
---------------------------------------------------------*/
 
class TaskAdapter
{
public:
  TaskAdapter (THR_FUNC userfunc, 
			   void *arg, 
			   THR_C_FUNC entryPoint);
  // Constructor.

  void *invoke (void);
  // Execute the <user_func_> with the <arg>.  This function deletes
  // <this>, thereby rendering the object useless after the call
  // returns.

  THR_C_FUNC entryPoint (void);
  // Accessor for the C entry point function to the OS thread creation
  // routine.

  virtual ~TaskAdapter (void);
  // Ensure that this object must be allocated on the heap.

private:

  THR_FUNC _userFunc;
  // Thread startup function passed in by the user (C++ linkage).

  void *_arg;
  // Argument to thread startup function.
  
  THR_C_FUNC _entryPoint;
  // Entry point to the underlying OS thread creation call (C
  // linkage).

};

/*----------------------------------------------------------------
CLASS
	TaskWrapper

DESCRIPTION
	This class provides a common interface that is mapped onto
	_VXWORKS_ tasks, and _WIN32_ threads.  This is based on the ACE_Thread
	class developed by Doug Schmidt. Copyright Washington University, 
	St. Louis.  This has been modified to meet the MBARI coding conventions,
    and some functionality has been removed.
----------------------------------------------------------------*/
class TaskWrapper
{
  friend TaskBase;

protected:

  TaskWrapper();

  ~TaskWrapper();

  static int create(char *name,
			THR_FUNC func,
			void *args,
			int flags,
			TaskHandle *thrhandle,
			TaskId *thrid,
			int priority,
			size_t stacksize);
  
  // Continue the execution of a previously suspended thread.
  static long int resume (TaskHandle *);
  
  // Suspend the execution of a particular thread.
  static long int suspend (TaskHandle *);
  
  // Set the priority of a particular thread.
  // Not yet implemented for vxworks
  static int setprio (TaskHandle *, int prio);
  
  // Return the unique kernel handle of the thread.  Note that on
  // _WIN32_ this is actually a pseudohandle, which cannot be shared
  // with other processes or waited on by threads.  To locate the real
  // handle, please use the id() method.
  static void self (TaskHandle * &thandle);
  
  // Return the unique ID of the thread.
  static TaskId id (void);
  
  // Exit the current thread and return "status".
  static void exit (TaskId tid, void *status = 0);

  // Return the exit code
  static int exitCode(TaskHandle *h);

};
/*-------------------------------------------------------
CLASS 
  TaskBase

TITLE
  Direct base class for the Task template. This is based on the
  from the TaskBase class.  Copyright Washington University, 
  St. Louis.
  Please see http: //www.cs.wustl.edu/~schmidt/ for more details.

DESCRIPTION
  This class factors out the non-template code in order to
  reduce template bloat. 
  This has been modified to meet the MBARI coding conventions,
  and some functionality has been removed (such as ThreadManager).
----------------------------------------------------------*/
class TaskBase
{
  
public:
  //Initialization and termination methods.
  // Constructor.
  TaskBase (); 

  // Destructor.
  virtual ~TaskBase (void);

  // Returns task id. OS dependent.  
  TaskId id();

  // Returns the task exit Code. OS dependent.
  int exitCode();

  // Kill task now. This will fail if the task is not active
  void kill();

  //Initialization and termination hooks

  // Note that these methods *must* be defined by subclasses.

  // This is where the actual task specific code is called.  
  virtual void * run(void);

  // Hook called to open a Task.  <args> can be used to pass arbitrary
  // information into <open>. TODO: this is generally not used remove
  virtual int open (void *args = 0);

  // Hook called from <ThreadExit> during thread exit and from
  // the default implemenation of <moduleclosed>.  Call this method
  // to close the active task. This will set a flag to shutdown the
  // task
  virtual int close (void);

  // Runs the logic to invoke the run hook, and close hooks
  static void * svc(void *args);

  int activate( char *name, 
		   int priority, 
		   int flags, 
		   int stackSize,
		   TaskBase *task = 0);

  // Turn the task into an active object at <priority> level, 
  // with option
  // Returns -1 if failure
  // occurs, returns 1 if Task is already an active object and
  // returns 0 if Task was not already an active
  // object and a thread is created successfully    

  // Wait for thread running in this task to exit up to <milliSeconds>.
  virtual int wait (int milliSeconds);

  //Suspend/resume a Task
  virtual int suspendTask (void);

  // Suspend a task.
  virtual int resumeTask(void);
  // Resume a suspended task.

  static void cleanup (void *object);
  // Cleanup hook that is called when a thread exits to gracefully
  // shutdown an <Task>.

private:	
  // Count of the number of threads running within the task.  If this
  // value is > 0 then we're an active object and the value of
  // <thrcount> is the number of active threads at this instant.  If
  // the value == 0, then we're a passive object.
  int _thrCount;

  // Task flags.
  int _flags;
  
  TaskId _thrid;

  TaskHandle _thrhandle;  
  
  // Protect the state of a Task during concurrent operations.
  ThreadMutex _lock;

private:

};
#endif // ! defined OS_TASKLIB_H


