From 3f26c19b0b7a9fa73c58189788972ea43b72f014 Mon Sep 17 00:00:00 2001 From: Mike Buland Date: Mon, 25 Jun 2007 21:15:55 +0000 Subject: I think the plugger and programchain are all up to date to work with the new libbu++. The program chain may undergo heavy changes still, or be removed entirely, but we need it for congo and squirrelmud, so here it is for a while longer. The TafWriter isn't much closer, you still only get the groups in the output. --- src/linkmessage.cpp | 43 ++++++++++ src/linkmessage.h | 42 ++++++++++ src/old/linkmessage.cpp | 44 ----------- src/old/linkmessage.h | 39 ---------- src/old/plugger.cpp | 1 - src/old/plugger.h | 198 ----------------------------------------------- src/old/programchain.cpp | 96 ----------------------- src/old/programchain.h | 95 ----------------------- src/old/programlink.cpp | 54 ------------- src/old/programlink.h | 99 ------------------------ src/plugger.cpp | 1 + src/plugger.h | 196 ++++++++++++++++++++++++++++++++++++++++++++++ src/programchain.cpp | 97 +++++++++++++++++++++++ src/programchain.h | 98 +++++++++++++++++++++++ src/programlink.cpp | 56 ++++++++++++++ src/programlink.h | 100 ++++++++++++++++++++++++ src/tafwriter.cpp | 25 +++++- src/tafwriter.h | 10 ++- 18 files changed, 665 insertions(+), 629 deletions(-) create mode 100644 src/linkmessage.cpp create mode 100644 src/linkmessage.h delete mode 100644 src/old/linkmessage.cpp delete mode 100644 src/old/linkmessage.h delete mode 100644 src/old/plugger.cpp delete mode 100644 src/old/plugger.h delete mode 100644 src/old/programchain.cpp delete mode 100644 src/old/programchain.h delete mode 100644 src/old/programlink.cpp delete mode 100644 src/old/programlink.h create mode 100644 src/plugger.cpp create mode 100644 src/plugger.h create mode 100644 src/programchain.cpp create mode 100644 src/programchain.h create mode 100644 src/programlink.cpp create mode 100644 src/programlink.h diff --git a/src/linkmessage.cpp b/src/linkmessage.cpp new file mode 100644 index 0000000..abe113c --- /dev/null +++ b/src/linkmessage.cpp @@ -0,0 +1,43 @@ +#include "bu/linkmessage.h" + +Bu::LinkMessage::LinkMessage( int nNewMsg ) +{ + nMsg = nNewMsg; +} + +Bu::LinkMessage::~LinkMessage() +{ +} + +/* +void LinkMessage::setBroadcast( bool bOn ) +{ + bBroadcast = bOn; +} + +bool LinkMessage::isBroadcast() +{ + return bBroadcast; +} + + +void LinkMessage::setFromID( int id ) +{ + nFromLinkID = id; +} + +int LinkMessage::getFromID() +{ + return nFromLinkID; +} + +void LinkMessage::setToID( int id ) +{ + nTargetLinkID = id; +} + +int LinkMessage::getToID() +{ + return nTargetLinkID; +} +*/ diff --git a/src/linkmessage.h b/src/linkmessage.h new file mode 100644 index 0000000..64b8bc2 --- /dev/null +++ b/src/linkmessage.h @@ -0,0 +1,42 @@ +/**\file linkmessage.h + */ + +#ifndef LINKMESSAGE_H +#define LINKMESSAGE_H + +namespace Bu +{ + /** + * A message to be broadcast accross ProgramLinks in a ProgramChain. Generally + * one would make a subclass of this in order to transmit more useful + * information, but sometimes it isn't necesarry. + *@author Mike Buland + */ + class LinkMessage + { + public: + /** + * Construct a blank LinkMessage. + */ + LinkMessage() {}; + + /** + * Deconstruct a LinkMessage. + */ + virtual ~LinkMessage(); + + /** + * Create a LinkMessage object with a specific message assosiated with it + * to start with. + *@param nNewMsg The message to use in the Message object. + */ + LinkMessage( int nNewMsg ); + + /** + * The message contained in the Message object. + */ + int nMsg; + }; +} + +#endif diff --git a/src/old/linkmessage.cpp b/src/old/linkmessage.cpp deleted file mode 100644 index cf3df42..0000000 --- a/src/old/linkmessage.cpp +++ /dev/null @@ -1,44 +0,0 @@ -#include "linkmessage.h" -#include - -LinkMessage::LinkMessage( int nNewMsg ) -{ - nMsg = nNewMsg; -} - -LinkMessage::~LinkMessage() -{ -} - -/* -void LinkMessage::setBroadcast( bool bOn ) -{ - bBroadcast = bOn; -} - -bool LinkMessage::isBroadcast() -{ - return bBroadcast; -} - - -void LinkMessage::setFromID( int id ) -{ - nFromLinkID = id; -} - -int LinkMessage::getFromID() -{ - return nFromLinkID; -} - -void LinkMessage::setToID( int id ) -{ - nTargetLinkID = id; -} - -int LinkMessage::getToID() -{ - return nTargetLinkID; -} -*/ diff --git a/src/old/linkmessage.h b/src/old/linkmessage.h deleted file mode 100644 index 6cdfb2f..0000000 --- a/src/old/linkmessage.h +++ /dev/null @@ -1,39 +0,0 @@ -/**\file linkmessage.h - */ - -#ifndef LINKMESSAGE_H -#define LINKMESSAGE_H - -/** - * A message to be broadcast accross ProgramLinks in a ProgramChain. Generally - * one would make a subclass of this in order to transmit more useful - * information, but sometimes it isn't necesarry. - *@author Mike Buland - */ -class LinkMessage -{ -public: - /** - * Construct a blank LinkMessage. - */ - LinkMessage() {}; - - /** - * Deconstruct a LinkMessage. - */ - virtual ~LinkMessage(); - - /** - * Create a LinkMessage object with a specific message assosiated with it - * to start with. - *@param nNewMsg The message to use in the Message object. - */ - LinkMessage( int nNewMsg ); - - /** - * The message contained in the Message object. - */ - int nMsg; -}; - -#endif diff --git a/src/old/plugger.cpp b/src/old/plugger.cpp deleted file mode 100644 index f3bfa67..0000000 --- a/src/old/plugger.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "plugger.h" diff --git a/src/old/plugger.h b/src/old/plugger.h deleted file mode 100644 index d92f194..0000000 --- a/src/old/plugger.h +++ /dev/null @@ -1,198 +0,0 @@ -#ifndef PLUGGER_H -#define PLUGGER_H - - -#include "hashtable.h" -#include "list" -#include "hashfunctionstring.h" -#include "hashfunctionint.h" -#include "dlfcn.h" -#include "exceptions.h" - -typedef struct PluginInfo -{ - const char *sID; - const char *sAuthor; - unsigned short nVersion; - unsigned short nRevision; - void *(*createPlugin)(); - void (*destroyPlugin)( void * ); -} PluginInfo; - -typedef struct PluginReg -{ - bool bBuiltin; - void *dlHandle; - PluginInfo *pInfo; -} PluginReg; - -#define PluginInterface( classname, baseclass, name, ver, rev ) \ -extern "C" { \ - baseclass *create ##classname() \ - { \ - return new classname(); \ - } \ - void destroy ##classname( baseclass *pCls ) \ - { \ - delete pCls; \ - } \ - PluginInfo classname = { \ - #classname, name, ver, rev, \ - create ##classname, destroy ##classname }; \ -} - -#define PluginInterface2( pluginname, classname, baseclass, name, ver, rev ) \ -extern "C" { \ - baseclass *create ##classname() \ - { \ - return new classname(); \ - } \ - void destroy ##classname( baseclass *pCls ) \ - { \ - delete pCls; \ - } \ - PluginInfo pluginname = { \ - #pluginname, name, ver, rev, \ - (void *(*)())(create ##classname), \ - (void (*)( void * ))(destroy ##classname) }; \ -} - -#define PluginInterface3( structname, pluginname, classname, baseclass, name, ver, rev ) \ -extern "C" { \ - baseclass *create ##classname() \ - { \ - return new classname(); \ - } \ - void destroy ##classname( baseclass *pCls ) \ - { \ - delete pCls; \ - } \ - PluginInfo structname = { \ - #pluginname, name, ver, rev, \ - (void *(*)())(create ##classname), \ - (void (*)( void * ))(destroy ##classname) }; \ -} - -template -class Plugger -{ -public: - -public: - Plugger() : - hPlugin( new HashFunctionString(), 11 ), - hObj( new HashFunctionInt(), 11 ) - { - } - - virtual ~Plugger() - { - void *pos = hObj.getFirstItemPos(); - while( (pos = hObj.getNextItemPos( pos )) ) - { - T *pPlug = (T *)hObj.getItemID( pos ); - PluginReg *pReg = (PluginReg *)hObj.getItemData( pos ); - pReg->pInfo->destroyPlugin( pPlug ); - } - - std::list::iterator i; - for( i = lPlugin.begin(); i != lPlugin.end(); i++ ) - { - if( (*i)->bBuiltin == false ) - { - dlclose( (*i)->dlHandle ); - } - delete (*i); - } - } - - void registerBuiltinPlugin( PluginInfo *pInfo ) - { - PluginReg *pReg = new PluginReg; - pReg->bBuiltin = true; - pReg->pInfo = pInfo; - lPlugin.insert( lPlugin.end(), pReg ); - hPlugin.insert( pInfo->sID, pReg ); - } - - void registerExternalPlugin( const char *sFName, const char *sPluginName ) - { - PluginReg *pReg = (PluginReg *)hPlugin[sPluginName]; - if( pReg != NULL ) - { - hPlugin.del( sPluginName ); - dlclose( pReg->dlHandle ); - delete pReg; - pReg = NULL; - } - - pReg = new PluginReg; - - pReg->bBuiltin = false; - pReg->dlHandle = dlopen( sFName, RTLD_NOW ); - if( pReg->dlHandle == NULL ) - { - throw PluginException( 1, "Error on %s: %s", sFName, dlerror() ); - } - pReg->pInfo = (PluginInfo *)dlsym( pReg->dlHandle, sPluginName ); - if( pReg->pInfo == NULL ) - { - throw PluginException( 2, "Error on %s: %s", sFName, dlerror() ); - } - hPlugin.insert( pReg->pInfo->sID, pReg ); - lPlugin.insert( lPlugin.end(), pReg ); - } - - T *instantiate( const char *lpName ) - { - PluginReg *pReg = (PluginReg *)hPlugin[lpName]; - if( pReg == NULL ) - return NULL; - - T *p = (T *)pReg->pInfo->createPlugin(); - hObj.insert( p, pReg ); - //printf("pReg: %08X, pPlug: %08X\n", pReg, p ); - - return p; - } - - bool hasPlugin( const char *lpName ) - { - if( hPlugin[lpName] == NULL ) - return false; - return true; - } - - void destroy( T *pPlug ) - { - PluginReg *pReg = (PluginReg *)hObj[pPlug]; - //printf("pReg: %08X, pPlug: %08X\n", pReg, pPlug ); - if( pReg == NULL ) - return; - - pReg->pInfo->destroyPlugin( pPlug ); - - hObj.del( pPlug ); - } - - void unloadAll() - { - std::list::iterator i; - for( i = lPlugin.begin(); i != lPlugin.end(); i++ ) - { - if( (*i)->bBuiltin == false ) - { - dlclose( (*i)->dlHandle ); - } - delete (*i); - } - hPlugin.clear(); - } - -private: - std::list lPlugin; - HashTable hPlugin; - HashTable hObj; -}; - -#endif diff --git a/src/old/programchain.cpp b/src/old/programchain.cpp deleted file mode 100644 index 6120d58..0000000 --- a/src/old/programchain.cpp +++ /dev/null @@ -1,96 +0,0 @@ -#include -#include "programchain.h" - -ProgramChain::ProgramChain() : - xLog( MultiLog::getInstance() ) -{ - xLog.LineLog( MultiLog::LStatus, "Program Chain Initialized." ); -} - -ProgramChain::~ProgramChain() -{ -} - -bool ProgramChain::addLink( ProgramLink *pLink ) -{ - if( pLink->init() == false ) - { - emergencyShutdown(); - return false; - } - - lLink.append( pLink ); - - pLink->setChain( this ); - - return true; -} - -ProgramLink *ProgramChain::getLink( const char *lpName ) -{ - char a; - a = lpName[0]; - return NULL; -} - -ProgramLink *ProgramChain::getBaseLink() -{ - return NULL; -} - -bool ProgramChain::execChainOnce() -{ - int nLen = lLink.getSize(); - for( int j = 0; j < nLen; j++ ) - { - if( ((ProgramLink *)lLink[j])->timeSlice() == false ) - { - xLog.LineLog( MultiLog::LInfo, "Shutting down due to signal from link #%d", j ); - emergencyShutdown(); - return false; - } - } - - return true; -} - -bool ProgramChain::enterChainLoop() -{ - for(;;) - { - if( execChainOnce() == false ) - { - return false; - } - } - - return true; -} - -void ProgramChain::emergencyShutdown() -{ - int nLen = lLink.getSize(); - for( int j = 0; j < nLen; j++ ) - { - ((ProgramLink *)lLink[j])->deInit(); - delete (ProgramLink *)lLink[j]; - } - lLink.empty(); -} - -LinkMessage *ProgramChain::broadcastIRM( LinkMessage *pMsgOut, ProgramLink *pSender ) -{ - int nLen = lLink.getSize(); - for( int j = 0; j < nLen; j++ ) - { - LinkMessage *pMsg = ((ProgramLink *)lLink[j])->processIRM( pMsgOut ); - if( pMsg != NULL ) - { - delete pMsgOut; - return pMsg; - } - } - - delete pMsgOut; - return NULL; -} diff --git a/src/old/programchain.h b/src/old/programchain.h deleted file mode 100644 index 2bdfeee..0000000 --- a/src/old/programchain.h +++ /dev/null @@ -1,95 +0,0 @@ -#ifndef PROGRAMCHAIN_H -#define PROGRAMCHAIN_H - -#include "linkedlist.h" -#include "multilog.h" -#include "programlink.h" - -/** - * The Program Chain links together program "chunks" to more easily facilitate - * a generalized program loop with modular extensions. - *@author Mike Buland - */ -class ProgramChain -{ -public: - /** - * Construct an empty chain. - */ - ProgramChain(); - - /** - * Destroy your chain. - */ - virtual ~ProgramChain(); - - /** - * Adds a link to the end of the chain. - *@param pLink A pointer to the link to add to the chain. - *@returns True if adding the link was successful, otherwise false - *@author Mike Buland - */ - bool addLink( ProgramLink *pLink ); - - /** - * Gets a link by name. - *@param lpName The name of the link you're looking for. Every link has a - * name, apparently. - *@returns A pointer to the specified ProgramLink, or NULL if none were - * found matching your criteria. - *@author Mike Buland - */ - class ProgramLink *getLink( const char *lpName ); - - /** - * Gets the very first link in the chain. - *@returns A pointer to the first link in the chain. - *@author Mike Buland - */ - class ProgramLink *getBaseLink(); - - /** - * Runs through the chain once. Useful if you want to have more control - * over the operation of the chain. - *@returns true if every link returned true. If at least one link returns - * false, then returns false. - *@author Mike Buland - */ - bool execChainOnce(); - - /** - * Enters the master chain loop, looping over the entire chain and - * executing every link's TimeSlice routine in order, over and over, until - * a link returns a false value. - *@returns False, always. It returns true unless a link returned false, - * but loops until a link does return false. - *@author Mike Buland - **/ - bool enterChainLoop(); - - /** - * Broadcasts an Immediate Response Message to all active links, save the - * sender. Whatever link first responds with a non-null response message - * will have it's messages sent back to the broadcasting link as the returns - * of this function call. Therefore it is very important that all message - * processing code is handled in a fairly timely fasion. - *@param pMsgOut The message to broadcast in hopes of a response. - *@param pSender The message that sent out the message and doesn't want to - * receive it's own message. This should always just be "this". - *@returns The message that was returned by the first link to return a - * non-null response. If all messages return null responses then this also - * returns null. Please note that whoever calls this will be responsible - * for deleting the message returned by it, if non-null. - */ - class LinkMessage *broadcastIRM( LinkMessage *pMsgOut, ProgramLink *pSender ); - -private: - /** - * Shuts down all operation no matter what point in the operation we were. - */ - void emergencyShutdown(); - MultiLog &xLog; /**< A reference to the log. */ - LinkedList lLink; /**< The linked list that contains all of the links. */ -}; - -#endif diff --git a/src/old/programlink.cpp b/src/old/programlink.cpp deleted file mode 100644 index 21c6fe4..0000000 --- a/src/old/programlink.cpp +++ /dev/null @@ -1,54 +0,0 @@ -#include "programlink.h" -#include "programchain.h" - -ProgramLink::ProgramLink() -{ -} - -ProgramLink::~ProgramLink() -{ -} - -LinkMessage *ProgramLink::sendIRM( LinkMessage *pMsgOut ) -{ - return pChain->broadcastIRM( pMsgOut, this ); -} - -void ProgramLink::setChain( ProgramChain *pNewChain ) -{ - pChain = pNewChain; -} - -/* -void ProgramLink::postMessage( LinkMessage *pMsg, int nLvl ) -{ - if( nLvl == msgToChain ) - { - qMsgToChain.enqueue( pMsg ); - } - else if( nLvl == msgToLink ) - { - qMsgToLink.enqueue( pMsg ); - } - else - { - // ERROR! - } -} - -LinkMessage *ProgramLink::getMessage( int nLvl ) -{ - if( nLvl == msgToChain ) - { - return (LinkMessage *)qMsgToChain.dequeue(); - } - else if( nLvl == msgToLink ) - { - return (LinkMessage *)qMsgToLink.dequeue(); - } - else - { - // ERROR! - } -} -*/ diff --git a/src/old/programlink.h b/src/old/programlink.h deleted file mode 100644 index f93edcc..0000000 --- a/src/old/programlink.h +++ /dev/null @@ -1,99 +0,0 @@ -#ifndef PROGRAMLINK_H -#define PROGRAMLINK_H - -class ProgramLink; -#include "queue.h" -#include "linkmessage.h" -#include "programchain.h" - -/** - * Program Link is the base class for any object that will be a piece of the - * main program chain loop. - *@author Mike Buland - */ -class ProgramLink -{ -friend class ProgramChain; -public: - /** - * Construct a program link. - */ - ProgramLink(); - - /** - * Deconstruct. - */ - virtual ~ProgramLink(); - - /** - * Initialization code required for a link that wasn't performed in the - * constructor. - *@returns true if initialization was successful. A false value will halt - * the chain. - */ - virtual bool init()=0; - - /** - * DeInitialization code that should happen, but doesn't belong in the - * destructor. - *@returns true means everything worked, false means failure, but is - * meaningless. - */ - virtual bool deInit()=0; - - /** - * Executed once per link per chain pass. Contains the guts of the program. - *@returns true if everything went well. A false value will halt the chain. - */ - virtual bool timeSlice()=0; - - /** - * This must be handled in order to process Instant Response Messages. - * This function should return null on all messages that it doesn't - * understand how to handle, and construct new messages to return to sender - * in the cases where it does understand. - *@param pMsgIn The message that must be processed. - *@returns Either a new message in cases where a response is required, - * or null if nothing needs to be done by this link. - */ - virtual LinkMessage *processIRM( LinkMessage *pMsgIn ) = 0; - - /** - * Broadcast a LinkMessage to all other links in the system. Each other - * link will get a call of their processIRM function. If the message gets - * a response then you will regain control immediately, otherwise the system - * will give all other Links a chance to respond before returning NULL. - *@param pMsgOut The message to broadcast. - *@returns The message response, or NULL if no Link understood your message. - */ - LinkMessage *sendIRM( LinkMessage *pMsgOut ); - -private: - /** - * Set which chain we're assosiated with. This is how IRM messages make - * it out to the rest of the world. - *@param pNewChain A pointer to the containing program chain. - */ - void setChain( class ProgramChain *pNewChain ); - - /** - * The pointer to the containing chain. - */ - class ProgramChain *pChain; -/* - void postMessage( LinkMessage *pMsg, int nLvl ); - LinkMessage *getMessage( int nLvl ); - - enum - { - msgToChain, - msgToLink - }; - -private: - Queue qMsgToChain; - Queue qMsgToLink; -*/ -}; - -#endif diff --git a/src/plugger.cpp b/src/plugger.cpp new file mode 100644 index 0000000..f3bfa67 --- /dev/null +++ b/src/plugger.cpp @@ -0,0 +1 @@ +#include "plugger.h" diff --git a/src/plugger.h b/src/plugger.h new file mode 100644 index 0000000..98d4ecc --- /dev/null +++ b/src/plugger.h @@ -0,0 +1,196 @@ +#ifndef PLUGGER_H +#define PLUGGER_H + + +#include "bu/hash.h" +#include "bu/list.h" +#include +#include "bu/exceptions.h" +#include "bu/fstring.h" + +namespace Bu +{ + typedef struct PluginInfo + { + const char *sID; + const char *sAuthor; + unsigned short nVersion; + unsigned short nRevision; + void *(*createPlugin)(); + void (*destroyPlugin)( void * ); + } PluginInfo; + + typedef struct PluginReg + { + bool bBuiltin; + void *dlHandle; + PluginInfo *pInfo; + } PluginReg; + +#define PluginInterface( classname, baseclass, name, ver, rev ) \ + extern "C" { \ + baseclass *create ##classname() \ + { \ + return new classname(); \ + } \ + void destroy ##classname( baseclass *pCls ) \ + { \ + delete pCls; \ + } \ + PluginInfo classname = { \ + #classname, name, ver, rev, \ + create ##classname, destroy ##classname }; \ + } + +#define PluginInterface2( pluginname, classname, baseclass, name, ver, rev ) \ + extern "C" { \ + baseclass *create ##classname() \ + { \ + return new classname(); \ + } \ + void destroy ##classname( baseclass *pCls ) \ + { \ + delete pCls; \ + } \ + PluginInfo pluginname = { \ + #pluginname, name, ver, rev, \ + (void *(*)())(create ##classname), \ + (void (*)( void * ))(destroy ##classname) }; \ + } + +#define PluginInterface3( structname, pluginname, classname, baseclass, name, ver, rev ) \ + extern "C" { \ + baseclass *create ##classname() \ + { \ + return new classname(); \ + } \ + void destroy ##classname( baseclass *pCls ) \ + { \ + delete pCls; \ + } \ + PluginInfo structname = { \ + #pluginname, name, ver, rev, \ + (void *(*)())(create ##classname), \ + (void (*)( void * ))(destroy ##classname) }; \ + } + + template + class Plugger + { + public: + typedef Bu::Hash PluginHash; + typedef Bu::Hash InstHash; + + public: + Plugger() + { + } + + virtual ~Plugger() + { + for( InstHash::iterator i = hObj.begin(); i != hObj.end(); i++ ) + { + T *pPlug = (T *)i.getKey(); + PluginReg *pReg = (PluginReg *)*i; + pReg->pInfo->destroyPlugin( pPlug ); + } + + for( PluginHash::iterator i = hPlugin.begin(); + i != hPlugin.end(); i++ ) + { + if( (*i)->bBuiltin == false ) + { + dlclose( (*i)->dlHandle ); + } + delete (*i); + } + } + + void registerBuiltinPlugin( PluginInfo *pInfo ) + { + PluginReg *pReg = new PluginReg; + pReg->bBuiltin = true; + pReg->pInfo = pInfo; + hPlugin.insert( pInfo->sID, pReg ); + } + + void registerExternalPlugin( const char *sFName, const char *sPluginName ) + { + PluginReg *pReg = (PluginReg *)hPlugin[sPluginName]; + if( pReg != NULL ) + { + hPlugin.erase( sPluginName ); + dlclose( pReg->dlHandle ); + delete pReg; + pReg = NULL; + } + + pReg = new PluginReg; + + pReg->bBuiltin = false; + pReg->dlHandle = dlopen( sFName, RTLD_NOW ); + if( pReg->dlHandle == NULL ) + { + throw PluginException( 1, "Error on %s: %s", sFName, dlerror() ); + } + pReg->pInfo = (PluginInfo *)dlsym( pReg->dlHandle, sPluginName ); + if( pReg->pInfo == NULL ) + { + throw PluginException( 2, "Error on %s: %s", sFName, dlerror() ); + } + hPlugin.insert( pReg->pInfo->sID, pReg ); + } + + T *instantiate( const char *lpName ) + { + PluginReg *pReg = (PluginReg *)hPlugin[lpName]; + if( pReg == NULL ) + return NULL; + + T *p = (T *)pReg->pInfo->createPlugin(); + hObj.insert( p, pReg ); + //printf("pReg: %08X, pPlug: %08X\n", pReg, p ); + + return p; + } + + bool hasPlugin( const char *lpName ) + { + if( hPlugin[lpName] == NULL ) + return false; + return true; + } + + void destroy( T *pPlug ) + { + PluginReg *pReg = (PluginReg *)hObj[pPlug]; + //printf("pReg: %08X, pPlug: %08X\n", pReg, pPlug ); + if( pReg == NULL ) + return; + + pReg->pInfo->destroyPlugin( pPlug ); + + hObj.erase( pPlug ); + } + + void unloadAll() + { + for( PluginHash::iterator i = hPlugin.begin(); + i != hPlugin.end(); i++ ) + { + if( (*i)->bBuiltin == false ) + { + dlclose( (*i)->dlHandle ); + } + delete (*i); + } + hPlugin.clear(); + } + + private: + PluginHash hPlugin; + InstHash hObj; + }; +} + +#endif diff --git a/src/programchain.cpp b/src/programchain.cpp new file mode 100644 index 0000000..0bb7a77 --- /dev/null +++ b/src/programchain.cpp @@ -0,0 +1,97 @@ +#include +#include "bu/programchain.h" +#include "bu/programlink.h" + +using namespace Bu; + +Bu::ProgramChain::ProgramChain() +{ +} + +Bu::ProgramChain::~ProgramChain() +{ +} + +bool Bu::ProgramChain::addLink( ProgramLink *pLink ) +{ + if( pLink->init() == false ) + { + emergencyShutdown(); + return false; + } + + lLink.append( pLink ); + + pLink->setChain( this ); + + return true; +} + +ProgramLink *Bu::ProgramChain::getLink( const char *lpName ) +{ + char a; + a = lpName[0]; + return NULL; +} + +ProgramLink *Bu::ProgramChain::getBaseLink() +{ + return NULL; +} + +bool Bu::ProgramChain::execChainOnce() +{ + for( Bu::List::iterator i = lLink.begin(); + i != lLink.end(); i++ ) + { + if( (*i)->timeSlice() == false ) + { + emergencyShutdown(); + return false; + } + } + + return true; +} + +bool Bu::ProgramChain::enterChainLoop() +{ + for(;;) + { + if( execChainOnce() == false ) + { + return false; + } + } + + return true; +} + +void Bu::ProgramChain::emergencyShutdown() +{ + for( Bu::List::iterator i = lLink.begin(); + i != lLink.end(); i++ ) + { + (*i)->deInit(); + delete *i; + } + lLink.clear(); +} + +LinkMessage *Bu::ProgramChain::broadcastIRM( LinkMessage *pMsgOut, ProgramLink *pSender ) +{ + for( Bu::List::iterator i = lLink.begin(); + i != lLink.end(); i++ ) + { + LinkMessage *pMsg = (*i)->processIRM( pMsgOut ); + if( pMsg != NULL ) + { + delete pMsgOut; + return pMsg; + } + } + + delete pMsgOut; + return NULL; +} + diff --git a/src/programchain.h b/src/programchain.h new file mode 100644 index 0000000..e73d659 --- /dev/null +++ b/src/programchain.h @@ -0,0 +1,98 @@ +#ifndef PROGRAMCHAIN_H +#define PROGRAMCHAIN_H + +#include "bu/list.h" +#include "bu/linkmessage.h" + +namespace Bu +{ + class ProgramLink; + /** + * The Program Chain links together program "chunks" to more easily facilitate + * a generalized program loop with modular extensions. + *@author Mike Buland + */ + class ProgramChain + { + public: + /** + * Construct an empty chain. + */ + ProgramChain(); + + /** + * Destroy your chain. + */ + virtual ~ProgramChain(); + + /** + * Adds a link to the end of the chain. + *@param pLink A pointer to the link to add to the chain. + *@returns True if adding the link was successful, otherwise false + *@author Mike Buland + */ + bool addLink( Bu::ProgramLink *pLink ); + + /** + * Gets a link by name. + *@param lpName The name of the link you're looking for. Every link has a + * name, apparently. + *@returns A pointer to the specified ProgramLink, or NULL if none were + * found matching your criteria. + *@author Mike Buland + */ + class ProgramLink *getLink( const char *lpName ); + + /** + * Gets the very first link in the chain. + *@returns A pointer to the first link in the chain. + *@author Mike Buland + */ + class ProgramLink *getBaseLink(); + + /** + * Runs through the chain once. Useful if you want to have more control + * over the operation of the chain. + *@returns true if every link returned true. If at least one link returns + * false, then returns false. + *@author Mike Buland + */ + bool execChainOnce(); + + /** + * Enters the master chain loop, looping over the entire chain and + * executing every link's TimeSlice routine in order, over and over, until + * a link returns a false value. + *@returns False, always. It returns true unless a link returned false, + * but loops until a link does return false. + *@author Mike Buland + **/ + bool enterChainLoop(); + + /** + * Broadcasts an Immediate Response Message to all active links, save the + * sender. Whatever link first responds with a non-null response message + * will have it's messages sent back to the broadcasting link as the returns + * of this function call. Therefore it is very important that all message + * processing code is handled in a fairly timely fasion. + *@param pMsgOut The message to broadcast in hopes of a response. + *@param pSender The message that sent out the message and doesn't want to + * receive it's own message. This should always just be "this". + *@returns The message that was returned by the first link to return a + * non-null response. If all messages return null responses then this also + * returns null. Please note that whoever calls this will be responsible + * for deleting the message returned by it, if non-null. + */ + class LinkMessage *broadcastIRM( LinkMessage *pMsgOut, ProgramLink *pSender ); + + private: + /** + * Shuts down all operation no matter what point in the operation we were. + */ + void emergencyShutdown(); + Bu::List lLink; /**< The linked list that contains all of the links. */ + }; +} + + +#endif diff --git a/src/programlink.cpp b/src/programlink.cpp new file mode 100644 index 0000000..e5c624c --- /dev/null +++ b/src/programlink.cpp @@ -0,0 +1,56 @@ +#include "bu/programlink.h" +#include "bu/programchain.h" + +using namespace Bu; + +Bu::ProgramLink::ProgramLink() +{ +} + +Bu::ProgramLink::~ProgramLink() +{ +} + +LinkMessage *Bu::ProgramLink::sendIRM( LinkMessage *pMsgOut ) +{ + return pChain->broadcastIRM( pMsgOut, this ); +} + +void Bu::ProgramLink::setChain( ProgramChain *pNewChain ) +{ + pChain = pNewChain; +} + +/* +void ProgramLink::postMessage( LinkMessage *pMsg, int nLvl ) +{ + if( nLvl == msgToChain ) + { + qMsgToChain.enqueue( pMsg ); + } + else if( nLvl == msgToLink ) + { + qMsgToLink.enqueue( pMsg ); + } + else + { + // ERROR! + } +} + +LinkMessage *ProgramLink::getMessage( int nLvl ) +{ + if( nLvl == msgToChain ) + { + return (LinkMessage *)qMsgToChain.dequeue(); + } + else if( nLvl == msgToLink ) + { + return (LinkMessage *)qMsgToLink.dequeue(); + } + else + { + // ERROR! + } +} +*/ diff --git a/src/programlink.h b/src/programlink.h new file mode 100644 index 0000000..7c31a18 --- /dev/null +++ b/src/programlink.h @@ -0,0 +1,100 @@ +#ifndef PROGRAMLINK_H +#define PROGRAMLINK_H + +#include "bu/linkmessage.h" +#include "bu/programchain.h" + +namespace Bu +{ + /** + * Program Link is the base class for any object that will be a piece of the + * main program chain loop. + *@author Mike Buland + */ + class ProgramLink + { + friend class Bu::ProgramChain; + public: + /** + * Construct a program link. + */ + ProgramLink(); + + /** + * Deconstruct. + */ + virtual ~ProgramLink(); + + /** + * Initialization code required for a link that wasn't performed in the + * constructor. + *@returns true if initialization was successful. A false value will halt + * the chain. + */ + virtual bool init()=0; + + /** + * DeInitialization code that should happen, but doesn't belong in the + * destructor. + *@returns true means everything worked, false means failure, but is + * meaningless. + */ + virtual bool deInit()=0; + + /** + * Executed once per link per chain pass. Contains the guts of the program. + *@returns true if everything went well. A false value will halt the chain. + */ + virtual bool timeSlice()=0; + + /** + * This must be handled in order to process Instant Response Messages. + * This function should return null on all messages that it doesn't + * understand how to handle, and construct new messages to return to sender + * in the cases where it does understand. + *@param pMsgIn The message that must be processed. + *@returns Either a new message in cases where a response is required, + * or null if nothing needs to be done by this link. + */ + virtual LinkMessage *processIRM( LinkMessage *pMsgIn ) = 0; + + /** + * Broadcast a LinkMessage to all other links in the system. Each other + * link will get a call of their processIRM function. If the message gets + * a response then you will regain control immediately, otherwise the system + * will give all other Links a chance to respond before returning NULL. + *@param pMsgOut The message to broadcast. + *@returns The message response, or NULL if no Link understood your message. + */ + LinkMessage *sendIRM( LinkMessage *pMsgOut ); + + private: + /** + * Set which chain we're assosiated with. This is how IRM messages make + * it out to the rest of the world. + *@param pNewChain A pointer to the containing program chain. + */ + void setChain( class ProgramChain *pNewChain ); + + /** + * The pointer to the containing chain. + */ + class ProgramChain *pChain; + /* + void postMessage( LinkMessage *pMsg, int nLvl ); + LinkMessage *getMessage( int nLvl ); + + enum + { + msgToChain, + msgToLink + }; + + private: + Queue qMsgToChain; + Queue qMsgToLink; + */ + }; +} + +#endif diff --git a/src/tafwriter.cpp b/src/tafwriter.cpp index 3e6c025..ac42d3d 100644 --- a/src/tafwriter.cpp +++ b/src/tafwriter.cpp @@ -1,9 +1,32 @@ #include "tafwriter.h" -Bu::TafWriter::TafWriter() +Bu::TafWriter::TafWriter( Bu::Stream &sOut ) : + sOut( sOut ) { } Bu::TafWriter::~TafWriter() { } + +void Bu::TafWriter::writeNode( Bu::TafNode *pRoot ) +{ + sOut.write("{", 1 ); + writeString( pRoot->getName().getStr() ); + sOut.write(": ", 2 ); + sOut.write("}", 1 ); +} + +void Bu::TafWriter::writeString( const Bu::FString &str ) +{ + sOut.write("\"", 1 ); + for( const char *s = str.getStr(); *s; s++ ) + { + if( *s == '\"' ) + sOut.write("\\\"", 2 ); + else + sOut.write( s, 1 ); + } + sOut.write("\"", 1 ); +} + diff --git a/src/tafwriter.h b/src/tafwriter.h index 7057d62..4310e62 100644 --- a/src/tafwriter.h +++ b/src/tafwriter.h @@ -2,6 +2,9 @@ #define BU_TAF_WRITER_H #include +#include "bu/tafnode.h" +#include "bu/stream.h" +#include "bu/fstring.h" namespace Bu { @@ -11,11 +14,14 @@ namespace Bu class TafWriter { public: - TafWriter(); + TafWriter( Bu::Stream &sOut ); virtual ~TafWriter(); - private: + void writeNode( Bu::TafNode *pRoot ); + private: + void writeString( const Bu::FString &str ); + Bu::Stream &sOut; }; } -- cgit v1.2.3