CPPGPGPU Library - Reference (Doxygen)

Main Page | General Use | Reference | Examples Info | Get/Download CPPGPGPU | SF.net Page

Node.cpp

Go to the documentation of this file.
00001 #include "Node.h"
00002 
00003 #ifdef _WIN32
00004 #include <windows.h>
00005 #else
00006 #include <pthread.h>
00007 #endif
00008 
00009 #undef PostMessage
00010 
00013 Node::Node()
00014 {
00015     This = NULL;
00016 }
00017 
00018 Node::Node( NodeObject * nToInit )
00019 {
00020     This = NULL;
00021     Hook( nToInit );
00022 }
00023 
00024 Node::Node( const Node & nToCopy )
00025 {
00026     This = NULL;
00027     Hook( nToCopy.This );
00028 }
00029 
00030 Node::~Node()
00031 {
00032     Unhook( This );
00033 }
00034 
00035 Node & Node::operator = ( const Node & rhs )
00036 {
00037     NodeObject * Tmp = This;
00038     Hook( rhs.This );
00039     Unhook( Tmp );
00040     return *this;
00041 }
00042 
00043 Node & Node::operator = ( NodeObject * rhs )
00044 {
00045     NodeObject * Tmp = This;
00046     Hook( rhs );
00047     Unhook( Tmp );
00048     return *this;
00049 }
00050 
00051 void Node::Hook( NodeObject * n )
00052 {
00053     if( n )
00054         n->Lock();
00055     This = n;
00056     if( This ) This->IncCount();
00057     if( This ) This->Unlock();
00058 }
00059 
00060 void Node::Unhook( NodeObject * n )
00061 {
00062     if( !n )
00063         return;
00064     n->Lock();
00065     n->DecCount();
00066     if( n->GetCount() <= 0 )
00067     {
00068         n->Unlock();
00069         delete n;
00070     }
00071     else
00072         n->Unlock();
00073     return;
00074 }
00075 
00078 NodeObject::NodeObject( const string & sName )
00079 {
00080 #ifndef NOSYNCHRONIZATION
00081 #if defined( _WIN32 )
00082     SECURITY_ATTRIBUTES p;
00083     p.nLength = sizeof( SECURITY_ATTRIBUTES );
00084     p.bInheritHandle = true;
00085     p.lpSecurityDescriptor = NULL;
00086     m_vMutex = CreateMutex( &p, true, sName.c_str() );
00087 #else
00088     m_vMutex = malloc( sizeof( pthread_mutex_t ) );
00089     pthread_mutexattr_t attr;
00090     pthread_mutexattr_init( &attr );
00091     pthread_mutexattr_settype( &attr, PTHREAD_MUTEX_RECURSIVE );
00092     pthread_mutex_init( (pthread_mutex_t*)m_vMutex, &attr );
00093 #endif
00094 #endif
00095     m_sName = sName;
00096     m_iCount = 0;   //Careful: This must be incremented upon a node assignment.
00097     m_bDestroyOnUpdate = false;
00098     NODEMAN->Add( this );
00099 }
00100 
00101 NodeObject::~NodeObject()
00102 {
00103     NODEMAN->Drop( this );
00104 #ifndef NOSYNCHRONIZATION
00105 #if defined( _WIN32 )
00106     CloseHandle( m_vMutex );
00107 #else
00108     pthread_mutex_destroy( (pthread_mutex_t*)m_vMutex );
00109     free( m_vMutex );
00110 #endif
00111 #endif
00112 }
00113 
00114 void NodeObject::SetName( const string & sName )
00115 {
00116     NODEMAN->Drop( this );
00117     m_sName = sName;
00118     NODEMAN->Add( this );
00119 }
00120 
00121 Node NodeObject::AttachChild( Node n )
00122 {
00123     m_vnChildren.push_back( n );
00124     n->AttachParent( Node( this ) );
00125     return Node( this );
00126 }
00127 
00128 void NodeObject::DetachChild( Node n )
00129 {
00130     for( unsigned i = 0; i < m_vnChildren.size(); ++i )
00131         if( m_vnChildren[i] == n )
00132         {
00133             m_vnChildren[i]->DetachParent( this );
00134             m_vnChildren.erase( m_vnChildren.begin() + i );
00135             --i;
00136         }
00137 }
00138 
00139 void NodeObject::AttachParent( NodeObject * n )
00140 {
00141     m_vnParents.push_back( n );
00142 }
00143 
00144 void NodeObject::Init()
00145 {
00146 }
00147 
00148 void NodeObject::Disestablish()
00149 {
00150     
00151 }
00152 
00153 void NodeObject::Render()
00154 {
00155     for( unsigned i = 0; i < m_vnChildren.size(); ++i )
00156         m_vnChildren[i]->Render();
00157 }
00158 
00159 void NodeObject::Update( const float fDtime )
00160 {
00161     for( unsigned i = 0; i < m_vnChildren.size(); ++i )
00162         m_vnChildren[i]->Update( fDtime );
00163 }
00164 
00165 void NodeObject::Message( int iMessageID, const string & sMessageName, const string & sMessagePayload )
00166 {
00167     printf( "Message Received: %d %s %s ME:\"%s\"\n", iMessageID, sMessageName.c_str(), sMessagePayload.c_str(), GetName().c_str() );
00168 }
00169 
00170 void NodeObject::DetachParent( NodeObject * n )
00171 {
00172     for( unsigned i = 0; i < m_vnParents.size(); ++i )
00173         if( m_vnParents[i] == n )
00174         {
00175             m_vnParents.erase( m_vnParents.begin() + i );
00176             --i;
00177         }
00178 }
00179 
00180 
00181 #ifndef NOSYNCHRONIZATION
00182 void NodeObject::Lock()
00183 {
00184 #if defined( _WIN32 )
00185     int r = WaitForSingleObject( m_vMutex, 100000 );  //100 seconds should be long enough.
00186 #else
00187     pthread_mutex_lock( (pthread_mutex_t*)m_vMutex );
00188 #endif
00189 }
00190 
00191 void NodeObject::Unlock()
00192 {
00193 #if defined( _WIN32 )
00194     ReleaseMutex( m_vMutex );
00195 #else
00196     pthread_mutex_unlock( (pthread_mutex_t*)m_vMutex );
00197 #endif
00198 }
00199 
00200 #else
00201 void NodeObject::Lock() { }
00202 void NodeObject::Unlock() { }
00203 #endif
00204 
00205 REGISTER_CLASS( NodeObject );
00206 
00209 NodeManager * NODEMAN = NULL;
00210 
00211 NodeManager * NodeManager::Instance()
00212 {
00213     if( !NODEMAN )
00214     {
00215         NODEMAN = new NodeManager;
00216         NODEMAN->m_fCurrentTime = 0.0f;
00217     }
00218     return NODEMAN;
00219 }
00220 
00221 void NodeManager::RegisterType( const string & sClass, ProducerFunct t )
00222 {
00223     m_mToMake[sClass] = t;
00224 }
00225 
00226 Node NodeManager::Spawn( const string & sClass, const string & sName )
00227 {
00228     NodeObject * n = GetInstanceExp( sName );
00229     if( n )
00230         return Node( n );
00231     else
00232         return SpawnExplicit( sClass, sName );
00233 }
00234 
00235 Node NodeManager::SpawnExplicit( const string & sClass, const string & sName )
00236 {
00237     map< string, ProducerFunct >::iterator i( m_mToMake.find( sClass ) );
00238     if( i != m_mToMake.end() )
00239         return (i->second)( sName );
00240     else
00241         return Node( NULL );
00242 }
00243 
00244 void NodeManager::Add( NodeObject * nObject )
00245 {
00246     if( nObject )
00247         m_mInstances[nObject->GetName()] = nObject;
00248 }
00249 
00250 void NodeManager::Drop( NodeObject * nObject )
00251 {
00252     if( nObject )
00253     {
00254         map< string, NodeObject * >::iterator i = m_mInstances.find( nObject->GetName() );
00255         if( i != m_mInstances.end() )
00256             m_mInstances.erase( i );
00257     }
00258 }
00259 
00260 void NodeManager::RegisterForMessage( const string & sMessage, int iMessageID, Node nToRegister )
00261 {
00262     m_mMessageMatches[sMessage][nToRegister] = iMessageID;
00263 }
00264 
00265 void NodeManager::UnregisterForMessage( const string & sMessage, int iMessageID, Node nToRegister )
00266 {
00267     map< Node, int > & j = m_mMessageMatches[sMessage];
00268     map< Node, int >::iterator i = j.find( nToRegister );
00269     if( i == j.end() )
00270         return;
00271     else
00272         j.erase( i );
00273 }
00274 
00275 void NodeManager::BroadcastMessage( const string & sMessage, const string & sPayload, Node nTarget )
00276 {
00277     if( nTarget )
00278         nTarget->Message( -1, sMessage, sPayload );
00279     else
00280     {
00281         map< string, map< Node, int > >::iterator i = m_mMessageMatches.find( sMessage );
00282         if( i == m_mMessageMatches.end() )
00283             return;
00284 
00285         map< Node, int >::iterator j = (i->second).begin();
00286         for( ; j != (i->second).end() ; ++j )
00287             ((NodeObject*)(j->first).Get())->Message( j->second, sMessage, sPayload );
00288     }
00289 }
00290 
00291 void NodeManager::PostMessage( const string & sMessage, const string & sPayload, Node nTarget, const float fTimeInFuture )
00292 {
00293     if( fTimeInFuture < 0.00001 ) //For dispatchment immediately
00294     {
00295         m_dImmediateMessages.push_back( StringPair(sMessage, sPayload, nTarget) );
00296     } else
00297     {
00298         int i;
00299         for( i = m_vFutureMessages.size() - 1; i >= 0; --i )
00300             if( m_vFutureMessages[i].fFuture - m_fCurrentTime > fTimeInFuture )
00301             {
00302                 m_vFutureMessages.insert( m_vFutureMessages.begin() + i + 1, StringPairFloat( sMessage, sPayload, nTarget, fTimeInFuture + m_fCurrentTime ) );
00303                 break;
00304             }
00305         //Looks like we're the biggest element in the pond.
00306         if( i < 0 )
00307             m_vFutureMessages.insert( m_vFutureMessages.begin(), StringPairFloat( sMessage, sPayload, nTarget, fTimeInFuture + m_fCurrentTime ) );
00308     }
00309 }
00310 
00311 void NodeManager::Update( const float fDtime )
00312 {
00313     m_fCurrentTime += fDtime;
00314     for( unsigned i = 0; i < m_dImmediateMessages.size(); i++ )
00315     {
00316         StringPair * f = &m_dImmediateMessages[i];
00317         BroadcastMessage( f->sP1, f->sP2, f->nTarget );
00318     }
00319     m_dImmediateMessages.clear();
00320 
00321     for( int i = m_vFutureMessages.size() - 1; i >= 0; --i )
00322     {
00323         if( m_vFutureMessages[i].fFuture > m_fCurrentTime )
00324             break;
00325         StringPairFloat * f = &m_vFutureMessages[i];
00326         BroadcastMessage( f->sP1, f->sP2, f->nTarget );
00327         m_vFutureMessages.resize( m_vFutureMessages.size() - 1 );
00328     }
00329 }
00330 
00331 /*
00332 Copyright (c) 2007 Charles Lohr
00333 
00334 Permission is hereby granted, free of charge, to any person obtaining a copy
00335 of this software and associated documentation files (the "Software"), to deal
00336 in the Software without restriction, including without limitation the rights
00337 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00338 copies of the Software, and to permit persons to whom the Software is
00339 furnished to do so, subject to the following conditions:
00340 
00341 The above copyright notice and this permission notice shall be included in
00342 all copies or substantial portions of the Software.
00343 
00344 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00345 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00346 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00347 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00348 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00349 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00350 THE SOFTWARE.
00351 */

© 2005-2007 Charles Lohr, Joshua Allen, David Chapman, Andrew Lohr. All material including documentation under the MIT/X11 license.