/* * SRT - Secure, Reliable, Transport * Copyright (c) 2019 Haivision Systems Inc. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * */ #include "platform_sys.h" #include #include #include #include "sync.h" #include "srt.h" #include "hvu_compat.h" #include "hvu_threadname.h" #include "logging.h" #include "logger_fas.h" #include "common.h" // HAVE_CXX11 is defined in utilities.h, included with common.h. // The following conditional inclusion must go after common.h. #if HAVE_CXX11 #include // This condition is defined in the Linux manpage for rand_r #elif _POSIX_C_SOURCE >= 1 || _XOPEN_SOURCE || _POSIX_SOURCE #define SRT_HAVE_RAND_R 1 #else #define SRT_HAVE_RAND_R 0 #endif // IMPORTANT NOTE on the thread-safe initialization of static local variables: // 1. C++11 guarantees thread-safe deadlock-free initialization // 2. C++03 STANDARD doesn't give such a guarantee, however compilers do: // - gcc, clang, Intel: Implemented and turned on by default, unless // overridden by -fno-threadsafe-statics; gcc supports it since version 4.0 // released in 2005 // - Microsoft Visual Studio: this is supported since VS 2019 // // Therefore this code relies everywhere on that the static locals are initialized // safely in the multithreaded environment and pthread_once() is not in use. using namespace srt::logging; using namespace std; namespace srt { namespace sync { std::string FormatTime(const steady_clock::time_point& timestamp) { using namespace hvu; if (is_zero(timestamp)) { // Use special string for 0 return "00:00:00.000000 [STDY]"; } const int decimals = clockSubsecondPrecision(); const uint64_t total_sec = count_seconds(timestamp.time_since_epoch()); const uint64_t days = total_sec / (60 * 60 * 24); const uint64_t hours = total_sec / (60 * 60) - days * 24; const uint64_t minutes = total_sec / 60 - (days * 24 * 60) - hours * 60; const uint64_t seconds = total_sec - (days * 24 * 60 * 60) - hours * 60 * 60 - minutes * 60; steady_clock::time_point frac = timestamp - seconds_from(total_sec); ofmtbufstream out; if (days) out << days << OFMT_RAWSTR("D "); fmtc d02 = fmtc().dec().fillzero().width(2), dec0 = fmtc().dec().fillzero().width(decimals); out << fmt(hours, d02) << OFMT_RAWSTR(":") << fmt(minutes, d02) << OFMT_RAWSTR(":") << fmt(seconds, d02) << OFMT_RAWSTR(".") << fmt(frac.time_since_epoch().count(), dec0) << OFMT_RAWSTR(" [STDY]"); return out.str(); } std::string FormatTimeSys(const steady_clock::time_point& timestamp) { using namespace hvu; const time_t now_s = ::time(NULL); // get current time in seconds const steady_clock::time_point now_timestamp = steady_clock::now(); const int64_t delta_us = count_microseconds(timestamp - now_timestamp); const int64_t delta_s = static_cast(floor((static_cast(count_microseconds(now_timestamp.time_since_epoch()) % 1000000) + delta_us) / 1000000.0)); const time_t tt = now_s + delta_s; struct tm tm = SysLocalTime(tt); // in seconds char tmp_buf[512]; size_t tmp_size = strftime(tmp_buf, 512, "%X.", &tm); // Mind the theoretically possible error case if (!tmp_size) return "