ezResult ezTaskSystem::CancelTask(ezTask* pTask, ezOnTaskRunning::Enum OnTaskRunning) { if (pTask->IsTaskFinished()) return EZ_SUCCESS; EZ_PROFILE_SCOPE("CancelTask"); EZ_ASSERT_DEV(pTask->m_BelongsToGroup.m_pTaskGroup->m_uiGroupCounter == pTask->m_BelongsToGroup.m_uiGroupCounter, "The task to be removed is in an invalid group."); // we set the cancel flag, to make sure that tasks that support canceling will terminate asap pTask->m_bCancelExecution = true; { EZ_LOCK(s_TaskSystemMutex); // if the task is still in the queue of its group, it had not yet been scheduled if (!pTask->m_bTaskIsScheduled && pTask->m_BelongsToGroup.m_pTaskGroup->m_Tasks.RemoveAndSwap(pTask)) { // we set the task to finished, even though it was not executed pTask->m_bIsFinished = true; return EZ_SUCCESS; } // check if the task has already been scheduled for execution // if so, remove it from the work queue { for (ezUInt32 i = 0; i < ezTaskPriority::ENUM_COUNT; ++i) { auto it = s_Tasks[i].GetIterator(); while (it.IsValid()) { if (it->m_pTask == pTask) { s_Tasks[i].Remove(it); // we set the task to finished, even though it was not executed pTask->m_bIsFinished = true; // tell the system that one task of that group is 'finished', to ensure its dependencies will get scheduled TaskHasFinished(it->m_pTask, it->m_pBelongsToGroup); return EZ_SUCCESS; } ++it; } } } } // if we made it here, the task was already running // thus we just wait for it to finish if (OnTaskRunning == ezOnTaskRunning::WaitTillFinished) WaitForTask(pTask); return EZ_FAILURE; }
void MumbleClient::ThreadFuncImpl() { SetThreadName(-1, "[Mumble] Network Thread"); while (true) { ClientTask task = WaitForTask(); try { switch (task) { case ClientTask::BeginConnect: { const auto& address = m_connectionInfo.address; m_socket = socket(address.GetAddressFamily(), SOCK_STREAM, IPPROTO_TCP); int on = 1; setsockopt(m_socket, IPPROTO_TCP, TCP_NODELAY, (char*)&on, sizeof(on)); m_socketConnectEvent = WSACreateEvent(); m_socketReadEvent = WSACreateEvent(); WSAEventSelect(m_socket, m_socketConnectEvent, FD_CONNECT); u_long nonBlocking = 1; ioctlsocket(m_socket, FIONBIO, &nonBlocking); connect(m_socket, address.GetSocketAddress(), address.GetSocketAddressLength()); trace("[mumble] connecting to %s...\n", address.ToString()); break; } case ClientTask::EndConnect: { WSANETWORKEVENTS events = { 0 }; WSAEnumNetworkEvents(m_socket, m_socketConnectEvent, &events); if (events.iErrorCode[FD_CONNECT_BIT]) { // TODO: reconnecting? trace("[mumble] connecting failed: %d\n", events.iErrorCode[FD_CONNECT_BIT]); m_completionEvent.set_exception(std::runtime_error("Failed Mumble connection.")); break; } WSACloseEvent(m_socketConnectEvent); m_socketConnectEvent = INVALID_HANDLE_VALUE; LARGE_INTEGER waitTime; waitTime.QuadPart = -20000000LL; SetWaitableTimer(m_idleEvent, &waitTime, 0, nullptr, nullptr, 0); m_handler.Reset(); WSAEventSelect(m_socket, m_socketReadEvent, FD_READ); m_sessionManager = std::make_unique<Botan::TLS::Session_Manager_In_Memory>(m_rng); m_credentials = std::make_unique<MumbleCredentialsManager>(); m_tlsClient = std::make_shared<Botan::TLS::Client>(*this, *(m_sessionManager.get()), *(m_credentials.get()), m_policy, m_rng, Botan::TLS::Server_Information() ); m_connectionInfo.isConnected = true; break; } case ClientTask::Idle: { if (m_tlsClient->is_active() && m_connectionInfo.isConnected) { MumbleProto::Ping ping; ping.set_timestamp(msec().count()); ping.set_tcp_ping_avg(m_tcpPingAverage); ping.set_tcp_ping_var(m_tcpPingVariance); ping.set_tcp_packets(m_tcpPingCount); Send(MumbleMessageType::Ping, ping); LARGE_INTEGER waitTime; waitTime.QuadPart = -50000000LL; SetWaitableTimer(m_idleEvent, &waitTime, 0, nullptr, nullptr, 0); } break; } case ClientTask::RecvData: { WSANETWORKEVENTS ne; WSAEnumNetworkEvents(m_socket, m_socketReadEvent, &ne); uint8_t buffer[16384]; int len = recv(m_socket, (char*)buffer, sizeof(buffer), 0); if (len > 0) { std::unique_lock<std::recursive_mutex> lock(m_clientMutex); m_tlsClient->received_data(buffer, len); } else if (len == 0) { // TCP close, graceful? trace("[mumble] tcp close :(\n"); } else { if (WSAGetLastError() != WSAEWOULDBLOCK) { // TCP close, error state trace("[mumble] tcp error :(\n"); } } break; } } } catch (std::exception& e) { trace("lolexception %s", e.what()); } } }