void ServoRestyleManager::PostRestyleEvent(Element* aElement, nsRestyleHint aRestyleHint, nsChangeHint aMinChangeHint) { MOZ_ASSERT(!(aMinChangeHint & nsChangeHint_NeutralChange), "Didn't expect explicit change hints to be neutral!"); if (MOZ_UNLIKELY(IsDisconnected()) || MOZ_UNLIKELY(PresContext()->PresShell()->IsDestroying())) { return; } // We allow posting restyles from within change hint handling, but not from // within the restyle algorithm itself. MOZ_ASSERT(!ServoStyleSet::IsInServoTraversal()); if (aRestyleHint == 0 && !aMinChangeHint) { return; // Nothing to do. } // Processing change hints sometimes causes new change hints to be generated, // and very occasionally, additional restyle hints. We collect the change // hints manually to avoid re-traversing the DOM to find them. if (mReentrantChanges && !aRestyleHint) { mReentrantChanges->AppendElement(ReentrantChange { aElement, aMinChangeHint }); return; } if (aRestyleHint & ~eRestyle_AllHintsWithAnimations) { mHaveNonAnimationRestyles = true; } Servo_NoteExplicitHints(aElement, aRestyleHint, aMinChangeHint); }
void XEWinConnectionInServer::SendData( const BYTE *pBuffer, int len ) { // XLOCK_OBJ; if( IsDisconnected() ) return; if( m_Socket ) { // 커넥션이 끊어진 이후에 올수도 있다. memset( &m_opSend, 0, sizeof( m_opSend ) ); m_opSend.typeEvent = 1; DWORD sendBytes = 0; WSABUF b[ 1 ]; b[0].buf = (CHAR*)pBuffer; b[0].len = len; // WSARecv와 마찬가지로 미리 실행시키고 완료되면 워커스레드의 IOCP에서 통보받는다. auto result = WSASend( m_Socket, b, 1, &sendBytes, 0, (LPWSAOVERLAPPED)&m_opSend, nullptr ); if( result == SOCKET_ERROR ) { const auto lastErr = GetLastError(); if( XBREAK(lastErr != WSAECONNRESET && lastErr != ERROR_IO_PENDING)) { int numError = WSAGetLastError(); CONSOLE_THIS( "connect", "WSAGetLastError() == 0x%x socket=%d this=0x%0x idConnect=0x%0x", numError, (DWORD)m_Socket, ( DWORD )this, m_idConnect ); ClearConnection(); } else { XBREAK( sendBytes != 0 && (DWORD)len != sendBytes ); // 어떤경우에 생기는지 확인하려고 } } else { XBREAK( sendBytes != 0 && (DWORD)len != sendBytes ); // 어떤경우에 생기는지 확인하려고 } // 전부다 못보낸 경우도 처리해야 할듯. #pragma message( "check this" ) } // Socket }
void ServoRestyleManager::PostRestyleEvent(Element* aElement, nsRestyleHint aRestyleHint, nsChangeHint aMinChangeHint) { if (MOZ_UNLIKELY(IsDisconnected()) || MOZ_UNLIKELY(PresContext()->PresShell()->IsDestroying())) { return; } if (aRestyleHint == 0 && !aMinChangeHint && !HasPendingRestyles()) { return; // Nothing to do. } // XXX This is a temporary hack to make style attribute change works. // In the future, we should be able to use this hint directly. if (aRestyleHint & eRestyle_StyleAttribute) { aRestyleHint |= eRestyle_Subtree; } // Note that unlike in Servo, we don't mark elements as dirty until we process // the restyle hints in ProcessPendingRestyles. if (aRestyleHint || aMinChangeHint) { ServoElementSnapshot* snapshot = SnapshotForElement(aElement); snapshot->AddExplicitRestyleHint(aRestyleHint); snapshot->AddExplicitChangeHint(aMinChangeHint); } PostRestyleEventInternal(false); }
/** @brief */ void XEWinConnectionInServer::ProcessHeartBeat() { // XLOCK_OBJ; ////////////////////////////////////////////////////////////////////////// if( m_modeHeartBeat == xHB_READY ) { if( m_timerHeartBeat.IsOff() ) m_timerHeartBeat.Set( 10.f ); // x초 기다리고 요청패킷을 보내본다. if( m_timerHeartBeat.IsOver() ) { // 확인패킷 보내고 10초짜리 타이머 돌린다. 10초안에 응답이 안오면 이 커넥트는 끊는다. // 아이폰에서 테스트할때 와이파이에서 3G로 바꿔서 연결끊어졌는데 소켓으로 데이타는 계속 날아가는 // 현상 있었음. 클라가보내는 응답도 받아야 할듯? XPacket ar((ID)XE::xXEPK_REQUEST_HB); Send( ar ); if( IsDisconnected() == FALSE ) { m_modeHeartBeat = xHB_REQUEST; float secNotResponse = 40.f; // 디폴트 if( XEOption::sGet() ) { auto sec = XEOption::sGet()->GetParam().GetFloat( "sec_not_response" ); if( sec > 0 ) { secNotResponse = sec; } else { CONSOLE( "경고: ini에 sec_not_response값이 정해지지 않았음. 디폴트 40초로 합니다." ); } } m_timerHeartBeat.Set( secNotResponse ); } } } else ////////////////////////////////////////////////////////////////////////// if( m_modeHeartBeat == xHB_REQUEST ) { // 기다리는중. if( m_timerHeartBeat.IsOver() ) { #if defined(_DEBUG) && !defined(_XNOT_BREAK) m_modeHeartBeat = xHB_READY; m_timerHeartBeat.Off(); // DoDisconnect(); // 디버그 모드에서 끊김 테스트를 위해.. #else // 응답이 없으므로 이 커넥션은 끊는다. #if _DEV_LEVEL <= DLV_DEV_EXTERNAL auto spUser = GetspUser(); if( spUser ) { CONSOLE("응답이 없는 소켓이 발견되어 연결을 끊습니다: ip=%s, idAcc=%d", m_szIP, spUser->GetidUser() ); } else { CONSOLE("응답이 없는 소켓이 발견되어 연결을 끊습니다: %s", m_szIP ); } #endif OnFireConnectBefore(); // 서버에서 자르기 전에 이벤트 핸들러. DoDisconnect(); m_timerHeartBeat.Off(); #endif // not debug } }// else }
void ServoRestyleManager::PostRestyleEvent(Element* aElement, nsRestyleHint aRestyleHint, nsChangeHint aMinChangeHint) { if (MOZ_UNLIKELY(IsDisconnected()) || MOZ_UNLIKELY(PresContext()->PresShell()->IsDestroying())) { return; } if (aRestyleHint == 0 && !aMinChangeHint && !HasPendingRestyles()) { return; // Nothing to do. } // We allow posting change hints during restyling, but not restyle hints // themselves, since those would require us to re-traverse the tree. MOZ_ASSERT_IF(mInStyleRefresh, aRestyleHint == 0); // Processing change hints sometimes causes new change hints to be generated. // Doing this after the gecko post-traversal is problematic, so instead we just // queue them up for special handling. if (mReentrantChanges) { MOZ_ASSERT(aRestyleHint == 0); mReentrantChanges->AppendElement(ReentrantChange { aElement, aMinChangeHint }); return; } // XXX This is a temporary hack to make style attribute change works. // In the future, we should be able to use this hint directly. if (aRestyleHint & eRestyle_StyleAttribute) { aRestyleHint &= ~eRestyle_StyleAttribute; aRestyleHint |= eRestyle_Self | eRestyle_Subtree; } // XXX For now, convert eRestyle_Subtree into (eRestyle_Self | // eRestyle_SomeDescendants), which Servo will interpret as // RESTYLE_SELF | RESTYLE_DESCENDANTS, since this is a commonly // posted restyle hint that doesn't yet align with RestyleHint's // bits. if (aRestyleHint & eRestyle_Subtree) { aRestyleHint &= ~eRestyle_Subtree; aRestyleHint |= eRestyle_Self | eRestyle_SomeDescendants; } if (aRestyleHint || aMinChangeHint) { Servo_NoteExplicitHints(aElement, aRestyleHint, aMinChangeHint); } PostRestyleEventInternal(false); }
// Returns cmd for convenience char GBASockClient::ReceiveCmd(char* data_in, bool block) { if (IsDisconnected()) return data_in[0]; std::size_t num_received = 0; if (block || clock_sync == 0) { sf::SocketSelector Selector; Selector.add(client); Selector.wait(sf::seconds(6)); } if (client.receive(data_in, 5, num_received) == sf::Socket::Disconnected) Disconnect(); return data_in[0]; }
void GBASockClient::ReceiveClock(bool block) { if (IsDisconnected()) return; char sync_ticks[4] = { 0, 0, 0, 0 }; std::size_t num_received = 0; if (clock_client.receive(sync_ticks, 4, num_received) == sf::Socket::Disconnected) Disconnect(); if (num_received == 4) { clock_sync_ticks = 0; for (int i = 0; i < 4; i++) clock_sync_ticks |= (u8)(sync_ticks[i]) << ((3 - i) * 8); clock_sync += clock_sync_ticks; } }
void ServoRestyleManager::PostRestyleEvent(Element* aElement, nsRestyleHint aRestyleHint, nsChangeHint aMinChangeHint) { if (MOZ_UNLIKELY(IsDisconnected()) || MOZ_UNLIKELY(PresContext()->PresShell()->IsDestroying())) { return; } if (aRestyleHint == 0 && !aMinChangeHint && !HasPendingRestyles()) { return; // Nothing to do. } // Note that unlike in Servo, we don't mark elements as dirty until we process // the restyle hints in ProcessPendingRestyles. if (aRestyleHint || aMinChangeHint) { ServoElementSnapshot* snapshot = SnapshotForElement(aElement); snapshot->AddExplicitRestyleHint(aRestyleHint); snapshot->AddExplicitChangeHint(aMinChangeHint); } PostRestyleEventInternal(false); }
void XEWinSocketSvr::ProcessLoginedList() { XVector<XSPWinConnInServer> aryDestroy; auto llMilli1 = GET_FREQ_TIME(); XPROF_OBJ( "listLogined" ); auto plistLogined = &m_Logined.m_shoList.GetSharedObj(); // 동접이 많으면 이 많은 커넥션들 다 패킷펌핑하기전까진 워커스레드 접속스레드 멈춰야 되는데... 이래선 싱글스레드와 다를바 없지 않은가. // 로그인된 커넥션들 프로세스 XINT64 llProcessTotal = 0; XINT64 lllock = 0; // for( auto spConnect : *plistLogined ) { XINT64 llStart = XE::GetFreqTime();; for( auto itor = (*plistLogined).begin(); itor != (*plistLogined).end(); ) { auto spConnect = (*itor); auto pConnect = spConnect.get(); XINT64 lllock1 = XE::GetFreqTime();; if( lllock1 - llStart > 100000 ) // 처리속도가 너무 올래걸릴거 같으면 일단 그냥 루프 빠져나감. break; pConnect->GetspLock()->Lock( __TFUNC__ ); lllock += GET_FREQ_TIME() - lllock1; const int cntUse = spConnect.use_count(); if( XASSERT( pConnect ) ) { if( pConnect->IsDisconnected() ) { OnDisconnectConnection( spConnect ); pConnect->OnDisconnect(); } if( !pConnect->GetbDestroy() ) { auto llProcess = GET_FREQ_TIME(); pConnect->Process(); llProcessTotal += (GET_FREQ_TIME() - llProcess); // if( pConnect->IsDisconnected() ) { // 연결은 끊어졌어도 클라측에서 중요한 패킷을 보냈을수도 있으므로 패킷펌핑은 다 끝내고 삭제하도록 바뀜. pConnect->SetbDestroy( true ); } // 커넥션이 비동기 파괴명령을 처리 pConnect->ProcesssAsyncDisconnect(); } if( pConnect->GetbDestroy() ) { ++m_numDestroyAdd; aryDestroy.Add( spConnect ); plistLogined->erase( itor++ ); } else ++itor; } pConnect->GetspLock()->Unlock(); } auto llPass = GET_FREQ_TIME() - llMilli1; m_aryTime.Add( xProfile(_T("process list"), llPass ) ); m_aryTime.Add( xProfile(_T("process"), llProcessTotal ) ); m_aryTime.Add( xProfile( _T( "lock" ), lllock ) ); m_aryTime.Add( xProfile( _T( "num process" ), plistLogined->size() ) ); // Logined 프로세스 & destroy ////////////////////////////////////////////////////////////////////////// auto pListConnected = &m_Connected.m_shoList.GetSharedObj(); m_numConnected = pListConnected->size(); // 멀티스레드이므로 여기에 값이 있을 수 있음. if( m_numConnected > m_maxConnected ) m_maxConnected = m_numConnected; m_Connected.m_shoList.ReleaseSharedObj(); m_numLogined = plistLogined->size(); if( m_numLogined > m_maxLogined ) m_maxLogined = m_numLogined; // 순간적으로 numConnect수보다 커넥션객체의 생성수가 훨씬 많을때가 있다. // leak으로 보이지만 봇 클라이언트를 종료시키는 순간 모두 사라지는걸로 보아 순간적으로 접속이 몰릴때 메인스레드 프로세스에서 // 다 처리를 못해서 그런듯 하다. // unlock m_Logined.m_shoList.ReleaseSharedObj(); // 삭제예정된 커넥션들 참조해제 ProcessDestroyList( aryDestroy ); aryDestroy.clear(); } // process & destroy
void XEWinSocketSvr::WorkThread() { unsigned long readbytes; unsigned long dwCompKey; // OVERLAPPED * pOverlap; XE::xOVERLAPPED* pOverlap = nullptr; while( 1 ) { // 클라이언트로부터 데이타가 오길 기다림 BOOL bRet = GetQueuedCompletionStatus( m_hIOCP, &readbytes, &dwCompKey, (LPOVERLAPPED*)&pOverlap, INFINITE ); // TODO: #pragma message("리턴값처리 제대로 할것. ") if( bRet == FALSE ) { auto err = GetLastError(); TCHAR* szMsg = nullptr; FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER , nullptr , err , MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT) , (TCHAR*)&szMsg , 0 , nullptr ); if( pOverlap == nullptr ) { return; } else { if( readbytes ) { // 패킷을 dequeue했지만 실패한I/O에 대한 dequeue였다. } else { // 클라이언트 소켓 close } } } else { if( pOverlap == nullptr ) return; } const auto typeEvent = pOverlap->typeEvent; if( bRet == FALSE && pOverlap == nullptr ) { return; } // 어떤 커넥션으로부터 데이타가 도착함. // 어떤 클라이언트 연결로부터 왔는지 알아냄 ID idConnect = (ID)dwCompKey; // 해당 커넥션객체를 찾음. auto spConnect = FindspConnect( idConnect ); // 스레드안전 // if( spConnect ) { XAUTO_LOCK3( spConnect ); // if( readbytes != 0 ) { #if _DEV_LEVEL <= DLV_DEV_EXTERNAL if( spConnect->IsDisconnected() ) { CONSOLE( "connect", "끊어진 소켓에서 IOCP발생" ); } #endif // 받은 데이터를 큐에 밀어넣음 // 접속되고 곧바로 recv가 온다면 커넥션객체에 채 XUser가 붙기도 전에 이게 호출될수도 있음. // 그러므로 그런패킷은 일단 커넥션 큐안에 쌓아둬야 한다. if( !spConnect->IsDisconnected() && !spConnect->IsbDestroy() ) { if( typeEvent == 1 ) { // send의 완료는 따로 처리할것이 없음. // send continue; // spConnect->SendData( ) } else { // recv spConnect->tRecvData( readbytes ); #if _DEV_LEVEL <= DLV_OPEN_BETA const int sizeQ = spConnect->GetSizeQueue(); // 최대 큐크기 표시용 if( sizeQ > m_sizeMaxQ ) m_sizeMaxQ = sizeQ; #endif // 비동기 recv를 큐에 올림 spConnect->tWSARecv(); } } } else { // 접속 끊김 // 서버의 다른데서 소켓닫으면 여기로 들어오나? spConnect->Set_bConnected( FALSE ); // 연결해제 플래그만 켜고 실제 삭제처리는 메인스레드에서. if( bRet && pOverlap == nullptr ) { spConnect->DoDisconnect(); return; } BTRACE( "disconnected:%s", GetszName() ); continue; // 끊긴 커넥션이므로 더이상 처리안해도 된다. } // if( readbytes == 0 ) { // 접속 끊김 } else { #if (_DEV_LEVEL <= DLV_DEV_EXTERNAL) && !defined(_XBOT) CONSOLE( "이미 삭제되거나 없는 연결에서 데이타가 도착했습니다." ); #endif } // if( pConn ) { Sleep( m_msecSleepRecv ); } // while(1) } // WorkThread()