void RemoteNetworkView::ForwardEvent(IEventDataPtr pEventData) { std::string httpinmsg; if (!pEventData) { GCC_ERROR("Event Invalid"); return; } int socketId = pEventData->VGetSocketId(); std::ostrstream out; pEventData->VSerialize(out); out << std::ends; IPacket *packetBack = NULL; if (!strncmp("HTTP", &out.rdbuf()->str()[0], 4)) { packetBack = GCC_NEW HTTPPacket(out.rdbuf()->str()); } else { //TODO create binary packet } std::shared_ptr<IPacket> ipBack(packetBack); printf("RemoteNetworkView Forward Event socket:%d %s\n", socketId, pEventData->GetName()); g_pSocketManager->Send(socketId, ipBack); if (!strncmp("HTTP", &out.rdbuf()->str()[0], 4)) { IEventDataPtr pCloseSocketHttpEvent(CREATE_EVENT(EventData_CloseSocketHTTP::sk_EventType)); char* id = new char[100]; sprintf_s(id, 100, "%d", socketId); httpinmsg.append(id); std::istrstream in(httpinmsg.c_str(), httpinmsg.size()); pCloseSocketHttpEvent->VDeserialize(in); IEventManager::Get()->VQueueEvent(pCloseSocketHttpEvent); } }
//--------------------------------------------------------------------------------------------------------------------- // EventManager::VQueueEvent //--------------------------------------------------------------------------------------------------------------------- bool EventManager::VQueueEvent(const IEventDataPtr& pEvent) { GCC_ASSERT(m_activeQueue >= 0); GCC_ASSERT(m_activeQueue < EVENTMANAGER_NUM_QUEUES); // make sure the event is valid if (!pEvent) { GCC_ERROR("Invalid event in VQueueEvent()"); return false; } GCC_LOG("Events", "Attempting to queue event: " + std::string(pEvent->GetName())); auto findIt = m_eventListeners.find(pEvent->VGetEventType()); if (findIt != m_eventListeners.end()) { m_queues[m_activeQueue].push_back(pEvent); GCC_LOG("Events", "Successfully queued event: " + std::string(pEvent->GetName())); return true; } else { GCC_LOG("Events", "Skipping event since there are no delegates registered to receive it: " + std::string(pEvent->GetName())); return false; } }
// ///////////////////////////////////////////////////////////////// // // ///////////////////////////////////////////////////////////////// bool EventManager::VQueueEvent ( IEventDataPtr const & inEvent ) { assert ( m_activeQueue >= 0 ); assert ( m_activeQueue < kNumQueues ); if ( ! VValidateType( inEvent->VGetEventType() ) ) return false; EventListenerMap::const_iterator it = m_registry.find( inEvent->VGetEventType().getHashValue() ); if ( it == m_registry.end() ) { // if global listener is not active, then abort queue add EventListenerMap::const_iterator itWC = m_registry.find( 0 ); if ( itWC == m_registry.end() ) { // no listeners for this event, skipit return false; } } m_queues[m_activeQueue].push_back( inEvent ); return true; }
// ***************************************************************************** void cEventManager::VUpdate(const TICK tickCurrent, const float fElapsedTime) { // swap active queues and clear the new queue after the swap int queueToProcess = m_activeQueue; m_activeQueue = (m_activeQueue + 1) % 2; m_queues[m_activeQueue].clear(); // Process the queue while (!m_queues[queueToProcess].empty()) { // pop the front of the queue IEventDataPtr pEvent = m_queues[queueToProcess].front(); m_queues[queueToProcess].pop_front(); Log_Write(ILogger::LT_EVENT, 3 , "Processing Event : " + pEvent->VGetEventName()); // find all the delegate functions registered for this event auto findIt = m_eventListeners.find(pEvent->VGetEventID()); if (findIt != m_eventListeners.end()) { const EventListenerList& eventListeners = findIt->second; // call each listener for (auto it = eventListeners.begin(); it != eventListeners.end(); ++it) { EventListenerCallBackFn listener = (*it); listener(pEvent); } } } }
void RemoteNetworkView::RemoveHTTPSocket(IEventDataPtr pEventData) { printf("Remove HTTP Socket %d\n", pEventData->VGetSocketId()); NetSocket* netSocket = g_pSocketManager->FindSocket(pEventData->VGetSocketId()); // say to delete socket AFTER packet treatment if (netSocket) { netSocket->SetSocketDelete(4); } }
void NetworkEventForwarder::ForwardEvent(IEventDataPtr pEventData) { std::ostrstream out; out << static_cast<int>(RemoteEventSocket::NetMsg_Event) << " "; out << pEventData->VGetEventType() << " "; pEventData->VSerialize(out); out << "\r\n"; std::shared_ptr<BinaryPacket> eventMsg(GCC_NEW BinaryPacket(out.rdbuf()->str(), out.pcount())); g_pSocketManager->Send(m_sockId, eventMsg); }
//--------------------------------------------------------------------------------------------------------------------- // EventManager::VTrigger //--------------------------------------------------------------------------------------------------------------------- bool EventManager::VTriggerEvent(const IEventDataPtr& pEvent) const { GCC_LOG("Events", "Attempting to trigger event " + std::string(pEvent->GetName())); bool processed = false; auto findIt = m_eventListeners.find(pEvent->VGetEventType()); if (findIt != m_eventListeners.end()) { const EventListenerList& eventListenerList = findIt->second; for (EventListenerList::const_iterator it = eventListenerList.begin(); it != eventListenerList.end(); ++it) { EventListenerDelegate listener = (*it); GCC_LOG("Events", "Sending Event " + std::string(pEvent->GetName()) + " to delegate."); listener(pEvent); // call the delegate processed = true; } } return processed; }
void RemoteNetworkView::GetActor(IEventDataPtr pEventData) { char response[4]; std::string httpinmsg; IEventDataPtr pResponseHttpEvent(CREATE_EVENT(EventData_ResponseHTTP::sk_EventType)); std::shared_ptr<EventData_GetActor> pCastEventData = std::static_pointer_cast<EventData_GetActor>(pEventData); std::string name = pCastEventData->VGetActorName(); unsigned int ip = pCastEventData->VGetIp(); pResponseHttpEvent->VSetSocketId(pEventData->VGetSocketId()); pResponseHttpEvent->VSetIp(ip); //look for actor data in actor manager by ip / actor name StrongActorPtr pActor = m_ActorManager->GetActorByName(ip, name); if (pActor == NULL) { _itoa_s(http_response_code_t::NOTFOUND, response,10); httpinmsg.append(response); std::istrstream in(httpinmsg.c_str(),httpinmsg.size()); pResponseHttpEvent->VDeserialize(in); IEventManager::Get()->VTriggerEvent(pResponseHttpEvent); } else { // Better (de-)serialize Actor with streams std::string buffer; _itoa_s(http_response_code_t::OK, response, 10); buffer.append(response); buffer.append(" "); char* id = new char[10]; sprintf_s(id, 10, "%d", pActor->GetId()); buffer.append(id); buffer.append("#"); buffer.append(pActor->GetName()); buffer.append("#"); Vec3 position = pActor->GetPosition(); char *xpos = new char[10]; sprintf_s(xpos, 10, "%.3f", position.x); buffer.append(xpos); buffer.append("#"); char *ypos = new char[10]; sprintf_s(ypos, 10, "%.3f", position.y); buffer.append(ypos); buffer.append("#"); char *zpos = new char[10]; sprintf_s(zpos, 10, "%.3f", position.z); buffer.append(zpos); buffer.push_back('\0'); // when found, send answer std::istrstream in(buffer.c_str(), buffer.size()); pResponseHttpEvent->VDeserialize(in); IEventManager::Get()->VTriggerEvent(pResponseHttpEvent); } }
// ***************************************************************************** void cEventManager::VTriggerEvent(const IEventDataPtr & pEvent) { auto findIt = m_eventListeners.find(pEvent->VGetEventID()); if (findIt != m_eventListeners.end()) { const EventListenerList& eventListenerList = findIt->second; for (EventListenerList::const_iterator it = eventListenerList.begin(); it != eventListenerList.end(); ++it) { EventListenerCallBackFn listener = (*it); listener(pEvent); } } }
// ***************************************************************************** void cEventManager::VQueueEvent(const IEventDataPtr & pEvent) { // make sure the event is valid if (!pEvent) { Log_Write(ILogger::LT_ERROR, 1, "Invalid event in VQueueEvent()"); return; } auto findIt = m_eventListeners.find(pEvent->VGetEventID()); if (findIt != m_eventListeners.end()) { m_queues[m_activeQueue].push_back(pEvent); } else { Log_Write(ILogger::LT_EVENT, 2, "Skipping event since there are no delegates registered to receive it: " + pEvent->VGetEventName()); } }
// ///////////////////////////////////////////////////////////////// // GameTimer version. // // ///////////////////////////////////////////////////////////////// bool EventManager::VTick (U64 maxMillis) { //// Reset listeners removed flag upon entry. //m_listenersRemoved = false; // Create and start a timer on entry. shared_ptr<IGameTimer> timer(GCC_NEW GlfwGameTimer()); timer->VStart(); EventListenerMap::const_iterator itWC = m_registry.find( 0 ); // TODO: Implement this when i get multiprogramming chapter done. //// This section added to handle events from other threads //// Check out Chapter 18 //// -------------------------------------------------------- //IEventDataPtr rte; // //while (m_RealtimeEventQueue.try_pop(rte)) //{ // VQueueEvent(rte); // // curMs = GetTickCount(); // if ( maxMillis != IEventManager::kINFINITE ) // { // // if ( curMs >= maxMs ) // { // assert(0 && "A realtime process is spamming the event manager!"); // } // } //} //// -------------------------------------------------------- // swap active queues, make sure new queue is empty after the // swap ... I32 queueToProcess = m_activeQueue; m_activeQueue = ( m_activeQueue + 1 ) % kNumQueues; m_queues[m_activeQueue].clear(); // now process as many events as we can ( possibly time // limited ) ... always do AT LEAST one event, if ANY are // available ... while ( m_queues[queueToProcess].size() > 0 ) { IEventDataPtr event = m_queues[queueToProcess].front(); m_queues[queueToProcess].pop_front(); EventType const & eventType = event->VGetEventType(); EventListenerMap::const_iterator itListeners = m_registry.find( eventType.getHashValue() ); // Handle of events of type wildcard if ( itWC != m_registry.end() ) { EventListenerTable const & table = itWC->second; for(EventListenerTable::const_iterator it2 = table.begin(); it2 != table.end(); ++it2 ) { (*it2)->VHandleEvent( *event ); } } // no listerners currently for this event type, skipit if ( itListeners == m_registry.end() ) continue; EventListenerTable const & table = itListeners->second; // Handle all events of the current type in the queue for(EventListenerTable::const_iterator it = table.begin(); it != table.end(); ++it) { if ( (*it)->VHandleEvent( *event ) ) { break; } } if ( maxMillis != IEventManager::kINFINITE ) { if ( static_cast<U64>(timer->VGetTime()) >= maxMillis ) { // time ran about, abort processing loop break; } } } // if any events left to process, push them onto the active // queue. // // Note: to preserver sequencing, go bottom-up on the // raminder, inserting them at the head of the active // queue... bool queueFlushed = ( m_queues[queueToProcess].size() == 0 ); if ( !queueFlushed ) { while ( m_queues[queueToProcess].size() > 0 ) { IEventDataPtr event = m_queues[queueToProcess].back(); m_queues[queueToProcess].pop_back(); m_queues[m_activeQueue].push_front( event ); } } // all done, this pass return queueFlushed; }
// // EventManager::VTick - Chapter 10, page 296 // EventManager::VTick - Chapter 18, page 671 (for the threadsafe stuff) // // Allow for processing of any queued messages, optionally // specify a processing time limit so that the event processing // does not take too long. Note the danger of using this // artificial limiter is that all messages may not in fact get // processed. // // returns true if all messages ready for processing were // completed, false otherwise (e.g. timeout ) // bool EventManager::VTick ( unsigned long maxMillis ) { unsigned long curMs = GetTickCount(); unsigned long maxMs = maxMillis == IEventManager::kINFINITE ? IEventManager::kINFINITE : (curMs + maxMillis ); EventListenerMap::const_iterator itWC = m_registry.find( 0 ); // This section added to handle events from other threads // Check out Chapter 18 // -------------------------------------------------------- IEventDataPtr rte; while (m_RealtimeEventQueue.try_pop(rte)) { VQueueEvent(rte); curMs = GetTickCount(); if ( maxMillis != IEventManager::kINFINITE ) { if ( curMs >= maxMs ) { assert(0 && "A realtime process is spamming the event manager!"); } } } // -------------------------------------------------------- // swap active queues, make sure new queue is empty after the // swap ... int queueToProcess = m_activeQueue; m_activeQueue = ( m_activeQueue + 1 ) % kNumQueues; m_queues[m_activeQueue].clear(); // now process as many events as we can ( possibly time // limited ) ... always do AT LEAST one event, if ANY are // available ... while ( m_queues[queueToProcess].size() > 0 ) { IEventDataPtr event = m_queues[queueToProcess].front(); m_queues[queueToProcess].pop_front(); EventType const & eventType = event->VGetEventType(); EventListenerMap::const_iterator itListeners = m_registry.find( eventType.getHashValue() ); if ( itWC != m_registry.end() ) { EventListenerTable const & table = itWC->second; bool processed = false; for ( EventListenerTable::const_iterator it2 = table.begin(), it2End = table.end(); it2 != it2End; it2++ ) { (*it2)->HandleEvent( *event ); } } // no listerners currently for this event type, skipit if ( itListeners == m_registry.end() ) continue; unsigned int const kEventId = itListeners->first; EventListenerTable const & table = itListeners->second; for ( EventListenerTable::const_iterator it = table.begin(), end = table.end(); it != end ; it++ ) { if ( (*it)->HandleEvent( *event ) ) { break; } } curMs = GetTickCount(); if ( maxMillis != IEventManager::kINFINITE ) { if ( curMs >= maxMs ) { // time ran about, abort processing loop break; } } } // if any events left to process, push them onto the active // queue. // // Note: to preserver sequencing, go bottom-up on the // raminder, inserting them at the head of the active // queue... bool queueFlushed = ( m_queues[queueToProcess].size() == 0 ); if ( !queueFlushed ) { while ( m_queues[queueToProcess].size() > 0 ) { IEventDataPtr event = m_queues[queueToProcess].back(); m_queues[queueToProcess].pop_back(); m_queues[m_activeQueue].push_front( event ); } } // all done, this pass return queueFlushed; }
//--------------------------------------------------------------------------------------------------------------------- // EventManager::VTick //--------------------------------------------------------------------------------------------------------------------- bool EventManager::VUpdate(unsigned long maxMillis) { unsigned long currMs = GetTickCount(); unsigned long maxMs = ((maxMillis == IEventManager::kINFINITE) ? (IEventManager::kINFINITE) : (currMs + maxMillis)); // This section added to handle events from other threads. Check out Chapter 20. IEventDataPtr pRealtimeEvent; while (m_realtimeEventQueue.try_pop(pRealtimeEvent)) { VQueueEvent(pRealtimeEvent); currMs = GetTickCount(); if (maxMillis != IEventManager::kINFINITE) { if (currMs >= maxMs) { GCC_ERROR("A realtime process is spamming the event manager!"); } } } // swap active queues and clear the new queue after the swap int queueToProcess = m_activeQueue; m_activeQueue = (m_activeQueue + 1) % EVENTMANAGER_NUM_QUEUES; m_queues[m_activeQueue].clear(); GCC_LOG("EventLoop", "Processing Event Queue " + ToStr(queueToProcess) + "; " + ToStr((unsigned long)m_queues[queueToProcess].size()) + " events to process"); // Process the queue while (!m_queues[queueToProcess].empty()) { // pop the front of the queue IEventDataPtr pEvent = m_queues[queueToProcess].front(); m_queues[queueToProcess].pop_front(); GCC_LOG("EventLoop", "\t\tProcessing Event " + std::string(pEvent->GetName())); const EventType& eventType = pEvent->VGetEventType(); // find all the delegate functions registered for this event auto findIt = m_eventListeners.find(eventType); if (findIt != m_eventListeners.end()) { const EventListenerList& eventListeners = findIt->second; GCC_LOG("EventLoop", "\t\tFound " + ToStr((unsigned long)eventListeners.size()) + " delegates"); // call each listener for (auto it = eventListeners.begin(); it != eventListeners.end(); ++it) { EventListenerDelegate listener = (*it); GCC_LOG("EventLoop", "\t\tSending event " + std::string(pEvent->GetName()) + " to delegate"); listener(pEvent); } } // check to see if time ran out currMs = GetTickCount(); if (maxMillis != IEventManager::kINFINITE && currMs >= maxMs) { GCC_LOG("EventLoop", "Aborting event processing; time ran out"); break; } } // If we couldn't process all of the events, push the remaining events to the new active queue. // Note: To preserve sequencing, go back-to-front, inserting them at the head of the active queue bool queueFlushed = (m_queues[queueToProcess].empty()); if (!queueFlushed) { while (!m_queues[queueToProcess].empty()) { IEventDataPtr pEvent = m_queues[queueToProcess].back(); m_queues[queueToProcess].pop_back(); m_queues[m_activeQueue].push_front(pEvent); } } return queueFlushed; }