//The NODE and the WHEEL of NODES
//Written By Billy Stiltner COPYRIGHT 1996 Billy Stiltner
/*/
Copyright (C) 1995 Billy Stiltner
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation;
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
/*/
//#include<alloc.h>
//This is a very simple set of classes for a Node and List
///////////////////////////////////////////////////////////////////
unsigned long nexusconstructors;
unsigned long roticonstructors;
unsigned long nexusdestructors;
unsigned long rotidestructors;
class NEXUS;
typedef void (NEXUS::*pMF)();
//typedef class *pC;
class NEXUS
{
public:
//data members
NEXUS *next;
NEXUS *previous;
//member functions
NEXUS();
NEXUS *GET_NEXT();
NEXUS *operator ++();
NEXUS *operator --();
//NEXUS *operator +(int n);
//NEXUS *operator -(int n);
int IS_PRIMUS();
int IS_MAXIMUS();
int IS_INTERNEXUS();
int IS_UNUSNEXUS();
virtual ~NEXUS();
};
/////////////////////////////////////////////////////////////////// .
///////////////////////////////////////////////////////////////////////////
class ROTI : public NEXUS
{
public:
//data members
NEXUS *PRIMUS;
NEXUS *MAXIMUS;
NEXUS *PROXIMUS;
NEXUS *BUFF;
//member functions
ROTI();
void PUT_PRIMUS(NEXUS *p);
void PUT_MAXIMUS(NEXUS *p);
void PUT_BEFORE_PROXIMUS(NEXUS *p);
void PUT_AFTER_PROXIMUS(NEXUS *p);
void PUT_BEFORE_NEXUS(NEXUS *p,NEXUS *q);
void PUT_AFTER_NEXUS(NEXUS *p,NEXUS *q);
void XFER(NEXUS *n,ROTI *r);
void DELETE_NEXUS(NEXUS *p);
void FOR_EACH(pMF pFunc);
void EXTRACT_NEXUS(NEXUS *p);
~ROTI();
};
/////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
NEXUS::NEXUS()
{
//nexusconstructors++;
next=NULL;
previous=NULL;
}
///////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
int NEXUS::IS_PRIMUS()
{
if((previous==NULL)&&(next!=NULL))
return(1);else return(0);
}
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
int NEXUS::IS_MAXIMUS()
{
if((next==NULL)&&(previous!=NULL))
return(1);else return(0);
}
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
int NEXUS::IS_INTERNEXUS()
{
if((previous!=NULL)&&(next!=NULL))
return(1);else return(0);
}
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
int NEXUS::IS_UNUSNEXUS()
{
if((previous==NULL)&&(next==NULL))
return(1);else return(0);
}
//////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
NEXUS *NEXUS::GET_NEXT()
{ // NEXUS *j;
//j=this->next;
return(next);
}
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
inline NEXUS *NEXUS::operator ++()
{ // NEXUS *j;
//j=this->next;
return(next);
}
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
inline NEXUS *NEXUS::operator --()
{
return(previous);
}
///////////////////////////////////////////////////////////////////////////
/*///////////////////////////////////////////////////////////////////////////
inline NEXUS *NEXUS::operator +(int n)
{
int c;
NEXUS *np;
np=this;
if(np!=NULL)
{
for(c=0;c<n;c++)
{
np=np->next;
if(np==NULL)break;
};
};
return(np);
};
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
inline NEXUS *NEXUS::operator -(int n)
{
int c;
NEXUS *np;
np=this;
if(np!=NULL)
{
for(c=0;c<n;c++)
{
np=np->previous;
if(np==NULL)break;
};
};
return(np);
};
//*/////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
NEXUS::~NEXUS()
{
//nexusdestructors++;
//cout<<"IN NEXUS Destructor"<<"\n";
}
///////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
ROTI::ROTI():NEXUS()
{
//roticonstructors++;
PRIMUS=NULL;
MAXIMUS=NULL;
PROXIMUS=NULL;
BUFF=NULL;
}
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////
void ROTI::PUT_PRIMUS(NEXUS *p)
{
p->next = PRIMUS;
p->previous = NULL;
if(!p->IS_UNUSNEXUS()){
p->next->previous = p;
}else{
MAXIMUS = p;
};
PRIMUS = p;
}
////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////
void ROTI::PUT_MAXIMUS(NEXUS *p)
{
p->previous = MAXIMUS;
p->next = NULL;
if(!p->IS_UNUSNEXUS()){
p->previous->next = p;
}else{
PRIMUS = p;
};
MAXIMUS = p;
}
///////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
void ROTI::PUT_BEFORE_PROXIMUS(NEXUS *p)
{
if(PROXIMUS!=NULL)PUT_BEFORE_NEXUS(p,PROXIMUS);
}
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
void ROTI::PUT_AFTER_PROXIMUS(NEXUS *p)
{
if(PROXIMUS!=NULL)PUT_AFTER_NEXUS(p,PROXIMUS);
}
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
void ROTI::PUT_BEFORE_NEXUS(NEXUS *p,NEXUS *q)
{
if(q!=NULL)
{
if((q->IS_INTERNEXUS())||(q->IS_MAXIMUS()))
{
p->next=q;
p->previous=q->previous;
q->previous->next=p;
q->previous=p;
}else{
if(q->IS_PRIMUS())PUT_PRIMUS(p);
}
}
}
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
void ROTI::PUT_AFTER_NEXUS(NEXUS *p,NEXUS *q)
{
if(q!=NULL)
{
if((q->IS_INTERNEXUS())||(q->IS_PRIMUS()))
{
p->previous=q;
p->next=q->next;
q->next->previous=p;
q->next=p;
}else{
if(q->IS_MAXIMUS())PUT_MAXIMUS(p);
}
}
}
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
void ROTI::XFER(NEXUS *n,ROTI *r)
{
//-+EXTRACT_NEXUS(n);
r->PUT_MAXIMUS(n);
}
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
//REMOVES NEXUS FROM ROTI AND DELETES NEXUS
void ROTI::DELETE_NEXUS(NEXUS *p)
{
if((p->next!=NULL)&&(p->previous!=NULL)) //if p is between
{
p->previous->next=p->next;//adjust previous
p->next->previous=p->previous;//adjust next
if(PROXIMUS==p)PROXIMUS=p->next; //if p was PROXIMUS make next PROXIMUS
if(p!=NULL)delete p;//delete p
return;
}
if(p->next==NULL)
{
MAXIMUS=p->previous;
p->previous->next=NULL;
if(PROXIMUS==p)
{
if(p->previous==NULL){
PROXIMUS=NULL;}else{PROXIMUS=p->previous;}
}
if(p!=NULL)delete p;
return;
}
if(p->previous==NULL)
{
PRIMUS=p->next;
p->next->previous=NULL;
if(PROXIMUS==NULL)
{
if(p->next==NULL){
PROXIMUS=NULL;}else{PROXIMUS=p->next;}
}
if(p!=NULL)delete p;
return;
}
//if(p->pPORTAL!=NULL)delete p->pPORTAL;
}
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//EXTRACTS A NEXUS FROM LIST WITHOUT DELETING
void ROTI::EXTRACT_NEXUS(NEXUS *p)
{
if(p->previous==NULL){
PRIMUS=p->next;
p->next->previous=NULL;
}
if(p->next==NULL){
MAXIMUS=p->previous;
p->previous->next=NULL;
}
if((p->next!=NULL)&&(p->previous!=NULL)){
p->previous->next=p->next;
p->next->previous=p->previous;
}
}
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
void ROTI::FOR_EACH(pMF pFunc)
{
if((PRIMUS!=NULL)&&(MAXIMUS!=NULL))//if not emptty
for(NEXUS *current=PRIMUS; //start on PRIMUS
current!=NULL; //Stop after Maximus
current=++(*current)) //increment current
(current->*pFunc)(); //call current function
}
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
ROTI::~ROTI()
{
//rotidestructors++;
//cout<<"\n"<<"IN ROTI Destructor"<<"\n";
/*/
//roti can only be a base class and nexus can only be a base class
if(PRIMUS!=NULL)
{
NEXUS *NEXT;
NEXUS* current = PRIMUS;
for(;;)
{
NEXT=current->next;
if(current!=NULL)delete current;
if(current == NULL)break;
current=NEXT;
};
};
/*/
}
///////////////////////////////////////////////////////////////////
I know Miller doesn't use c++,
here is the above code used in more code
I would like to know how do do this in c
about the only thing I used c++ for is
object oriented programming so that data of classes could have functions associated with them, the inheritance model i used might be a bit hard to follow then there is the problem of using borland style macros which simplifies defining member functions , it was something dreamed up in the development of borland's visual studio so that windows programs could be visually written, kind of how puredata is a visusual programming environment except the 2 approaches are very different.
What are the differences?
/*/
Impulse.h See below for description.
Copyright (C) 1995 Billy Stiltner
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License,
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
/*/
//The classes herein can be used together to provide a basis for a
//response mechanism.
//
//The impulse is a node based object.
//
//The Reactor is a list based object.
//
//The Coordinator is used as a wrapper in that it maintains two Reactors,
//an ACTIVE Reactor, and an INACTIVE Reactor so that responses can be
//loaded and unloaded hence DYNAMIC RESPONSE LOADING (DRL).
//
//The Coordinator can make reflexes and responses.
//
//The impulse is a dual natured class, it can be a reflex or a response.
//
//The reflex is created with a pointer to a variable uint *Var, a uint
//Condition, and a pMF pFunc. HOW IT WORKS: reflex's VAR is set to Var,
//CONDITION is set to Condition, and RESPOND is set to pFunc, if *VAR,
//wherever it may be, is equal to CONDITION, whatever it may be, RESPOND,
//whatever it does, is CALLED.
//
//The response is created with a uint Message and a pMF pFunc. HOW IT WORKS:
//response's CONDITION is set to Message and RESPOND is set to pFunc, *VAR
//must be provided at response time if *VAR = CONDITION then RESPOND is CALLED.
//
//The Reactor maintains reflexes and responses, it can only hold one
//type of impulse, but can hold as many as there is memory to put them.
//
//
//include files//////////////////////////////////////////////////////////////
//#include<objects.h>
//#include<nexus.h>
//#include"c:\program\svga\objects.h"
/////////////////////////////////////////////////////////////////////////////
//defines////////////////////////////////////////////////////////////////////
#define TORPID 0L
#define AWAKE 1L
/////////////////////////////////////////////////////////////////////////////
//variables//////////////////////////////////////////////////////////////////
unsigned long impulseconstructors;
unsigned long coordinatorconstructors;
unsigned long impulsedestructors;
unsigned long coordinatordestructors;
/////////////////////////////////////////////////////////////////////////////
//classes////////////////////////////////////////////////////////////////////
class impulse: public NEXUS
{
public://access modifier
//data members///////////////////////////////////////////////////////////////
pMF RESPOND; //*function to call if message = CONDITION
unsigned int *VAR; //unsigned int pointer to a variable to check
unsigned int CONDITION; //value to compare condition with
//member functions///////////////////////////////////////////////////////////
//impulse(); //default constructor sets all to NULL
impulse(impulse *i); //constructer using impulse *
impulse(unsigned int Message, //consructor to make a response
pMF pFunc);
impulse(unsigned int *Var, //consructor to make a reflex
unsigned int Condition,
pMF pFunc);
void makeresponse(unsigned int Message,//function to make a response
pMF pFunc);
void makereflex(unsigned int *Var, //function to make a reflex
unsigned int Condition,
pMF pFunc);
void respond(NEXUS *pN); //function to call when responding
~impulse(); //destructor
};
/////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
class Reactor : public ROTI
{
public:
//data members
//member functions
Reactor();
//void DefineResponse(impulse *im);
impulse *DefineReflex(unsigned int *Var,
unsigned int Condition,
pMF pFunc);
impulse *DefineResponse(unsigned int Message,
pMF pFunc);
virtual void Reflex(NEXUS *pN);
virtual void Respond(MSG *Msg,NEXUS *pN);
~Reactor();
};
////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
class Coordinator
{
public:
Reactor *ACTIVE;
Reactor *INACTIVE;
Coordinator();
impulse *MakeReflex(unsigned int *Var,
unsigned int Condition,
pMF pFunc);
impulse *MakeResponse(unsigned int Message,
pMF pFunc);
void Activate(impulse *i);
void Deactivate(impulse *i);
virtual void Reflex(NEXUS *pN);
virtual void Respond(MSG *Msg,NEXUS *pN);
~Coordinator();
};
////////////////////////////////////////////////////////////////////
//SUGGESTION:
//make a member of class x
// x::MakeResponseTable()
// {
// DEFINE_RESPONSE(x,MessageId,NameOfFunctionCalledInResponseToMessageId);
// etc...
// }
////////////////////////////////////////////////////////////////////////
#define DEFINE_RESPONSE(classname,\
imessage,\
ifunctionname)\
DefineResponse(imessage,\
(pMF)&classname::ifunctionname);
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
#define DEFINE_REFLEX(classname,\
nvar,\
ncondittion,\
nfunctionname)\
DefineReflex(nvar,\
ncondittion,\
(pMF)&classname::nfunctionname);
//////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
#define MAKE_RESPONSE(classname,\
imessage,\
ifunctionname)\
MakeResponse(imessage,\
(pMF)&classname::ifunctionname);
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
#define MAKE_REFLEX(classname,\
nvar,\
ncondittion,\
nfunctionname)\
MakeReflex(nvar,\
ncondittion,\
(pMF)&classname::nfunctionname);
//////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
impulse::impulse(unsigned int Message,pMF pFunc) : NEXUS()
{ // void (impulse::*pFunc)()):NEXUS()
impulseconstructors++;
CONDITION=Message;
RESPOND=pFunc;
}
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
impulse::impulse(impulse *i):NEXUS()
{
impulseconstructors++;
RESPOND=i->RESPOND;
VAR=i->VAR;
CONDITION=i->CONDITION;
}
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
//impulse::impulse():NEXUS()
//{
//impulseconstructors++;
//VAR=NULL;
//CONDITION=NULL;
//RESPOND=NULL;
//};
///////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
impulse::impulse(unsigned int *Var,
unsigned int Condition,
pMF pFunc):NEXUS()
{
impulseconstructors++;
VAR=Var;
CONDITION=Condition;
RESPOND=pFunc;
}
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
void impulse::makeresponse(unsigned int Message, pMF pFunc)
{
CONDITION=Message;
RESPOND=pFunc;
VAR=NULL;
}
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
void impulse::respond(NEXUS *pN)
{
(pN->*RESPOND)();//This works but all RESPOND functions must be NEXUS
//(this->*RESPOND)();
//RESPOND();
//return(RESPOND);
}
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
impulse::~impulse()
{
impulsedestructors++;
//cout<<"\n"<<"IN impulse Destructor"<<"\n";
}
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
void impulse::makereflex(unsigned int *Var,
unsigned int Condition,
pMF pFunc)
{
VAR=Var;
CONDITION=Condition;
RESPOND=pFunc;
}
///////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
Reactor::Reactor():ROTI()
{
coordinatorconstructors++;
}
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////
impulse * Reactor::DefineResponse(unsigned int Message,
pMF pFunc)
{
impulse* newimpulse = new impulse(Message,pFunc);
PUT_MAXIMUS(newimpulse);
return(newimpulse);
}
///////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////
impulse * Reactor::DefineReflex(unsigned int *Var,
unsigned int Condition,
pMF pFunc)
{
impulse* newnatural = new impulse(Var,Condition,pFunc);
PUT_MAXIMUS(newnatural);
return(newnatural);
}
///////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
void Reactor::Respond(MSG *Msg,NEXUS *pN)
{
if(PRIMUS!=NULL)
{
impulse* current = (impulse *)PRIMUS;
for(;;)
{
if(current->CONDITION==Msg->message){
current->respond(pN);
break;
}
if(current->next == NULL)break;
current=(impulse *)current->next;
}
}
}
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
void Reactor::Reflex(NEXUS *pN)
{
if(PRIMUS!=NULL)
{
impulse* current =(impulse *) PRIMUS;
for(;;)
{
if(current->CONDITION==*(current->VAR)){
current->respond(pN);
}
if(current->next == NULL)break;
current=(impulse *)current->next;
}
}
}
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
Reactor::~Reactor()
{
coordinatordestructors++;
if((PRIMUS!=NULL)&&(MAXIMUS!=NULL))//if not emptty
for(NEXUS *current=PRIMUS; //start on PRIMUS
current!=NULL; //Stop after Maximus
current=++(*current)) //increment current
delete current;
//cout<<"\n"<<"IN Reactor Destructor"<<"\n";
//NEXUS* NEXT;
//NEXUS* current = PRIMUS;//IDLE->PRIMUS;
//if(PRIMUS!=NULL)//IDLE->PRIMUS!=NULL)
//{
//for(;;)
// {
// NEXT=current->next;
// if(current!=NULL)delete current;
// if(current == NULL)break;
// current=NEXT;
// }
//}
}
///////////////////////////////////////////////////////////////////
Coordinator::Coordinator()
{
ACTIVE=new Reactor();
INACTIVE=new Reactor();
}
///////////////////////////////////////////////////////////////////
impulse * Coordinator::MakeResponse(unsigned int Message,
pMF pFunc)
{
impulse* newimpulse = ACTIVE->DefineResponse(Message,pFunc);
return(newimpulse);
}
///////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////
impulse * Coordinator::MakeReflex(unsigned int *Var,
unsigned int Condition,
pMF pFunc)
{
impulse *newreflex;
newreflex=ACTIVE->DefineReflex(Var,Condition,pFunc);
return(newreflex);
}
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
void Coordinator::Activate(impulse *i)
{
//this method of activation is slower than another type that would take
//up more memory so this type takes up less memory
//so this is the small slow version
//1 see if i is inactive
//2 see if i is already active
impulse *current;
//iterate through the inactive list
for(current=(impulse *)INACTIVE->PRIMUS;
current!=NULL;
current=(impulse *)current->next)
//see if i is in here
if(i==current)
{
//if so iterate through the active list
for(current=(impulse *)ACTIVE->PRIMUS;
current!=NULL;
current=(impulse *)current->next)
if(i==current)return;//get out if i is already in the active list
//if we made it here i aint already active
INACTIVE->EXTRACT_NEXUS(i);//if not active get i out of inactive list
ACTIVE->PUT_MAXIMUS(i);//and put i in active list
break;
}
}
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
void Coordinator::Deactivate(impulse *i)
{
//1 see if i is active
//2 see if i is already inactive
impulse *current;
for(current=(impulse *)ACTIVE->PRIMUS;
current!=NULL;
current=(impulse *)current->next)
if(i==current)
{
for(current=(impulse *)INACTIVE->PRIMUS;
current!=NULL;
current=(impulse *)current->next)if(i==current)return;
ACTIVE->EXTRACT_NEXUS(i);
INACTIVE->PUT_MAXIMUS(i);
break;
}
}
///////////////////////////////////////////////////////////////////////////
void Coordinator::Respond(MSG *Msg,NEXUS *pN)
{
ACTIVE->Respond(Msg,pN);
};
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
void Coordinator::Reflex(NEXUS *pN)
{
ACTIVE->Reflex(pN);
}
///////////////////////////////////////////////////////////////////////////
Coordinator::~Coordinator()
{
if(ACTIVE!=NULL)delete ACTIVE;
if(INACTIVE!=NULL)delete INACTIVE;
}