SharedJello::~SharedJello(void) { if(pipe!=0&&!communicationThread.isJoined()) { /* Ask the server to disconnect: */ { Threads::Mutex::Lock pipeLock(pipeMutex); writeMessage(DISCONNECT_REQUEST,*pipe); pipe->flush(); } /* Wait until the communication thread receives the disconnect reply and terminates: */ communicationThread.join(); } /* Close the server pipe: */ pipe=0; /* Delete the crystal and renderer triple-buffers: */ for(int i=0;i<3;++i) { delete renderers[i]; delete crystals[i]; } /* Delete all atom draggers: */ for(AtomDraggerList::iterator adIt=atomDraggers.begin();adIt!=atomDraggers.end();++adIt) delete *adIt; /* Delete the user interface: */ delete mainMenu; delete settingsDialog; }
SharedJello::~SharedJello(void) { if(pipe!=0) { { /* Ask the server to disconnect: */ Threads::Mutex::Lock pipeLock(pipe->getMutex()); pipe->writeMessage(SharedJelloPipe::DISCONNECT_REQUEST); pipe->flushWrite(); pipe->shutdown(false,true); } } /* Wait until the communication thread receives the disconnect reply and terminates: */ communicationThread.join(); /* Close the server pipe: */ delete pipe; /* Delete the crystal and renderer triple-buffer: */ for(int i=0;i<3;++i) { delete renderers[i]; delete crystals[i]; } /* Delete all atom draggers: */ for(AtomDraggerList::iterator adIt=atomDraggers.begin();adIt!=atomDraggers.end();++adIt) delete *adIt; /* Delete the user interface: */ delete mainMenu; delete settingsDialog; }
void SharedJello::sendParamUpdate(void) { /* Send a parameter state update to the server: */ Threads::Mutex::Lock pipeLock(pipeMutex); writeMessage(CLIENT_PARAMUPDATE,*pipe); pipe->write<Scalar>(atomMass); pipe->write<Scalar>(attenuation); pipe->write<Scalar>(gravity); pipe->flush(); }
void SharedJello::sendParamUpdate(void) { /* Send a parameter state update to the server: */ { Threads::Mutex::Lock pipeLock(pipe->getMutex()); pipe->writeMessage(SharedJelloPipe::CLIENT_PARAMUPDATE); pipe->write<Scalar>(atomMass); pipe->write<Scalar>(attenuation); pipe->write<Scalar>(gravity); pipe->flushWrite(); } }
void ProviderAgent::_writeResponse(Message* message) { PEG_METHOD_ENTER(TRC_PROVIDERAGENT, "ProviderAgent::_writeResponse"); CIMMessage* response = dynamic_cast<CIMMessage*>(message); PEGASUS_ASSERT(response != 0); // // Write the response message to the pipe // try { // Use Mutex to prevent concurrent writes to the same pipe AutoMutex pipeLock(_pipeToServerMutex); AnonymousPipe::Status writeStatus = _pipeToServer->writeMessage(response); if (writeStatus != AnonymousPipe::STATUS_SUCCESS) { PEG_TRACE_CSTRING(TRC_PROVIDERAGENT, Tracer::LEVEL1, "Error writing response to pipe."); Logger::put_l(Logger::ERROR_LOG, System::CIMSERVER, Logger::WARNING, MessageLoaderParms( "ProviderManager.ProviderAgent.ProviderAgent." "CIMSERVER_COMMUNICATION_FAILED", "cimprovagt \"$0\" communication with CIM Server failed. " "Exiting.", _agentId)); _terminating = true; } } catch (...) { PEG_TRACE_CSTRING(TRC_PROVIDERAGENT, Tracer::LEVEL1, "Caught exception while writing response."); Logger::put_l(Logger::ERROR_LOG, System::CIMSERVER, Logger::WARNING, MessageLoaderParms( "ProviderManager.ProviderAgent.ProviderAgent." "CIMSERVER_COMMUNICATION_FAILED", "cimprovagt \"$0\" communication with CIM Server failed. " "Exiting.", _agentId)); _terminating = true; } PEG_METHOD_EXIT(); }
void SharedJelloServer::sendServerUpdate(void) { /* Lock the client state list: */ Threads::Mutex::Lock clientStateListLock(clientStateListMutex); /* Go through all client states: */ for(ClientStateList::iterator cslIt=clientStates.begin();cslIt!=clientStates.end();++cslIt) { ClientState* cs=*cslIt; if(cs->connected) { try { Threads::Mutex::Lock pipeLock(cs->pipeMutex); if(cs->parameterVersion!=parameterVersion) { /* Send a parameter update message: */ writeMessage(SERVER_PARAMUPDATE,*cs->pipe); cs->pipe->write<Scalar>(crystal.getAtomMass()); cs->pipe->write<Scalar>(crystal.getAttenuation()); cs->pipe->write<Scalar>(crystal.getGravity()); cs->parameterVersion=parameterVersion; } /* Send a server update message: */ writeMessage(SERVER_UPDATE,*cs->pipe); /* Send the crystal's state: */ crystal.writeAtomStates(*cs->pipe); cs->pipe->flush(); } catch(...) { /* Ignore write errors; let the client communication thread handle them */ } } } }
void SharedJello::frame(void) { /* Check if there was a parameter update since the last frame: */ if(parameterVersion!=newParameterVersion) { /* Update the settings dialog: */ updateSettingsDialog(); parameterVersion=newParameterVersion; } /* Check if there was a server state update since the last frame: */ if(lockedIndex!=mostRecentIndex) { /* Deactivate the previously locked crystal state: */ renderers[lockedIndex]->setActive(false); /* Lock the most recent crystal state: */ lockedIndex=mostRecentIndex; /* Activate the previously locked crystal state: */ renderers[lockedIndex]->setActive(true); } /* Send a state update to the server: */ { Threads::Mutex::Lock pipeLock(pipe->getMutex()); pipe->writeMessage(SharedJelloPipe::CLIENT_UPDATE); pipe->write<int>(atomDraggers.size()); for(AtomDraggerList::iterator adIt=atomDraggers.begin();adIt!=atomDraggers.end();++adIt) { pipe->write<unsigned int>((*adIt)->draggerID); pipe->write<int>((*adIt)->draggerRayBased?1:0); pipe->writePoint((*adIt)->draggerRay.getOrigin()); pipe->writeVector((*adIt)->draggerRay.getDirection()); pipe->writeONTransform((*adIt)->draggerTransformation); pipe->write<char>((*adIt)->active?char(1):char(0)); } pipe->flushWrite(); } }
void SharedJello::frame(void) { /* Check if there was a parameter update since the last frame: */ if(parameterVersion!=newParameterVersion) { /* Update the settings dialog: */ updateSettingsDialog(); parameterVersion=newParameterVersion; } /* Check if there was a server state update since the last frame: */ if(lockedIndex!=mostRecentIndex) { /* Deactivate the previously locked crystal state: */ renderers[lockedIndex]->setActive(false); /* Lock the most recent crystal state: */ lockedIndex=mostRecentIndex; /* Activate the previously locked crystal state: */ renderers[lockedIndex]->setActive(true); } /* Send a state update to the server: */ { Threads::Mutex::Lock pipeLock(pipeMutex); writeMessage(CLIENT_UPDATE,*pipe); pipe->write<Card>(atomDraggers.size()); for(AtomDraggerList::iterator adIt=atomDraggers.begin();adIt!=atomDraggers.end();++adIt) { pipe->write<Card>((*adIt)->draggerID); pipe->write<Byte>((*adIt)->draggerRayBased?1:0); write((*adIt)->draggerRay,*pipe); write((*adIt)->draggerTransformation,*pipe); pipe->write<Byte>((*adIt)->active?1:0); } pipe->flush(); } }
void* SharedJelloServer::clientCommunicationThreadMethod(SharedJelloServer::ClientState* clientState) { /* Enable immediate cancellation of this thread: */ Threads::Thread::setCancelState(Threads::Thread::CANCEL_ENABLE); // Threads::Thread::setCancelType(Threads::Thread::CANCEL_ASYNCHRONOUS); Comm::NetPipe& pipe=*(clientState->pipe); Threads::Mutex& pipeMutex=clientState->pipeMutex; try { /* Connect the client by sending the size of the Jell-O crystal: */ { Threads::Mutex::Lock pipeLock(pipeMutex); writeMessage(CONNECT_REPLY,pipe); write(crystal.getDomain().min,pipe); write(crystal.getDomain().max,pipe); Card numAtoms[3]; for(int i=0;i<3;++i) numAtoms[i]=crystal.getNumAtoms()[i]; pipe.write(numAtoms,3); pipe.flush(); } /* Mark the client as connected: */ { Threads::Mutex::Lock clientStateListLock(clientStateListMutex); clientState->connected=true; } #ifdef VERBOSE std::cout<<"SharedJelloServer: Connection to client from host "<<pipe.getPeerHostName()<<", port "<<pipe.getPeerPortId()<<" established"<<std::endl<<std::flush; #endif /* Run the client communication protocol machine: */ bool goOn=true; while(goOn) { /* Wait for and handle the next message: */ switch(readMessage(pipe)) { case CLIENT_PARAMUPDATE: /* Update the simulation parameter set: */ { Threads::Mutex::Lock parameterLock(parameterMutex); ++newParameterVersion; newAtomMass=pipe.read<Scalar>(); newAttenuation=pipe.read<Scalar>(); newGravity=pipe.read<Scalar>(); } break; case CLIENT_UPDATE: { /* Lock the next free client update slot: */ ClientState::StateUpdate& su=clientState->stateUpdates.startNewValue(); /* Process the client update message: */ unsigned int newNumDraggers=pipe.read<Card>(); if(newNumDraggers!=su.numDraggers) { delete[] su.draggerStates; su.numDraggers=newNumDraggers; su.draggerStates=su.numDraggers!=0?new ClientState::StateUpdate::DraggerState[su.numDraggers]:0; } for(unsigned int draggerIndex=0;draggerIndex<su.numDraggers;++draggerIndex) { su.draggerStates[draggerIndex].id=pipe.read<Card>(); su.draggerStates[draggerIndex].rayBased=pipe.read<Byte>()!=0; SharedJelloProtocol::read(su.draggerStates[draggerIndex].ray,pipe); SharedJelloProtocol::read(su.draggerStates[draggerIndex].transform,pipe); su.draggerStates[draggerIndex].active=pipe.read<Byte>()!=0; } /* Mark the client update slot as most recent: */ clientState->stateUpdates.postNewValue(); break; } case DISCONNECT_REQUEST: /* Send a disconnect reply: */ { Threads::Mutex::Lock pipeLock(pipeMutex); writeMessage(DISCONNECT_REPLY,pipe); pipe.flush(); } goOn=false; break; default: Misc::throwStdErr("Protocol error in client communication"); } } } catch(std::runtime_error err) { /* Ignore any connection errors; just disconnect the client */ std::cerr<<"SharedJelloServer: Disconnecting client due to exception "<<err.what()<<std::endl<<std::flush; } /****************************************************************************************** Disconnect the client by removing it from the list and deleting the client state structure: ******************************************************************************************/ #ifdef VERBOSE std::cout<<"SharedJelloServer: Disconnecting client from host "<<pipe.getPeerHostName()<<", port "<<pipe.getPeerPortId()<<std::endl<<std::flush; #endif { /* Lock the client state list: */ Threads::Mutex::Lock clientStateListLock(clientStateListMutex); /* Unlock all atoms held by the client: */ for(ClientState::AtomLockMap::Iterator alIt=clientState->atomLocks.begin();!alIt.isFinished();++alIt) crystal.unlockAtom(alIt->getDest().draggedAtom); /* Find this client's state in the list: */ ClientStateList::iterator cslIt; for(cslIt=clientStates.begin();cslIt!=clientStates.end()&&*cslIt!=clientState;++cslIt) ; /* Remove the client state from the list: */ clientStates.erase(cslIt); /* Delete the client state object: */ delete clientState; } return 0; }
void* VRDeviceServer::clientCommunicationThreadMethod(VRDeviceServer::ClientData* clientData) { /* Enable immediate cancellation of this thread: */ Threads::Thread::setCancelState(Threads::Thread::CANCEL_ENABLE); Threads::Thread::setCancelType(Threads::Thread::CANCEL_ASYNCHRONOUS); Vrui::VRDevicePipe& pipe=clientData->pipe; enum State { START,CONNECTED,ACTIVE,STREAMING,FINISH }; try { /* Execute client communication protocol state machine: */ State state=START; // Current client state while(state!=FINISH) { /* Read the next message from the client: */ Vrui::VRDevicePipe::MessageIdType message=pipe.readMessage(); /* Handle the message based on the current state: */ switch(state) { case START: switch(message) { case Vrui::VRDevicePipe::CONNECT_REQUEST: { /* Read client's protocol version number: */ unsigned int clientProtocolVersion=pipe.read<unsigned int>(); /* Lock the pipe for writing: */ Threads::Mutex::Lock pipeLock(clientData->pipeMutex); /* Send connect reply message: */ pipe.writeMessage(Vrui::VRDevicePipe::CONNECT_REPLY); if(clientProtocolVersion>Vrui::VRDevicePipe::protocolVersionNumber) clientProtocolVersion=Vrui::VRDevicePipe::protocolVersionNumber; pipe.write<unsigned int>(clientProtocolVersion); /* Send server layout: */ deviceManager->getState().writeLayout(pipe); pipe.flush(); } /* Go to connected state: */ state=CONNECTED; break; default: state=FINISH; } break; case CONNECTED: switch(message) { case Vrui::VRDevicePipe::ACTIVATE_REQUEST: { /* Lock the client list: */ Threads::Mutex::Lock clientListLock(clientListMutex); /* Start VR devices if this is the first active client: */ if(numActiveClients==0) deviceManager->start(); /* Activate the client: */ clientData->active=true; ++numActiveClients; } /* Go to active state: */ state=ACTIVE; break; default: state=FINISH; } break; case ACTIVE: switch(message) { case Vrui::VRDevicePipe::PACKET_REQUEST: case Vrui::VRDevicePipe::STARTSTREAM_REQUEST: deviceManager->lockState(); try { /* Lock the pipe for writing: */ Threads::Mutex::Lock pipeLock(clientData->pipeMutex); if(message==Vrui::VRDevicePipe::STARTSTREAM_REQUEST) { /* Enable streaming: */ clientData->streaming=true; } /* Send packet reply message: */ pipe.writeMessage(Vrui::VRDevicePipe::PACKET_REPLY); /* Send server state: */ deviceManager->getState().write(pipe); pipe.flush(); } catch(...) { /* Unlock the device manager's state and throw the exception again: */ deviceManager->unlockState(); throw; } deviceManager->unlockState(); if(message==Vrui::VRDevicePipe::STARTSTREAM_REQUEST) state=STREAMING; break; case Vrui::VRDevicePipe::DEACTIVATE_REQUEST: { /* Lock the client list: */ Threads::Mutex::Lock clientListLock(clientListMutex); /* Deactivate client: */ clientData->active=false; --numActiveClients; /* Stop VR devices if this was the last active client: */ if(numActiveClients==0) deviceManager->stop(); } /* Go to connected state: */ state=CONNECTED; break; default: state=FINISH; } break; case STREAMING: switch(message) { case Vrui::VRDevicePipe::PACKET_REQUEST: /* Ignore message: */ break; case Vrui::VRDevicePipe::STOPSTREAM_REQUEST: { /* Lock the pipe for writing: */ Threads::Mutex::Lock pipeLock(clientData->pipeMutex); /* Disable streaming: */ clientData->streaming=false; /* Send stopstream reply message: */ pipe.writeMessage(Vrui::VRDevicePipe::STOPSTREAM_REPLY); pipe.flush(); } /* Go to active state: */ state=ACTIVE; break; default: state=FINISH; } break; default: /* Just to make g++ happy... */ ; } } } catch(std::runtime_error err) { /* Print error message to stderr, but ignore exception otherwise: */ fprintf(stderr,"VRDeviceServer: Terminating client connection due to exception\n %s\n",err.what()); fflush(stderr); } catch(...) { /* Just ignore the exception: */ fprintf(stderr,"VRDeviceServer: Terminating client connection due to spurious exception\n"); fflush(stderr); } /* Cleanly deactivate client: */ { Threads::Mutex::Lock clientListLock(clientListMutex); if(clientData->streaming) { /* Leave streaming mode: */ clientData->streaming=false; } if(clientData->active) { /* Deactivate client: */ clientData->active=false; --numActiveClients; /* Stop VR devices if this was the last active client: */ if(numActiveClients==0) deviceManager->stop(); } /* Remove client from list: */ ClientList::iterator c**t; for(c**t=clientList.begin();c**t!=clientList.end()&&*c**t!=clientData;++c**t) ; clientList.erase(c**t); /* Disconnect client: */ delete clientData; } /* Terminate: */ #ifdef VERBOSE printf("VRDeviceServer: Disconnected client\n"); fflush(stdout); #endif return 0; }