Click here to Skip to main content
15,893,564 members
Articles / Programming Languages / Visual Basic

Timers & Timings

Rate me:
Please Sign up or sign in to vote.
2.77/5 (7 votes)
7 Apr 20052 min read 63.5K   4.6K   24  
Produce timed event flags, functions, threads & timings therof.
// ====================================================================	//
//			    T I M _ S R C . C P P			//
// --------------------------------------------------------------------	//
// Task		: Subroutines to provide timers that set flags or call	//
//		  call-back routines on expiry (i.e. on interrupts)	//
// ====================================================================	//
#define _WIN32_WINNT 0x400
#include "TIM_src.h"

#include <process.h>
#include <sys/timeb.h>
#include <stdio.h>

//#define IFD1 if(dbgjpm&1)		// Errors
#define   IFD2 if(dbgjpm&2)		// Standard
//#define IFD4 if(dbgjpm&4)		// Details
#define	KeyTak(y) WaitForSingleObject(y,INFINITE)
#define	KeyRtn(y) SetEvent(y)

 static	void TIM_irpt_rtn(void*);

#define	thread_wait 200	// Wait this number of mSecs for thread to start or stop

#define	InitIfNot {if(!already_initialised)initialise();}

// ====================================================================	//
// Data global to the universe						//
// ====================================================================	//
#pragma data_seg(".TIMshare")
	long	TIMvz=sizeof(TIMver)-1;	// for VBusers
	char	TIMversion[] = TIMver;
	long	TIMdz=sizeof(TIMdat)-1;	// for VBusers
	char	TIMdate[]    = TIMdat;
#pragma data_seg()
extern "C" char* _stdcall TIM_getVersion(void) {return TIMversion;}
extern "C" char* _stdcall TIM_getDate	(void) {return TIMdate;}

	bool	beginCC = true;		// default to C/C++ user, it is global
static	long	dbgjpm;			// 0none,1thread,2user,3all or 4basic
extern "C" void TIM_set_debug (long x) {dbgjpm = x;}

// ====================================================================	//
// Data global to this module						//
// ====================================================================	//
 static	long	already_initialised = false,
		XitHeartBeatRqd = false;
 static	HANDLE	ti_keyh,		// Event handle for the above key
		tickerh;		// handle for function event on ticker thread
 static	tim_typ	     TIM[MX_NR_TIM];
 static	timF_typ    timF[MX_NR_TIM];

 static void initialise (void);

// ====================================================================	//
//			T I M _ c a n _ t m r				//
// ====================================================================	//
//			T I M _ m o d _ t m r				//
// ====================================================================	//
//			T I M _ g e t _ h a n d l e			//
// ====================================================================	//
//			T I M _ m a k e _ t m r				//
// ====================================================================	//
//			T I M _ m a k e _ t m r F			//
// ====================================================================	//
//			T I M _ m a k e _ t m r T			//
// ====================================================================	//
// static		i n i t i a l i s e				//
// ====================================================================	//
//			T I M _ r e s e t				//
// ====================================================================	//
//			T I M _ s t d _ f n p				//
// ====================================================================	//
//			T I M _ s p i n _ t h r e a d	    		//
// ====================================================================	//
//			T I M _ k i l l _ t h r e a d			//
// ====================================================================	//
// static		T I M _ i r p t _ c b				//
// ====================================================================	//
// static		T I M _ i r p t _ r t n				//
// ====================================================================	//
//			T I M _ m S					//
// ====================================================================	//
//			T I M _ m S q c t r				//
// ====================================================================	//
//			T I M _ i c t r					//
// ====================================================================	//
//			T I M _ q c t r					//
// ====================================================================	//
//			T I M _ i n i t V B				//
// ====================================================================	//
//			T I M _ e r r t x t				//
// ====================================================================	//

// ====================================================================	//
//				T I M _ c a n _ t m r			//
// --------------------------------------------------------------------	//
// Purpose		: Cancels a timer				//
// --------------------------------------------------------------------	//
// Implementation	: Sets the counter for the timer to -1 to	//
//			  indicate that the timer is not in use.	//
// --------------------------------------------------------------------	//
// Input parameters	: t_id	    - identification number for timer	//
// Output parameters	: None						//
// Return value		: _SUCCESS, _NO_KNOWN_TIMER			//
// ====================================================================	//
extern "C" long _stdcall TIM_can_tmr (long t_id)
{
	long timer_id = t_id - 1;

    InitIfNot;

    if (0 <= timer_id && timer_id < MX_NR_TIM)	// timer exist?
    {						// maybe
	if (TIM[timer_id].count >= 0)		// timer exist?
	{					// yes
//	    ===================================================	//
//	    Set the timer counter to -1.			//
//	    This effectively cancels the timer.			//
//	    ===================================================	//
	    InterlockedExchange(&TIM[timer_id].count,-1);// declare the timer free

	    if (TIM[timer_id].handle != NULL)
	    {
		CloseHandle(TIM[timer_id].handle);
		TIM[timer_id].handle = NULL;
	    }

	    return TIM_SUCCESS;
	}
    }

    return TIM_NO_KNOWN_TIMER;
}

// ====================================================================	//
//				T I M _ m o d _ t m r			//
// --------------------------------------------------------------------	//
// Purpose		: Sets a timer about to expire or modifies it	//
// --------------------------------------------------------------------	//
// Implementation	: Adjusts the counter for the timer so that	//
//			  the timer may expire at a different time.	//
// --------------------------------------------------------------------	//
// Input parameters	: t_id	    - identification number for timer	//
//			: time	    _ the new time (in mSecs)		//
// Output parameters	: None						//
// Return value		: _SUCCESS, _NO_KNOWN_TIMER			//
// ====================================================================	//
extern "C" long _stdcall TIM_mod_tmr (long t_id, long time)
{
	long timer_id = t_id - 1;

    InitIfNot;

    if (0 <= timer_id && timer_id < MX_NR_TIM)	// timer exists?
    {						// maybe
	if (TIM[timer_id].count >= 0)		// timer exists?
	{					// yes
//	    ===================================================	//
//	    Adjust a timer counter.				//
//	    This may change the expiration of the timer.	//
//	    N.B. this does not affect the repeating interval	//
//	    ===================================================	//
	    if (TIM[timer_id].count <= 1) return TIM_SUCCESS;

	    long t = time; if(t<=0) t = 1;

	    InterlockedExchange(&TIM[timer_id].count,t);// new time to expiration

	    return TIM_SUCCESS;
	}
    }

    return TIM_NO_KNOWN_TIMER;
}


// ====================================================================	//
//				T I M _ g e t _ h a n d l e		//
// --------------------------------------------------------------------	//
// Purpose		: return a HANDLE given a timer id		//
// --------------------------------------------------------------------	//
// Input parameters	: t_id - identification number for timer	//
// Return value		: timer HANDLE, NULL				//
// ====================================================================	//
extern "C" HANDLE _stdcall TIM_get_handle (long t_id)
{
	long timer_id = t_id - 1;

    InitIfNot;

    if (0 <= timer_id && timer_id < MX_NR_TIM)	// timer exists?
    {						// its possible
	return TIM[timer_id].handle;
    }

    return NULL;
}

// ====================================================================	//
//				T I M _ m a k e _ t m r			//
// --------------------------------------------------------------------	//
// Purpose		: Starts a timer, specifying a flag to be set	//
//			  when the timer expires.			//
// --------------------------------------------------------------------	//
// Implementation	: Finds a free slot & initialises timer details.//
//			  Next time the interrupt occurs the timer	//
//			  counter will automatically be decremented.	//
// --------------------------------------------------------------------	//
// Input parameters	: time	  - time in units of 1/18ths of second.	//
//			  timer_id- ptr to identification number for	//
//				    timer				//
//			  flag	  - pointer to flag name string to	//
//				    declare when timer expires.		//
//			  rpt	  - repeat (true/false)			//
// Output parameters	: timer_id					//
// Return value		: _SUCCESS, _NO_TIMERS_LEFT			//
// ====================================================================	//
extern "C" long _stdcall TIM_make_tmr (long time, long*timer_id, char*flag, bool rpt)
{
    InitIfNot;

//  ===========================================================	//
//  Finds the first free slot & sets up the time,		//
//  & flag in the timers slot.					//
//  In finding the slot try to avoid free slots with handles	//
//  this gives time after timer expiry to check the flag state	//
//  ===========================================================	//
    KeyTak(ti_keyh);
    long j=MX_NR_TIM; for(long i=0; i<MX_NR_TIM; i++)
    {
	if (TIM[i].count == -1)			// timer slot unused?
	{   if (j == MX_NR_TIM) j = i;		// yes, 1st possible slot to use
	    if (TIM[i].handle == NULL) break;	// not last used for a flag slot
	}
    }
    if (i == MX_NR_TIM) i = j;			// entirely free slot?, no

    if (i < MX_NR_TIM)				// got a free slot?
    {						// yes
	if (TIM[i].handle != NULL && strcmp(TIM[i].flagna,flag) != 0)
	{					// handle exists but flag name is different
	    CloseHandle(TIM[i].handle); TIM[i].handle = NULL;
	}
	if (TIM[i].handle == NULL)
	{					// need to create handle & record flag name
	    if (strcmp("",flag)==0) TIM[i].handle=CreateEvent(NULL,false,false,NULL);
	    else		    TIM[i].handle=CreateEvent(NULL,false,false,flag);
	    if (strlen(flag)<sizeof(TIM[i].flagna))    strcpy(TIM[i].flagna,flag);
	    else	    strncpy(TIM[i].flagna,flag,sizeof(TIM[i].flagna)-1);

	    IFD2 printf("\nflagHandle TIM[%d].handle %d",i,TIM[i].handle);
	}
	TIM[i].fnp	 =			// function pointer
	TIM[i].thp	 = NULL;		// thread pointer
	long t = time; if(t<=0) t = 1;
	if(rpt) TIM[i].rptcnt =  t;
	else    TIM[i].rptcnt = -1;
	InterlockedExchange(&TIM[i].count,t);	// time to expiration

//	=======================================================	//
//	Give the caller a handle on the timer, so that he	//
//	can cancel it if required.				//
//	=======================================================	//
	*timer_id = i+1;

	KeyRtn(ti_keyh);
	return TIM_SUCCESS;
    }
    KeyRtn(ti_keyh);

//  ===========================================================	//
//  If we get to this point then there are no free slots.	//
//  ===========================================================	//
    return TIM_NO_TIMERS_LEFT;
}

// ====================================================================	//
//				T I M _ m a k e _ t m r F		//
// --------------------------------------------------------------------	//
// Purpose		: Starts a timer, specifying a function to be	//
//			  run when the timer expires.			//
// --------------------------------------------------------------------	//
// Implementation	: Finds a free slot & initialises timer details.//
//			  Next time the interrupt occurs the timer	//
//			  counter will automatically be decremented.	//
// --------------------------------------------------------------------	//
// Input parameters	: time	  - time in units of 1/18ths second.	//
//			  timer_id- ptr to identification no. for timer	//
//			  fnp	  - pointer to function to be run when	//
//				    timer expires.			//
//			  prm	  - pointer to function parameters	//
//			  rpt	  - repeat (true/false)			//
// Output parameters	: timer_id					//
// Return value		: _SUCCESS, _NO_TIMERS_LEFT			//
// ====================================================================	//
extern "C" long _stdcall TIM_make_tmrF (long time, long*timer_id, void(*fnp)(void*), void*prm, bool rpt)
{
    InitIfNot;

//  ===========================================================	//
//  Finds the first free slot & sets up the time,		//
//  function & parameter address in the timers slot.		//
//  In finding the slot try to avoid free slots with handles	//
//  this gives time after timer expiry to check the flag state	//
//  ===========================================================	//
    KeyTak(ti_keyh);
    long j = MX_NR_TIM;
    for(long i=0; i<MX_NR_TIM; i++)
    {
	if (TIM[i].count == -1)			// timer slot unused?
	{   if (j == MX_NR_TIM) j = i;		// yes, 1st possible slot to use
	    if (TIM[i].handle == NULL) break;	// not last used for a flag slot
	}
    }
    if (i == MX_NR_TIM) i = j;			// entirely free slot?, no

    if (i < MX_NR_TIM)				// got a free slot?
    {						// yes
	if (TIM[i].handle != NULL) { CloseHandle(TIM[i].handle); TIM[i].handle= NULL; }
	TIM[i].fnp	 = fnp;			// function pointer
	TIM[i].thp	 = NULL;		// thread pointer
	TIM[i].prm	 = prm;			// parameter
	long t = time; if(t<=0) t = 1;
	if(rpt) TIM[i].rptcnt =  t;
	else    TIM[i].rptcnt = -1;
	InterlockedExchange(&TIM[i].count,t);	// time to expiration

//	=======================================================	//
//	Give the caller a handle on the timer, so that he	//
//	can cancel it if required.				//
//	=======================================================	//
	*timer_id = i+1;

	KeyRtn(ti_keyh);
	return TIM_SUCCESS;
    }
    KeyRtn(ti_keyh);

//  ===========================================================	//
//  If we get to this point then there are no free slots.	//
//  ===========================================================	//
    return TIM_NO_TIMERS_LEFT;
}

// ====================================================================	//
//				T I M _ m a k e _ t m r T		//
// --------------------------------------------------------------------	//
// Purpose		: Starts a timer, specifying a thread to be	//
//			  spun off when the timer expires.		//
// --------------------------------------------------------------------	//
// Implementation	: Finds a free slot & initialises timer details.//
//			  Next time the interrupt occurs the timer	//
//			  counter will automatically be decremented.	//
// --------------------------------------------------------------------	//
// Input parameters	: time	  - time in units of 1/18ths second.	//
//			  timer_id- ptr to identification no. for timer	//
//			  thp	  - pointer to thread code to be spun	//
//				    off when timer expires.		//
//			  prm	  - pointer to thread parameters	//
//			  rpt	  - repeat (true/false)			//
// Output parameters	: timer_id					//
// Return value		: _SUCCESS, _NO_TIMERS_LEFT			//
// ====================================================================	//
extern "C" long _stdcall TIM_make_tmrT (long time, long*timer_id, void(*thp)(void*), void*prm, bool rpt)
{
    InitIfNot;

//  ===========================================================	//
//  Finds the first free slot & sets up the time,		//
//  thread & parameter address in the timers slot.		//
//  In finding the slot try to avoid free slots with handles	//
//  this gives time after timer expiry to check the flag state	//
//  ===========================================================	//
    KeyTak(ti_keyh);
    long j = MX_NR_TIM;
    for(long i=0; i<MX_NR_TIM; i++)
    {
	if (TIM[i].count == -1)			// timer slot unused?
	{   if (j == MX_NR_TIM) j = i;		// yes, 1st possible slot to use
	    if (TIM[i].handle == NULL) break;	// not last used for a flag slot
	}
    }
    if (i == MX_NR_TIM) i = j;			// entirely free slot?, no

    if (i < MX_NR_TIM)				// got a free slot?
    {						// yes
	if (TIM[i].handle != NULL) { CloseHandle(TIM[i].handle); TIM[i].handle= NULL; }
	TIM[i].fnp	 = NULL;		// function pointer
	TIM[i].thp	 = thp;			// thread pointer
	TIM[i].prm	 = prm;			// parameter
	long t = time; if(t<=0) t = 1;
	if(rpt) TIM[i].rptcnt =  t;
	else    TIM[i].rptcnt = -1;
	InterlockedExchange(&TIM[i].count,t);	// time to expiration
	
//	=======================================================	//
//	Give the caller a handle on the timer, so that he	//
//	can cancel it if required.				//
//	=======================================================	//
	*timer_id = i+1;

	KeyRtn(ti_keyh);
	return TIM_SUCCESS;
    }
    KeyRtn(ti_keyh);

//  ===========================================================	//
//  If we get to this point then there are no free slots.	//
//  ===========================================================	//
    return TIM_NO_TIMERS_LEFT;
}

// ====================================================================	//
//				i n i t i a l i s e			//
// --------------------------------------------------------------------	//
// Purpose		: Performs initialisation functions		//
// --------------------------------------------------------------------	//
// Implementation	: Performs the following functions:		//
//			  1. Initialises each timer to an unused value.	//
//			  2. Spins off the ticker thread		//
// ====================================================================	//
static void initialise (void)
{
//  ===========================================================	//
//  Initialise the library once.				//
//  ===========================================================	//
    if (already_initialised) return;

    if (dbgjpmval) dbgjpm = dbgjpmval;

    already_initialised = true;
    IFD2 printf("\nTIMz %d",sizeof(TIM));

//  ===========================================================	//
//  Initialise each counter to unused(-1).			//
//  ===========================================================	//
    memset( TIM,0,sizeof( TIM));
    memset(timF,0,sizeof(timF));
    for(long i=0; i<MX_NR_TIM; i++) TIM[i].count = -1;

    ti_keyh = CreateEvent(NULL,false,true,NULL);

//  ===========================================================	//
//  Spin off the ticker thread					//
//  ===========================================================	//
    _beginthread(&TIM_irpt_rtn,0,0);
}


// ====================================================================	//
//				T I M _ s t d _ f n p			//
// --------------------------------------------------------------------	//
// Prevent the default _cdecl type call by forcing a _stdcall		//
// ====================================================================	//
extern void TIM_std_fnp (void (*fnp)(void*), void *prm)
{
	long (_stdcall*fn)(void*);

    fn = (long(_stdcall*)(void*))fnp;

    (*fn)(prm);				// (*fnp)(prm);
}

// ====================================================================	//
//				T I M _ r e s e t			//
// --------------------------------------------------------------------	//
// Reset timers, cleanup & reset markers & flags, exit the two threads	//
// ====================================================================	//
extern "C" void _stdcall TIM_reset (void)
{
	long i;

//  ===========================================================	//
//  Cancel repeaters, expire the unexpired, return handles	//
//  ===========================================================	//
    for(i=0; i<MX_NR_TIM; i++) InterlockedExchange(&TIM[i].rptcnt,	     -1);
    for(i=0; i<MX_NR_TIM; i++) InterlockedExchange(&TIM[i].count ,TIM[i].rptcnt);
    for(i=0; i<MX_NR_TIM; i++)
	    if (TIM[i].handle) { CloseHandle(TIM[i].handle); TIM[i].handle = NULL; }

//  ===========================================================	//
//  Shut down the ticker threads				//
//  ===========================================================	//
    if (already_initialised)
    {
	XitHeartBeatRqd = true;

	SetEvent(tickerh);	    // release the ticker thread

//	=======================================================	//
//	Await ticker-ticker thread exit or dt elapse		//
//	=======================================================	//
	i = 0;
	while(i < thread_wait)
	{
	    Sleep(100); i++;
	    if (!XitHeartBeatRqd) break;
	}

	CloseHandle(ti_keyh);

	XitHeartBeatRqd = already_initialised = false;
    }
}


// ====================================================================	//
//				T I M _ s p i n _ t h r e a d		//
// --------------------------------------------------------------------	//
// Spin off a thread for a user, since BOSDLL does lots of this		//
// N.B	The thread entry point must be a _stdcall entry point		//
//	The user must Close the returned handle				//
// ====================================================================	//
extern "C" uint _stdcall TIM_spin_thread (void(_stdcall*thp)(void*), void*prm)
{
	uint tha;

    return _beginthreadex(NULL,0,(uint(_stdcall*)(void*))(thp),prm,0,&tha);
}


// ====================================================================	//
//				T I M _ k i l l _ t h r e a d		//
// --------------------------------------------------------------------	//
// Kill a thread for a user, since BOSDLL does lots of this		//
// ====================================================================	//
extern "C" void _stdcall TIM_kill_thread (uint han) { _endthreadex(han); }

// ====================================================================	//
//				T I M _ i r p t _ c b			//
// --------------------------------------------------------------------	//
// Purpose: Interrupt service routine(tickerticker thread)		//
// --------------------------------------------------------------------	//
// Implementation	: Scans each slot in the timer array looking	//
//			  for a timer to decrement.			//
// --------------------------------------------------------------------	//
//			  If timer is expiring (counter = 1) then set	//
//			  the flag or call the user's function or	//
//			  spin off the users's thread, as appropriate.	//
// ====================================================================	//
static __int64	TmilliS = 0, Tquadctr = 0;
static long	TIM_irpt_cbFIRST = true, begin_mS;
static void CALLBACK TIM_irpt_cb (UINT a, UINT b, DWORD c, DWORD d, DWORD e)
{
	tim_typ	*tp = TIM;			// pointer is 1/3 shorter & faster

    if (TIM_irpt_cbFIRST)
    {	TIM_irpt_cbFIRST = false;
	if (!SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_TIME_CRITICAL))
				printf("\n StThPr failed %d",GetLastError());
	begin_mS = true;
    }

    if (begin_mS)
    {
	_timeb stime; _ftime(&stime);

	if (TmilliS !=(stime.millitm))		// mS just moved on?
	{					// yes, this is most accurate
	    TmilliS  = stime.time;		// secs since 1/1/70
	    TmilliS *=(1000);			//
	    TmilliS +=(stime.millitm);		// msecs since 1st Jan 1970
	    begin_mS  = false;
	}
    }
    else TmilliS++;

    Tquadctr++;					// add, adc

//  ===========================================================	//
//  Run through each slot in the timer array checking for a	//
//  used timer slot. If we find one then decrement the timer	//
//  counter. If counter is 1 then the timer is about to expire,	//
//  so signal the timer expired to the host application & set	//
//  the slot to be unused again.				//
//  ===========================================================	//
    for(long i=0; i<MX_NR_TIM; i++,tp++)
	if (tp->count > 0)
	{
//	    ===================================================	//
//	    Trap when the signal is expiring.			//
//	    ===================================================	//
	    if (InterlockedDecrement(&tp->count) == 0)
	    {
//		===============================================	//
//		Signal to the user(appropriately, - depending	//
//		on how the timer was setup).			//
//		===============================================	//
		if (tp->handle != NULL)
		{
//		    ===========================================	//
//		    Set the flag				//
//		    ===========================================	//
		    IFD2 printf("\nSetEvent, handle %d",tp->handle);
		    SetEvent(tp->handle);
		}

		if (tp->fnp != NULL)
		{
//		    ===========================================	//
//		    Call the user's function on ticker thread	//
//		    ===========================================	//
		    if (timF[i].fnp == NULL)	// Matching slot available?
		    {   timF[i].fnp = tp->fnp;	// yes
		        timF[i].prm = tp->prm;
		    }
		    else			// no, use any empty slot
		    {	for(long j=0; j<MX_NR_TIM; j++)
			    if (timF[j].fnp == NULL)
			    {   timF[j].fnp = tp->fnp;
				timF[j].prm = tp->prm;
				break;
			    }
		    }
		    SetEvent(tickerh);		// release the ticker thread
		}

		if (tp->thp != NULL)
		{
//		    ===========================================	//
//		    Spin off the user's thread.			//
//		    ===========================================	//
		    if (beginCC) {_beginthread(				    tp->thp ,0,tp->prm);}
		    else
		    {	uint th, tha;
			th = _beginthreadex(NULL,0,(uint(_stdcall*)(void*))(tp->thp),  tp->prm,0,&tha);
			if (th > 0) CloseHandle((void*)th);
		    }
		}

//		===============================================	//
//		Signal that the slot is now free or repeat	//
//		===============================================	//
		InterlockedExchange(&tp->count,tp->rptcnt); 
	    }
	}
}

// ====================================================================	//
//				T I M _ i r p t _ r t n			//
// --------------------------------------------------------------------	//
// Purpose: Interrupt service routine (ticker thread).			//
//	    start the ticker-ticker thread.				//
//	    wait for functions to execute or exit request.		//
// ====================================================================	//
static void TIM_irpt_rtn (void *p)
{
	MMRESULT MMRsts;

    tickerh = CreateEvent(NULL,false,false,NULL); IFD2 printf("\nflagHandle tickerh %d",tickerh);

    _timeb stime; _ftime(&stime); TmilliS =(stime.millitm);

    MMRsts = timeSetEvent(1,0,&TIM_irpt_cb,0,TIME_PERIODIC);

    while (!XitHeartBeatRqd)
    {
	for(long i=0; i<MX_NR_TIM; i++)
	{
	    if (timF[i].fnp != NULL)
	    {
		if (beginCC)   (*timF[i].fnp)(timF[i].prm);
		else TIM_std_fnp(timF[i].fnp, timF[i].prm);

		timF[i].fnp = NULL;	// fuction called
	    }
	}

	WaitForSingleObject(tickerh,INFINITE);
    }

    timeKillEvent(MMRsts);

    CloseHandle(tickerh);

    TIM_irpt_cbFIRST = true;

    XitHeartBeatRqd = false;
}

// ====================================================================	//
//				T I M _ m S				//
//				T I M _ m S q c t r			//
//				T I M _ i c t r				//
//				T I M _ q c t r				//
// --------------------------------------------------------------------	//
// return an accurate millisecond value of the current second.		//
// return quad milliseconds since 1/1/70.				//
// return long milliseconds since init.					//
// return quad milliseconds since init.					//
// ====================================================================	//
extern "C"   long  _stdcall TIM_mS     (void){InitIfNot;return(long)(TmilliS%1000);	  }
extern "C" __int64 _stdcall TIM_mSqctr (void){InitIfNot;return	     TmilliS;		  }
extern "C"   long  _stdcall TIM_ictr   (void){InitIfNot;return(long)(Tquadctr&0x7fffffff);}
extern "C" __int64 _stdcall TIM_qctr   (void){InitIfNot;return	     Tquadctr;		  }


// ====================================================================	//
//				T I M _ i n i t V B			//
// --------------------------------------------------------------------	//
// ====================================================================	//
extern "C" void _stdcall TIM_initVB (void) { beginCC = false; }


// ====================================================================	//
//			T I M _ e r r t x t				//
// --------------------------------------------------------------------	//
// ====================================================================	//
extern "C" char* _stdcall TIM_errtxt (long stt)
{
#define etxxx "No such error code"	//   x
#define etP01 "TIM_SUCCESS"		//   1
#define etM02 "TIM_FAILURE"		//  -2
#define etM04 "TIM_NO_KNOWN_TIMER"	//  -4
#define etM06 "TIM_NO_TIMERS_LEFT"	//  -6
#define etM08 "TIM_TIMER_EXPIRED"	//  -8

 static	err_typ	et[] ={	sizeof(etxxx)-1,etxxx,
			sizeof(etP01)-1,etP01,
			sizeof(etM02)-1,etM02,
			sizeof(etM04)-1,etM04,
			sizeof(etM06)-1,etM06,
			sizeof(etM08)-1,etM08	};

    if (stt ==   1) return et[ 1].err;
    if (stt ==  -2) return et[ 2].err;
    if (stt ==  -4) return et[ 3].err;
    if (stt ==  -6) return et[ 4].err;
    if (stt ==  -8) return et[ 5].err;

    return et[0].err;
}


By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
United Kingdom United Kingdom
BSc (St.Andrews(1963-67))
MSCE
Systems Programmer 39+yrs
Married to first wife 35yrs & counting, four grown-up children
Religious opinions similar to MelG's
It is not the gnosis, but the praxis must be the fruit. (Aristotle)

Comments and Discussions