//-----------------------------------------------------------------------------
// Copyright (c) 1991,1992 Southeastern Universities Research Association,
//                         Continuous Electron Beam Accelerator Facility
//
// This software was developed under a United States Government license
// described in the NOTICE file included as part of this distribution.
//
//-----------------------------------------------------------------------------
//
// Description:
//      general cdev callback class
//
// Author:  Jie Chen and Walt Akers
//
// Revision History:
//   cdevCallback.h,v
// Revision 1.10  1998/01/29  15:20:05  akers
// Ongoing development
//
// Revision 1.9  1997/07/16  18:38:41  akers
// Testing for function_ in fireCallback
//
// Revision 1.8  1997/03/03  17:35:35  chen
// add buffering to channel access connection
//
// Revision 1.7  1996/12/19  15:22:33  akers
// Ongoing development
//
// Revision 1.6  1996/12/18  13:32:28  akers
// Added support for incomplete transactions and fireCallback method
//
// Revision 1.4  1995/09/05  17:18:23  chen
// add freelist and overload new/delete
//
// Revision 1.3  1995/07/05  19:28:50  chen
// minor changes
//
// Revision 1.2  1995/07/05  18:36:39  chen
// Allow inheritance
//
// Revision 1.1.1.1  1995/06/16  17:14:10  epics
// initial import of cdev
//
//
#ifndef _CDEV_CALLBACK_H
#define _CDEV_CALLBACK_H

#include <stdio.h>
#include <string.h>
#include <cdevSpec.h>

class cdevRequestObject;
class cdevData;

typedef void(*cdevCallbackFunction) (int status, 
void *userarg, 
cdevRequestObject &obj, 
cdevData &result);

class CDEV_CLASS_SPEC cdevCallback
{
public:
  // constructor and destructor
  cdevCallback(void);
  cdevCallback(cdevCallbackFunction, void *userarg);
  cdevCallback(const cdevCallback &callback);
  cdevCallback &operator=(const cdevCallback &callback);
  virtual~cdevCallback(void);
	
  virtual cdevCallbackFunction callbackFunction(void) const;
  // PURPOSE: return user callback function 
  // REQUIRE: nothing
  // PROMISE: return 0 if there nothing
	
  virtual void *userarg(void) const;
  // PURPUSE: return user arguments
  // REQUIRE: nothing
  // PROMISE: a user argument pointer
	
  int operator == (const cdevCallback &callback);
  int operator != (const cdevCallback &callback);
  // PURPOSE: if two cdevCallbacks have the same user function and user
  //          arguments, == return true
  // REQUIRE: nothing
  // PROMISE: 
	
  void *operator new(size_t size);
  void operator delete(void *p, size_t size);
  // PURPOSE: overloaded new and delete operator. 
  // REQUIRE: none
  // PROMISE: 
  
  // *********************************************************************
  // * The fireCallback method is allows the developer to execute the 
  // * callback function that is specified in the cdevCallback object
  // * and set the incomplete_ flag to the appropriate value prior to
  // * execution, and then restore it to its default value before
  // * returning.
  // *
  // * The value provided in the "partial" parameter will be used to set
  // * the incomplete_ flag.
  // *********************************************************************
  void fireCallback ( int                 status, 
		      void              * userarg,
		      cdevRequestObject & req,
		      cdevData          & data,
		      int                 partial)
  {
    if(function_!=NULL)
    	{
	incomplete_ = partial;
	(*function_)(status, userarg, req, data);
	incomplete_ = 0;
  	}
  }

  // *********************************************************************
  // * The isTransactionDone method allows the caller to discover if the
  // * transaction that executed the callback method is finished or
  // * ongoing.
  // *********************************************************************
  static int isTransactionDone ( void ) { return !incomplete_; }

protected:
  // data area
  cdevCallbackFunction function_;
  void *userarg_;

private:
  // Free List for all cdevCallback
  // Reason: cdevCallback is a very small object (8 byte). Using free list
  //         can speed up a program by an order of magnitude over the
  //         default malloc-based memory allocation primitives. It can also
  //         be less wasteful of memory, eliminating malloc's overheade of 
  //         four to eight bytes per allocation
  static cdevCallback *newlist;
  union
  {
    cdevCallback *freePtr;
    char *rep;
  };
  
  // *********************************************************************
  // * The incomplete_ flag is used to indicate that the transaction that
  // * has called this callback method is or is not finished.
  // * 
  // * The incomplete_ flag may have the following values...
  // *	0 - The transaction is finished
  // *	1 - The transaction is ongoing and more callbacks may be 
  // *	    expected.
  // *********************************************************************
  static int incomplete_;
};
#endif
