void WatchDirectory(void *thread_data) { // Copy thread inputs to local variables MediaScan *s = ((thread_data_type *)thread_data)->s; LPTSTR lpDir = ((thread_data_type *)thread_data)->lpDir; // Data variables for the windows directory change notification OVERLAPPED oOverlap; FILE_NOTIFY_INFORMATION Buffer[FILE_BUFFER_SZ]; char buf[256]; char full_path[MAX_PATH_STR_LEN]; DWORD BytesReturned; // Overlapped I/O variables WSAOVERLAPPED RecvOverlapped; HANDLE hDir; DWORD dwWaitStatus; DWORD dwBytesRead; BOOL bResult; WSABUF DataBuf; DWORD RecvBytes, Flags; char buffer[DATA_BUFSIZE]; int rc = 0; int err = 0; char *pBase = 0; // Thread state variables int ThreadRunning = TRUE; // Initialize the cache database if (!init_bdb(s)) { MediaScanError *e = error_create("", MS_ERROR_CACHE, "Unable to initialize libmediascan cache"); send_error(s, e); } SecureZeroMemory(buffer, DATA_BUFSIZE); // Make sure the RecvOverlapped struct is zeroed out SecureZeroMemory((PVOID) & oOverlap, sizeof(OVERLAPPED)); // Create the event that will get fired when a directory changes oOverlap.hEvent = CreateEvent(NULL, // default security attributes TRUE, // manual-reset event FALSE, // initial state is nonsignaled TEXT("MyFileChangeEvent")); // "FileChangeEvent" name // Make sure the RecvOverlapped struct is zeroed out SecureZeroMemory((PVOID) & RecvOverlapped, sizeof(WSAOVERLAPPED)); // Create an event handle and setup an overlapped structure. RecvOverlapped.hEvent = WSACreateEvent(); if (RecvOverlapped.hEvent == NULL) { LOG_ERROR("WSACreateEvent failed: %d\n", WSAGetLastError()); return; } DataBuf.len = DATA_BUFSIZE; DataBuf.buf = buffer; // Open the directory that we are going to have windows monitor, note the share modes hDir = CreateFile(lpDir, // pointer to the file name FILE_LIST_DIRECTORY, // access (read/write) mode FILE_SHARE_READ | FILE_SHARE_DELETE | FILE_SHARE_WRITE, // share mode NULL, // security descriptor OPEN_EXISTING, // how to create FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, // file attributes NULL); // file with attributes to copy // Tell windows to monitor the folder asyncroniously using overlapped I/O ReadDirectoryChangesW(hDir, // handle to directory &Buffer, // read results buffer FILE_BUFFER_SZ * sizeof(FILE_NOTIFY_INFORMATION), // length of buffer TRUE, // Monitor sub-directories = TRUE DETECTION_FILTER, // filter conditions &BytesReturned, // bytes returned &oOverlap, // We are using overlapped I/O NULL); // Not using completion routine Flags = 0; /* XXX FIXME, reqpipe is gone rc = WSARecv(s->thread->reqpipe[0], &DataBuf, 1, &RecvBytes, &Flags, &RecvOverlapped, NULL); if ((rc == SOCKET_ERROR) && (WSA_IO_PENDING != (err = WSAGetLastError()))) { LOG_ERROR("WSARecv failed with error: %d\n", err); return; } */ // Run until we are told to stop. It is important to let the thread clean up after itself so // there is shutdown code at the bottom of this function. while (ThreadRunning) { // Set up the events are going to wait for HANDLE event_list[2] = { oOverlap.hEvent, RecvOverlapped.hEvent }; FILE_NOTIFY_INFORMATION *fni; LOG_LEVEL(1, "\nWaiting for notification...\n"); // Wait forever for notification. dwWaitStatus = WaitForMultipleObjects(2, // number of objects in array event_list, // array of objects FALSE, // wait for any object INFINITE); // infinite wait switch (dwWaitStatus) { // This is for the event oOverlap.hEvent case WAIT_OBJECT_0: bResult = GetOverlappedResult(hDir, &oOverlap, &dwBytesRead, TRUE); pBase = (char *)Buffer; do { fni = (FILE_NOTIFY_INFORMATION *) pBase; // Note pRecord->FileName is in UTF-16, have to convert it to 8 bits WideCharToMultiByte(CP_UTF8, 0, fni->FileName, // the string you have fni->FileNameLength / 2, // length of the string buf, // output _countof(buf), // size of the buffer in bytes - if you leave it zero the return value is the length required for the output buffer NULL, NULL); buf[fni->FileNameLength / 2] = 0; // Set up a full path to the file to be scanned and call ms_scan_fileCall scan here with the file changed strcpy(full_path, lpDir); strcat(full_path, "\\"); strcat(full_path, buf); LOG_INFO("Found File Changed: %s", full_path); switch (fni->Action) { case FILE_ACTION_ADDED: LOG_INFO(" file was added\n"); // We get notifications even while a file is being copied. This will wait 60 seconds for the file to finish. if (WaitForFile(full_path, 10)) { ms_scan_file(s, full_path, TYPE_UNKNOWN); } else { LOG_ERROR("A file found by the background scanner never finished copying"); } break; case FILE_ACTION_REMOVED: LOG_INFO(" file was removed\n"); HandleRemovedFile(s, full_path); break; case FILE_ACTION_MODIFIED: LOG_INFO(" file was modified\n"); // This can be a change in the time stamp or attributes."; // We get notifications even while a file is being copied. This will wait 60 seconds for the file to finish. if (WaitForFile(full_path, 10)) { ms_scan_file(s, full_path, TYPE_UNKNOWN); } else { LOG_ERROR("A file found by the background scanner never finished copying"); } break; /* case FILE_ACTION_RENAMED_OLD_NAME: LOG_INFO(" file was renamed and this is the old name\n"); break; case FILE_ACTION_RENAMED_NEW_NAME: LOG_INFO(" file was renamed and this is the new name\n"); break; */ } if (!fni->NextEntryOffset) break; pBase += fni->NextEntryOffset; } while (TRUE); SecureZeroMemory((PVOID) Buffer, sizeof(Buffer)); ReadDirectoryChangesW(hDir, // handle to directory &Buffer, // read results buffer sizeof(Buffer), // length of buffer TRUE, // Monitor sub-directories = TRUE DETECTION_FILTER, // filter conditions &BytesReturned, // bytes returned &oOverlap, // We are using overlapped I/O NULL); // Not using completion routine break; /* WAIT_OBJECT_0: */ // This is for the event s->ghSignalEvent case WAIT_OBJECT_0 + 1: ThreadRunning = FALSE; break; /* WAIT_OBJECT_0 + 1: */ case WAIT_TIMEOUT: // A timeout occurred, this would happen if some value other // than INFINITE is used in the Wait call and no changes occur. // In a single-threaded environment you might not want an // INFINITE wait. LOG_INFO("\nNo changes in the timeout period.\n"); break; default: LOG_ERROR("\n ERROR: Unhandled dwWaitStatus.\n"); ExitThread(GetLastError()); break; } } // Free the data that was passed to this thread on the heap if (thread_data != NULL) { free(thread_data); thread_data = NULL; // Ensure address is not reused. } CancelIo(hDir); if (!HasOverlappedIoCompleted(&oOverlap)) { SleepEx(5, TRUE); } WSACloseEvent(RecvOverlapped.hEvent); CloseHandle(oOverlap.hEvent); ExitThread(GetLastError()); } /* WatchDirectory() */
u8 rtw_set_802_11_connect(_adapter* padapter, const u8 *bssid, NDIS_802_11_SSID *ssid) { _irqL irqL; u8 status = _SUCCESS; u32 cur_time = 0; bool bssid_valid = _TRUE; bool ssid_valid = _TRUE; struct mlme_priv *pmlmepriv = &padapter->mlmepriv; _func_enter_; if (!ssid || rtw_validate_ssid(ssid) == _FALSE) ssid_valid = _FALSE; if (!bssid || rtw_validate_bssid(bssid) == _FALSE) bssid_valid = _FALSE; if (ssid_valid == _FALSE && bssid_valid == _FALSE) { DBG_871X(FUNC_ADPT_FMT" ssid:%p, ssid_valid:%d, bssid:%p, bssid_valid:%d\n", FUNC_ADPT_ARG(padapter), ssid, ssid_valid, bssid, bssid_valid); status = _FAIL; goto exit; } if(padapter->hw_init_completed==_FALSE){ RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("set_ssid: hw_init_completed==_FALSE=>exit!!!\n")); status = _FAIL; goto exit; } _enter_critical_bh(&pmlmepriv->lock, &irqL); LOG_LEVEL(_drv_info_, FUNC_ADPT_FMT" fw_state=0x%08x\n", FUNC_ADPT_ARG(padapter), get_fwstate(pmlmepriv)); if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == _TRUE) { goto handle_tkip_countermeasure; } else if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == _TRUE) { goto release_mlme_lock; } handle_tkip_countermeasure: if (rtw_handle_tkip_countermeasure(padapter, __func__) == _FAIL) { status = _FAIL; goto release_mlme_lock; } if (ssid && ssid_valid) _rtw_memcpy(&pmlmepriv->assoc_ssid, ssid, sizeof(NDIS_802_11_SSID)); if (bssid && bssid_valid) { _rtw_memcpy(&pmlmepriv->assoc_bssid, bssid, ETH_ALEN); pmlmepriv->assoc_by_bssid = _TRUE; } if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == _TRUE) { pmlmepriv->to_join = _TRUE; } else { status = rtw_do_join(padapter); } release_mlme_lock: _exit_critical_bh(&pmlmepriv->lock, &irqL); exit: _func_exit_; return status; }
int APIENTRY WinMain(HINSTANCE hThisInst, HINSTANCE hPrevInst, LPSTR str, int nWinMode){ LOG_PREFIX("logs\\clientLog"); LOG_LEVEL(logger::Debug); // уровень лога в рантайме (например, берём из командной строки) LOG_DEBUG << "WinMain starting.."; Scene=0; hDC=0; int full=0; int WindowX=0; int WindowY=0; int Width=800; int Height=600; full = GetPrivateProfileIntA("Options", "FullScreenEnable", 0, "Data/graph.ini"); WindowX = GetPrivateProfileIntA("Options", "WindowX", 0, "Data/graph.ini"); WindowY = GetPrivateProfileIntA("Options", "WindowY", 0, "Data/graph.ini"); Width = GetPrivateProfileIntA("Options", "Width", 800, "Data/graph.ini"); Height = GetPrivateProfileIntA("Options", "Height", 600, "Data/graph.ini"); Scene = new TScene(); if ( full == 0 ){ WNDCLASSA wcl; wcl.hInstance = hThisInst; wcl.lpszClassName = "OpenGLWinClass"; wcl.lpfnWndProc = WindowFunc; wcl.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW; wcl.hIcon = NULL; wcl.hCursor = LoadCursor(NULL,IDC_ARROW); wcl.lpszMenuName = NULL; wcl.cbClsExtra = 0; wcl.cbWndExtra = 0; wcl.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); // RegisterClassA(&wcl); if ( !RegisterClassA(&wcl) ) return -1;//throw "RegisterClass"; hWnd = CreateWindowA("OpenGLWinClass", "Elt",WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, WindowX, WindowY, Width, Height, NULL, NULL, hThisInst, NULL); ShowWindow(hWnd, SW_SHOWNORMAL); UpdateWindow(hWnd); } if ( full == 1 ){ DEVMODE ss; WNDCLASSA wcl; memset(&ss, 0, sizeof(ss) ); ss.dmSize = sizeof(ss); ss.dmPelsWidth = Width; ss.dmPelsHeight = Height; ss.dmBitsPerPel = 32; ss.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT; if (ChangeDisplaySettings(&ss, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL) MessageBoxA(NULL, "Ошибка в ChangeDisplaySettings", "Error", MB_OK | MB_ICONSTOP); memset(&wcl, 0, sizeof(wcl) ); wcl.lpfnWndProc = (WNDPROC)WindowFunc; wcl.hInstance = hThisInst; wcl.hIcon = LoadIcon(NULL, IDI_APPLICATION); wcl.hCursor = LoadCursor(NULL, IDC_ARROW); wcl.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wcl.lpszClassName = "OpenGLWinClass"; if ( !RegisterClassA(&wcl) ) return -1;//throw "RegisterClass"; hWnd = CreateWindowA("OpenGLWinClass", "Elt", WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, 0, 0, Width, Height, NULL, NULL, hThisInst, NULL); if ( !hWnd ) return -1;//throw "CreateWindow"; SetWindowPos( hWnd, HWND_TOPMOST, 0, 0, 0, 0, 1 ); ShowWindow(hWnd, SW_SHOWMAXIMIZED); } MSG msg; LOG_DEBUG << "WinMain started end"; LOG_DEBUG << "World Init..."; World->Init(); LOG_DEBUG << "...End World Init"; //---network init LOG_DEBUG << "netClient.Init()"; netClient.Init(World); //World->SetNetStatData(&netClient.mNetStat); netClient.SetTimeBetweenPacketsSend(500); LOG_DEBUG << "netClient.Run()"; netClient.Run(); //--------------- tTick gTick; gTick.Init(20);//50 раз в сек LOG_DEBUG << "Start Main loop"; do{ if(PeekMessage( &msg, NULL, 0, 0, PM_REMOVE )) { if( msg.message == WM_QUIT ) break; TranslateMessage( &msg ); DispatchMessage ( &msg ); } World->CDM(); // Center of Decision Making (Graphics + Logic) gTick.Wait();//Зачем ждать? Перести в World->CDM() и если рано - не ждать а выходить }while(!bGameOver); LOG_DEBUG << "End Main loop"; LOG_DEBUG << "World->Destroy()"; World->Destroy(); //---network release LOG_DEBUG << "netClient.Stop()"; netClient.Stop(); LOG_DEBUG << "netClient.Release()"; netClient.Release(); //---------- if (Scene) delete Scene; LOG_DEBUG << "Scene deleted"; LOG_DEBUG << "World destroy"; DestroyWindow(hWnd); LOG_DEBUG << "Windows destroy"; if ( full == 1 ) ChangeDisplaySettings(NULL, 0); LOG_DEBUG << "EXIT"; return 0; }
int main( int argc, char *argv[] ) { tf::options o; o.register_option(tf::option("help", "Displays help", false, false, "help", 'h')); o.register_option(tf::option("config", "Configuration file to load", true, false, "config", 'c')); o.register_option(tf::option("loglevel", "Logging level (DEBUG, INFO, WARNING, ERROR)", false, true, "loglevel", 'l')); o.register_option(tf::option("interface", "Interface to bind to", false, true, "interface", 'i')); o.register_option(tf::option("service", "Service to process", true, true, "service", 's')); o.register_option(tf::option("nobanner", "Don't display startup banner", false, false, "nobanner", 'x')); o.register_option(tf::option("daemon", "Run in daemon mode", false, false, "daemon", 'd')); try { o.parse(argc, argv); } catch (const tf::option_exception &e) { ERROR_LOG(e.what()); o.printUsage(); return 1; } std::string loglevel; if (o.get("loglevel", loglevel)) { if (loglevel == "DEBUG") { LOG_LEVEL(tf::logger::debug); } else if (loglevel == "INFO") { LOG_LEVEL(tf::logger::info); } else if (loglevel == "WARNING") { LOG_LEVEL(tf::logger::warning); } else if (loglevel == "ERROR") { LOG_LEVEL(tf::logger::error); } else { ERROR_LOG("Invalid log level"); return 1; } } else { LOG_LEVEL(tf::logger::warning); } LOG_THREADS(true); if (!o.get("nobanner", false)) { char output[1024]; sprintf(output, banner, PROJECT_VERSION, 2016); tf::logger::instance().log(tf::logger::info, output); } std::string configFile; o.get("config", configFile); DEBUG_LOG("Using config file '" << configFile << "'"); if (o.get("daemon", false)) { tf::run_as_daemon(); } try { const std::string interface = o.getWithDefault("interface", "0.0.0.0"); const std::string service = o.getWithDefault("service", "7900"); fp::bootstrap engine(interface, service); engine.run(); } catch (const std::exception &stde) { ERROR_LOG("Internal error: " << stde.what()); return 1; } }
int main( int argc, char *argv[] ) { tf::options o; o.register_option(tf::option("help", "Displays help", false, false, "help", 'h')); o.register_option(tf::option("loglevel", "Logging level (DEBUG, INFO, WARNING, ERROR)", false, true, "loglevel", 'l')); o.register_option(tf::option("url", "URL to connect to", true, true, "url", 'u')); o.register_option(tf::option("subject", "Subject to user", true, true, "subject", 's')); try { o.parse(argc, argv); } catch (const tf::option_exception &e) { ERROR_LOG(e.what()); o.printUsage(); return 1; } std::string loglevel; if (o.get("loglevel", loglevel)) { if (loglevel == "DEBUG") { LOG_LEVEL(tf::logger::debug); } else if (loglevel == "INFO") { LOG_LEVEL(tf::logger::info); } else if (loglevel == "WARNING") { LOG_LEVEL(tf::logger::warning); } else if (loglevel == "ERROR") { LOG_LEVEL(tf::logger::error); } else { ERROR_LOG("Invalid log level"); return 1; } } else { LOG_LEVEL(tf::logger::warning); } try { fp::Session::initialise(); const std::string url = o.getWithDefault("url", ""); std::string subject; if (!o.get("subject", subject)) { ERROR_LOG("You must specify a subject"); } fp::BlockingQueue queue; auto transport = fp::make_realm_connection(url.c_str(), ""); const fp::Subscriber subscriber(transport, subject.c_str(), [&](const fp::Subscriber *event, const fp::Message *msg) noexcept { INFO_LOG(*msg); }); queue.addSubscriber(subscriber); bool shutdown = false; auto terminate = [&](const fp::SignalEvent *event, const int signal) noexcept { INFO_LOG("Shutdown signal caught..."); shutdown = true; }; auto sigint_handler = queue.registerEvent(SIGINT, terminate); auto sigterm_handler = queue.registerEvent(SIGTERM, terminate); while (!shutdown) { queue.dispatch(); } queue.unregisterEvent(sigint_handler); queue.unregisterEvent(sigterm_handler); queue.removeSubscriber(subscriber); fp::Session::destroy(); } catch (const std::exception &stde) { ERROR_LOG("Internal error: " << stde.what()); return 1; } }
shared_ptr<OGRSpatialReference> MapReprojector::createPlanarProjection(const OGREnvelope& env, Radians maxAngleError, Meters maxDistanceError, Meters testDistance, bool warnOnFail) { vector< shared_ptr<OGRSpatialReference> > projs = createAllPlanarProjections(env); QString deg = QChar(0x00B0); if (projs.size() == 0) { throw HootException("No candidate planar projections are available."); } vector<PlanarTestResult> testResults; vector<PlanarTestResult> passingResults; // if the envelope has zero size then return an orthographic projection. if (env.MaxX == env.MinX || env.MaxY == env.MinY) { return createOrthographic(env); } for (size_t i = 0; i < projs.size(); ++i) { PlanarTestResult tr; tr.i = i; if (_evaluateProjection(env, projs[i], testDistance, tr.distanceError, tr.angleError)) { // create a score that is weighted by the user's threshold values. tr.score = tr.distanceError / maxDistanceError + tr.angleError / maxAngleError; testResults.push_back(tr); if (tr.distanceError <= maxDistanceError && tr.angleError <= maxAngleError) { passingResults.push_back(tr); } } else { tr.distanceError = numeric_limits<double>::max(); tr.angleError = numeric_limits<double>::max(); tr.score = numeric_limits<double>::max(); testResults.push_back(tr); } //LOG_INFO("dis: " << tr.distanceError << "m angle: " << toDegrees(tr.angleError) << deg); } // |<--- 80 cols -->| QString errorMessage = "A projection within the specified error bounds could not be found. This is " "likely due to a very large bounds on the data. Please read " "'Hootenanny - Distance and Angle Errors Due to Reprojection' for more " "information. You may experience poor conflation performance as a result."; int bestIndex = -1; Log::WarningLevel level = Log::Debug; if (passingResults.size() > 0) { bestIndex = _findBestScore(passingResults); char* wkt = 0; projs[bestIndex]->exportToWkt(&wkt); LOG_DEBUG("Projection: " << wkt) OGRFree(wkt); } else if (warnOnFail == false) { level = Log::Warn; } else if (testResults.size() > 0) { LOG_WARN(errorMessage); bestIndex = _findBestScore(testResults); level = Log::Info; } LOG_LEVEL(level, "Planar projection has max distance error " << fixed << setprecision(2) << testResults[bestIndex].distanceError << "m " << "(" << testResults[bestIndex].distanceError / testDistance * 100.0 << "%) " << "and max angular error: " << toDegrees(testResults[bestIndex].angleError) << deg << " test distance: " << testDistance << "m"); LOG_LEVEL(level, "Projection: " << toWkt(projs[bestIndex])); if (bestIndex == -1) { throw HootException(errorMessage); } return projs[bestIndex]; }
int main( int argc, char *argv[] ) { tf::options o; o.register_option(tf::option("help", "Displays help", false, false, "help", 'h')); o.register_option(tf::option("loglevel", "Logging level (DEBUG, INFO, WARNING, ERROR)", false, true, "loglevel", 'l')); o.register_option(tf::option("url", "URL to connect to", true, true, "url", 'u')); o.register_option(tf::option("rate", "Sending message rate", false, true, "rate", 'r')); o.register_option(tf::option("count", "Number of messages to send", false, true, "count", 'c')); try { o.parse(argc, argv); } catch (const tf::option_exception &e) { ERROR_LOG(e.what()); o.printUsage(); return 1; } std::string loglevel; if (o.get("loglevel", loglevel)) { if (loglevel == "DEBUG") { LOG_LEVEL(tf::logger::debug); } else if (loglevel == "INFO") { LOG_LEVEL(tf::logger::info); } else if (loglevel == "WARNING") { LOG_LEVEL(tf::logger::warning); } else if (loglevel == "ERROR") { LOG_LEVEL(tf::logger::error); } else { ERROR_LOG("Invalid log level"); return 1; } } else { LOG_LEVEL(tf::logger::warning); } const size_t count = o.get("count", 1000ul); const size_t rate = o.get("rate", 100ul); try { using TimeType = std::chrono::high_resolution_clock::time_point; using ResultsType = std::pair<TimeType, TimeType>; std::vector<ResultsType> m_times(count); fp::Session::initialise(); if (std::thread::hardware_concurrency() >= 4) { fp::Session::assign_to_cpu({2, 3}); } else if (std::thread::hardware_concurrency() >= 2) { fp::Session::assign_to_cpu({0, 1}); } const std::string url = o.getWithDefault("url", ""); fp::BlockingQueue queue; auto transport = fp::make_realm_connection(url.c_str(), ""); if (!transport->valid()) { ERROR_LOG("Failed to create transport"); return 1; } uint32_t id = 0; bool shutdown = false; fp::MutableMessage sendMsg; sendMsg.setSubject("TEST.PERF.SOURCE"); sendMsg.addScalarField("id", id); auto duration = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::microseconds(1000000) / rate); INFO_LOG("Sending a message every " << duration.count() << " us"); queue.registerEvent(duration, [&](fp::TimerEvent *event) noexcept { if (id < count) { sendMsg.clear(); sendMsg.setSubject("TEST.PERF.SOURCE"); sendMsg.addScalarField("id", id); m_times[id].first = std::chrono::high_resolution_clock::now(); if (transport->sendMessage(sendMsg) == fp::OK) { DEBUG_LOG("Message send successfully: " << sendMsg); } else { ERROR_LOG("Failed to send message"); exit(1); } id++; } }); fp::Subscriber subscriber(transport, "TEST.PERF.SINK", [&](const fp::Subscriber *event, const fp::Message *recvMsg) noexcept { DEBUG_LOG("Received message from sink: " << *recvMsg); // std::chrono::high_resolution_clock::time_point t = std::chrono::high_resolution_clock::now(); uint32_t recv_id = 0; if (recvMsg->getScalarField("id", recv_id)) { DEBUG_LOG("Processing message: " << recv_id); uint64_t ts = 0; if (recvMsg->getScalarField("timestamp", ts)) { std::chrono::microseconds dur(ts); std::chrono::time_point<std::chrono::high_resolution_clock> t(dur); m_times[recv_id].second = t; } } if (recv_id >= count - 1) { shutdown = true; } }); queue.addSubscriber(subscriber); while (!shutdown) { queue.dispatch(); } fp::Session::destroy(); std::vector<std::chrono::microseconds> latencies; latencies.reserve(count); std::transform(m_times.begin(), m_times.end(), std::back_inserter(latencies), [&](auto &result) { return std::chrono::duration_cast<std::chrono::microseconds>(result.second - result.first); }); std::future<double> avg = std::async(std::launch::async, [&latencies]() { uint64_t total = 0; std::for_each(latencies.begin(), latencies.end(), [&total](auto &v) { total += v.count(); }); return static_cast<double>(total) / latencies.size(); }); std::future<std::chrono::microseconds> min = std::async(std::launch::async, [&latencies]() { return *std::min_element(latencies.begin(), latencies.end()); }); std::future<std::chrono::microseconds> max = std::async(std::launch::async, [&latencies]() { return *std::max_element(latencies.begin(), latencies.end()); }); auto find_p = [&](size_t p) { size_t index = std::floor((static_cast<double>(100 - p) / 100.0) * latencies.size()); std::nth_element(latencies.begin(), latencies.begin() + index, latencies.end(), std::greater<std::chrono::microseconds>()); return latencies[index]; }; std::future<std::chrono::microseconds> p99 = std::async(std::launch::async, std::bind(find_p, 95)); std::future<std::chrono::microseconds> p90 = std::async(std::launch::async, std::bind(find_p, 90)); std::future<std::chrono::microseconds> p50 = std::async(std::launch::async, std::bind(find_p, 50)); INFO_LOG("Avg round trip: " << avg.get() << " us"); INFO_LOG("Min round trip: " << min.get().count() << " us"); INFO_LOG("Max round trip: " << max.get().count() << " us"); INFO_LOG("P99 round trip: " << p99.get().count() << " us"); INFO_LOG("P90 round trip: " << p90.get().count() << " us"); INFO_LOG("P50 round trip: " << p50.get().count() << " us"); } catch (const std::exception &stde) { ERROR_LOG("Internal error: " << stde.what()); return 1; } }