const Model* Config::getModel( const eq::uint128_t& modelID ) { if( modelID == 0 ) return 0; // Protect if accessed concurrently from multiple pipe threads const eq::Node* node = getNodes().front(); const bool needModelLock = (node->getPipes().size() > 1); lunchbox::ScopedWrite _mutex( needModelLock ? &_modelLock : 0 ); const size_t nModels = _models.size(); LBASSERT( _modelDist.size() == nModels ); for( size_t i = 0; i < nModels; ++i ) { const ModelDist* dist = _modelDist[ i ]; if( dist->getID() == modelID ) return _models[ i ]; } _modelDist.push_back( new ModelDist ); Model* model = _modelDist.back()->loadModel( getApplicationNode(), getClient(), modelID ); LBASSERT( model ); _models.push_back( model ); return model; }
void Window::initCapabilities( osg::GraphicsContext* context ) { static lunchbox::Lock _wsiLock; static bool _initialized = false; lunchbox::ScopedWrite _mutex( &_wsiLock ); if( !_initialized ) { // Hack to initialize osgEarth with an existing graphics context osg::ref_ptr< WindowingSystem > wsi = new WindowingSystem( context ); wsi->initCapabilities( ); _initialized = true; } }
Mutex::Mutex() : FOR_UNIX(_mutex()) FOR_WIN(_handle()) { FOR_UNIX(pthread_mutex_init(&_mutex, NULL)); FOR_WIN(_handle = CreateMutex(NULL, false, NULL)); } Mutex::~Mutex() { FOR_UNIX(pthread_mutex_destroy(&_mutex)); FOR_WIN(CloseHandle(_handle)); } bool Mutex::lock() { FOR_UNIX(return pthread_mutex_lock(&_mutex) == 0); FOR_WIN(return WaitForSingleObject(_handle, INFINITE) == WAIT_OBJECT_0); } bool Mutex::tryLock() { FOR_UNIX(return pthread_mutex_trylock(&_mutex) == 0); FOR_WIN(return WaitForSingleObject(_handle, 0) == WAIT_OBJECT_0); } bool Mutex::unlock() { FOR_UNIX(return pthread_mutex_unlock(&_mutex) == 0); FOR_WIN(return ReleaseMutex(_handle)); } ScopLock::ScopLock(Mutex& mutex) : _mutex(mutex) { _mutex.lock(); } ScopLock::~ScopLock() { _mutex.unlock(); }
int main( int argc, char **argv ) { if( !co::init( argc, argv )) return EXIT_FAILURE; co::ConnectionDescriptionPtr remote; size_t packetSize = 1048576u; // needs to be modulo 8 uint32_t nPackets = 0xFFFFFFFFu; uint32_t waitTime = 0; bool useZeroconf = true; bool useObjects = false; try // command line parsing { TCLAP::CmdLine command( "nodeperf - Collage node-to-node network benchmark tool", ' ', co::Version::getString( )); TCLAP::ValueArg< std::string > remoteArg( "c", "connect", "connect to remote node, implies --disableZeroconf", false, "", "IP[:port][:protocol]", command ); TCLAP::SwitchArg zcArg( "d", "disableZeroconf", "Disable automatic connect using zeroconf", command, false ); TCLAP::SwitchArg objectsArg( "o", "object", "Benchmark object-object instead of node-node communication", command, false ); TCLAP::ValueArg<size_t> sizeArg( "p", "packetSize", "packet size", false, packetSize, "unsigned", command ); TCLAP::ValueArg<size_t> packetsArg( "n", "numPackets", "number of packets to send", false, nPackets, "unsigned", command ); TCLAP::ValueArg<uint32_t> waitArg( "w", "wait", "wait time (ms) between sends", false, 0, "unsigned", command ); command.parse( argc, argv ); if( remoteArg.isSet( )) { remote = new co::ConnectionDescription; remote->port = 4242; remote->fromString( remoteArg.getValue( )); } useZeroconf = !zcArg.isSet(); useObjects = objectsArg.isSet(); if( sizeArg.isSet( )) packetSize = sizeArg.getValue(); if( packetsArg.isSet( )) nPackets = uint32_t( packetsArg.getValue( )); if( waitArg.isSet( )) waitTime = waitArg.getValue(); } catch( TCLAP::ArgException& exception ) { LBERROR << "Command line parse error: " << exception.error() << " for argument " << exception.argId() << std::endl; co::exit(); return EXIT_FAILURE; } // Set up local node co::LocalNodePtr localNode = new PerfNode; if( !localNode->initLocal( argc, argv )) { co::exit(); return EXIT_FAILURE; } localNode->getZeroconf().set( "coNodeperf", co::Version::getString( )); Object object; object.setID( _objectID + localNode->getNodeID( )); LBCHECK( localNode->registerObject( &object )); // run if( remote ) { co::NodePtr node = new PerfNodeProxy; node->addConnectionDescription( remote ); localNode->connect( node ); } else if( useZeroconf ) { co::Zeroconf zeroconf = localNode->getZeroconf(); const co::Strings& instances = localNode->getZeroconf().getInstances(); BOOST_FOREACH( const std::string& instance, instances ) { if( !zeroconf.get( instance, "coNodeperf" ).empty( )) localNode->connect( co::uint128_t( instance )); } } { lunchbox::ScopedFastRead _mutex( nodes_ ); if( nodes_->empty( )) // Add default listener so others can connect to me localNode->addListener( new co::ConnectionDescription ); } co::Nodes nodes; while( true ) { lunchbox::Thread::yield(); lunchbox::ScopedFastRead _mutex( nodes_ ); if( !nodes_->empty( )) break; } Buffer buffer; const size_t bufferElems = packetSize / sizeof( uint64_t ); buffer.resize( bufferElems ); for( size_t i = 0; i < bufferElems; ++i ) buffer[i] = i; const float mBytesSec = buffer.getNumBytes() / 1024.0f / 1024.0f * 1000.0f; lunchbox::Clock clock; size_t sentPackets = 0; clock.reset(); while( nPackets-- ) { { lunchbox::ScopedFastRead _mutex( nodes_ ); if( nodes != *nodes_ ) { for( co::NodesCIter i = nodes_->begin(); i != nodes_->end(); ++i) { co::NodePtr node = *i; co::NodesCIter j = stde::find( nodes, node ); if( j == nodes.end( )) { // new node, map perf object LBASSERT( node->getType() == 0xC0FFEEu ); PerfNodeProxyPtr peer = static_cast< PerfNodeProxy* >( node.get( )); LBCHECK( localNode->mapObject( &peer->object, _objectID + peer->getNodeID( ))); } } nodes = *nodes_; } } if( nodes.empty( )) break; for( co::NodesCIter i = nodes.begin(); i != nodes.end(); ++i ) { co::NodePtr node = *i; if( node->getType() != 0xC0FFEEu ) continue; if( useObjects ) { const size_t j = (object.getID().low() + nPackets) % bufferElems; buffer[ j ] = nPackets; object.send( node, co::CMD_OBJECT_CUSTOM ) << nPackets <<buffer; buffer[ j ] = 0xDEADBEEFu; } else { const size_t j = (node->getNodeID().low() + nPackets) % bufferElems; buffer[ j ] = nPackets; node->send( co::CMD_NODE_CUSTOM ) << nPackets << buffer; buffer[ j ] = 0xDEADBEEFu; } ++sentPackets; if( waitTime > 0 ) lunchbox::sleep( waitTime ); } const float time = clock.getTimef(); if( time > 1000.f ) { const lunchbox::ScopedMutex<> mutex( print_ ); std::cerr << "Send perf: " << mBytesSec / time * sentPackets << "MB/s (" << sentPackets / time * 1000.f << "pps)" << std::endl; sentPackets = 0; clock.reset(); } } const float time = clock.getTimef(); if( time > 1000.f ) { const lunchbox::ScopedMutex<> mutex( print_ ); std::cerr << "Send perf: " << mBytesSec / time * sentPackets << "MB/s (" << sentPackets / time * 1000.f << "pps)" << std::endl; sentPackets = 0; clock.reset(); } localNode->deregisterObject( &object ); LBCHECK( localNode->exitLocal( )); LBCHECK( co::exit( )); return EXIT_SUCCESS; }