Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding SRT build option for building with C++11 chrono and threads #1266

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ option(USE_STATIC_LIBSTDCXX "Should use static rather than shared libstdc++" OFF
option(ENABLE_INET_PTON "Set to OFF to prevent usage of inet_pton when building against modern SDKs while still requiring compatibility with older Windows versions, such as Windows XP, Windows Server 2003 etc." ON)
option(ENABLE_CODE_COVERAGE "Enable code coverage reporting" OFF)
option(ENABLE_MONOTONIC_CLOCK "Enforced clock_gettime with monotonic clock on GC CV /temporary fix for #729/" OFF)
option(ENABLE_STDCXX_SYNC "Use C++11 chrono and threads for timing instead of pthreads" OFF)
option(USE_OPENSSL_PC "Use pkg-config to find OpenSSL libraries" ON)
option(USE_BUSY_WAITING "Enable more accurate sending times at a cost of potentially higher CPU load" OFF)
option(USE_GNUSTL "Get c++ library/headers from the gnustl.pc" OFF)
Expand Down Expand Up @@ -315,15 +316,15 @@ else()
message(STATUS "ENCRYPTION: DISABLED")
endif()

if ( USE_GNUSTL )
if (USE_GNUSTL)
pkg_check_modules (GNUSTL REQUIRED gnustl)
link_directories(${GNUSTL_LIBRARY_DIRS})
include_directories(${GNUSTL_INCLUDE_DIRS})
set (SRT_LIBS_PRIVATE ${SRT_LIBS_PRIVATE} ${GNUSTL_LIBRARIES} ${GNUSTL_LDFLAGS})
endif()

# Detect if the compiler is GNU compatable for flags
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Intel|Clang|AppleClang")
if (CMAKE_CXX_COMPILER_ID MATCHES "GNU|Intel|Clang|AppleClang")
message(STATUS "COMPILER: ${CMAKE_CXX_COMPILER_ID} (${CMAKE_CXX_COMPILER}) - GNU compat")
set(HAVE_COMPILER_GNU_COMPAT 1)
else()
Expand All @@ -340,7 +341,14 @@ endif()

if (NOT ENABLE_CXX11)
message(WARNING "Parts that require C++11 support will be disabled (srt-live-transmit)")
if (ENABLE_STDCXX_SYNC)
message(ERROR "ENABLE_STDCXX_SYNC is set, but C++11 is disabled by ENABLE_CXX11")
endif()
elseif (ENABLE_STDCXX_SYNC)
add_definitions(-DENABLE_STDCXX_SYNC=1)
set(CMAKE_CXX_STANDARD 11)
endif()
message(STATUS "STDCXX_SYNC: ${ENABLE_STDCXX_SYNC}")

# add extra warning flags for gccish compilers
if (HAVE_COMPILER_GNU_COMPAT)
Expand Down
2 changes: 1 addition & 1 deletion srtcore/core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6635,7 +6635,7 @@ int CUDT::sendmsg2(const char *data, int len, SRT_MSGCTRL& w_mctrl)

int32_t seqno = m_iSndNextSeqNo;
IF_HEAVY_LOGGING(int32_t orig_seqno = seqno);
IF_HEAVY_LOGGING(steady_clock::time_point ts_srctime = steady_clock::time_point(w_mctrl.srctime));
IF_HEAVY_LOGGING(steady_clock::time_point ts_srctime = steady_clock::time_point() + microseconds_from(w_mctrl.srctime));

// Check if seqno has been set, in case when this is a group sender.
// If the sequence is from the past towards the "next sequence",
Expand Down
37 changes: 28 additions & 9 deletions srtcore/sync.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ namespace srt_logging
}
using namespace srt_logging;

#if !defined(ENABLE_STDCXX_SYNC)
namespace srt
{
namespace sync
Expand Down Expand Up @@ -117,6 +118,7 @@ const int64_t s_cpu_frequency = get_cpu_frequency();

} // namespace sync
} // namespace srt
#endif // #if !defined(ENABLE_STDCXX_SYNC)

////////////////////////////////////////////////////////////////////////////////
//
Expand All @@ -137,6 +139,7 @@ static timespec us_to_timespec(const uint64_t time_us)
// TimePoint section
//
////////////////////////////////////////////////////////////////////////////////
#ifndef ENABLE_STDCXX_SYNC

template <>
srt::sync::Duration<srt::sync::steady_clock> srt::sync::TimePoint<srt::sync::steady_clock>::time_since_epoch() const
Expand Down Expand Up @@ -181,6 +184,8 @@ srt::sync::steady_clock::duration srt::sync::seconds_from(int64_t t_s)
return steady_clock::duration((1000000 * t_s) * s_cpu_frequency);
}

#endif // !defined(ENABLE_STDCXX_SYNC)

std::string srt::sync::FormatTime(const steady_clock::time_point& timestamp)
{
if (is_zero(timestamp))
Expand Down Expand Up @@ -226,6 +231,7 @@ std::string srt::sync::FormatTimeSys(const steady_clock::time_point& timestamp)
return out.str();
}

#if !defined(ENABLE_STDCXX_SYNC)
srt::sync::Mutex::Mutex()
{
pthread_mutex_init(&m_mutex, NULL);
Expand Down Expand Up @@ -262,9 +268,12 @@ srt::sync::ScopedLock::~ScopedLock()
m_mutex.unlock();
}

#endif // !defined(ENABLE_STDCXX_SYNC)

//
//
//
#if !defined(ENABLE_STDCXX_SYNC)

srt::sync::UniqueLock::UniqueLock(Mutex& m)
: m_Mutex(m)
Expand All @@ -290,13 +299,14 @@ srt::sync::Mutex* srt::sync::UniqueLock::mutex()
{
return &m_Mutex;
}
#endif // !defined(ENABLE_STDCXX_SYNC)

////////////////////////////////////////////////////////////////////////////////
//
// Condition section (based on pthreads)
//
////////////////////////////////////////////////////////////////////////////////
#ifndef USE_STDCXX_CHRONO
#ifndef ENABLE_STDCXX_SYNC

namespace srt
{
Expand Down Expand Up @@ -376,7 +386,7 @@ void Condition::notify_all()
}; // namespace sync
}; // namespace srt

#endif // ndef USE_STDCXX_CHRONO
#endif // ndef ENABLE_STDCXX_SYNC

////////////////////////////////////////////////////////////////////////////////
//
Expand Down Expand Up @@ -552,7 +562,7 @@ bool srt::sync::CGlobEvent::waitForEvent()
// CThread class
//
////////////////////////////////////////////////////////////////////////////////
#ifndef USE_STDCXX_CHRONO
#ifndef ENABLE_STDCXX_SYNC

srt::sync::CThread::CThread()
{
Expand Down Expand Up @@ -634,17 +644,21 @@ void srt::sync::CThread::create(void *(*start_routine) (void *), void *arg)
}
}

#ifdef USE_STDCXX_CHRONO
template< class Function >
bool srt::sync::StartThread(CThread& th, Function&& f, void* args, const char* name)
#endif // !defined(ENABLE_STDCXX_SYNC)

namespace srt {
namespace sync {

#ifdef ENABLE_STDCXX_SYNC
bool StartThread(CThread& th, ThreadFunc&& f, void* args, const char* name)
#else
bool srt::sync::StartThread(CThread& th, void* (*f) (void*), void* args, const char* name)
bool StartThread(CThread& th, void* (*f) (void*), void* args, const char* name)
#endif
{
ThreadName tn(name);
try
{
#if HAVE_FULL_CXX11 || defined(USE_STDCXX_CHRONO)
#if HAVE_FULL_CXX11 || defined(ENABLE_STDCXX_SYNC)
th = CThread(f, args);
#else
// No move semantics in C++03, therefore using a dedicated function
Expand All @@ -659,11 +673,16 @@ bool srt::sync::StartThread(CThread& th, void* (*f) (void*), void* args, const c
return true;
}

} // namespace sync
} // namespace srt


////////////////////////////////////////////////////////////////////////////////
//
// CThreadError class - thread local storage error wrapper
//
////////////////////////////////////////////////////////////////////////////////
#if !defined(ENABLE_STDCXX_SYNC)
namespace srt {
namespace sync {

Expand Down Expand Up @@ -726,4 +745,4 @@ CUDTException& GetThreadLocalError()
} // namespace sync
} // namespace srt

#endif // !defined(USE_STDCXX_CHRONO)
#endif // !defined(ENABLE_STDCXX_SYNC)
104 changes: 96 additions & 8 deletions srtcore/sync.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@
#ifndef __SRT_SYNC_H__
#define __SRT_SYNC_H__

//#define USE_STDCXX_CHRONO
//#define ENABLE_STDCXX_SYNC
//#define ENABLE_CXX17

#include <cstdlib>
#ifdef USE_STDCXX_CHRONO
#ifdef ENABLE_STDCXX_SYNC
#include <chrono>
#include <thread>
#else
Expand All @@ -37,6 +37,13 @@ using namespace std;
//
///////////////////////////////////////////////////////////////////////////////

#if ENABLE_STDCXX_SYNC

template <class Clock>
using Duration = chrono::duration<Clock>;

#else

/// Class template srt::sync::Duration represents a time interval.
/// It consists of a count of ticks of _Clock.
/// It is a wrapper of system timers in case of non-C++11 chrono build.
Expand Down Expand Up @@ -81,12 +88,36 @@ class Duration
int64_t m_duration;
};

#endif // ENABLE_STDCXX_SYNC

///////////////////////////////////////////////////////////////////////////////
//
// TimePoint and steadt_clock classes
//
///////////////////////////////////////////////////////////////////////////////

#if ENABLE_STDCXX_SYNC

using steady_clock = chrono::steady_clock;

template <class Clock, class Duration = typename Clock::duration>
using time_point = chrono::time_point<Clock, Duration>;

template <class Clock>
using TimePoint = chrono::time_point<Clock>;

template <class Clock, class Duration = typename Clock::duration>
inline bool is_zero(const time_point<Clock, Duration> &tp)
{
return tp.time_since_epoch() == Clock::duration::zero();
}

inline bool is_zero(const steady_clock::time_point& t)
{
return t == steady_clock::time_point();
}

#else
template <class _Clock>
class TimePoint;

Expand Down Expand Up @@ -175,6 +206,53 @@ inline Duration<steady_clock> operator*(const int& lhs, const Duration<steady_cl
return rhs * lhs;
}

#endif // ENABLE_STDCXX_SYNC

///////////////////////////////////////////////////////////////////////////////
//
// Duration and timepoint conversions
//
///////////////////////////////////////////////////////////////////////////////

#if ENABLE_STDCXX_SYNC

inline long long count_microseconds(const steady_clock::duration &t)
{
return std::chrono::duration_cast<std::chrono::microseconds>(t).count();
}

inline long long count_microseconds(const steady_clock::time_point tp)
{
return std::chrono::duration_cast<std::chrono::microseconds>(tp.time_since_epoch()).count();
}

inline long long count_milliseconds(const steady_clock::duration &t)
{
return std::chrono::duration_cast<std::chrono::milliseconds>(t).count();
}

inline long long count_seconds(const steady_clock::duration &t)
{
return std::chrono::duration_cast<std::chrono::seconds>(t).count();
}

inline steady_clock::duration microseconds_from(long t_us)
{
return std::chrono::microseconds(t_us);
}

inline steady_clock::duration milliseconds_from(long t_ms)
{
return std::chrono::milliseconds(t_ms);
}

inline steady_clock::duration seconds_from(long t_s)
{
return std::chrono::seconds(t_s);
}

#else

int64_t count_microseconds(const steady_clock::duration& t);
int64_t count_milliseconds(const steady_clock::duration& t);
int64_t count_seconds(const steady_clock::duration& t);
Expand All @@ -188,13 +266,20 @@ inline bool is_zero(const TimePoint<steady_clock>& t)
return t == TimePoint<steady_clock>();
}

#endif // ENABLE_STDCXX_SYNC


///////////////////////////////////////////////////////////////////////////////
//
// Mutex section
//
///////////////////////////////////////////////////////////////////////////////

#if ENABLE_STDCXX_SYNC
using Mutex = mutex;
using UniqueLock = unique_lock<mutex>;
using ScopedLock = lock_guard<mutex>;
#else
/// Mutex is a class wrapper, that should mimic the std::chrono::mutex class.
/// At the moment the extra function ref() is temporally added to allow calls
/// to pthread_cond_timedwait(). Will be removed by introducing CEvent.
Expand Down Expand Up @@ -248,6 +333,7 @@ class UniqueLock
int m_iLocked;
Mutex& m_Mutex;
};
#endif // ENABLE_STDCXX_SYNC

/// The purpose of this typedef is to reduce the number of changes in the code (renamings)
/// and produce less merge conflicts with some other parallel work done.
Expand Down Expand Up @@ -350,7 +436,7 @@ class Condition
void notify_all();

private:
#ifdef USE_STDCXX_CHRONO
#if ENABLE_STDCXX_SYNC
condition_variable m_cv;
#else
pthread_cond_t m_cv;
Expand All @@ -368,7 +454,9 @@ inline void releaseCond(Condition& cv) { cv.destroy(); }

inline void SleepFor(const steady_clock::duration& t)
{
#ifndef _WIN32
#ifdef ENABLE_STDCXX_SYNC
this_thread::sleep_for(t);
#elif !defined(_WIN32)
usleep(count_microseconds(t)); // microseconds
#else
Sleep(count_milliseconds(t));
Expand Down Expand Up @@ -634,7 +722,7 @@ class CGlobEvent
//
////////////////////////////////////////////////////////////////////////////////

#ifdef USE_STDCXX_CHRONO
#ifdef ENABLE_STDCXX_SYNC
typedef std::system_error CThreadException;
using CThread = std::thread;
#else // pthreads wrapper version
Expand Down Expand Up @@ -691,9 +779,9 @@ class CThread
/// @returns true if thread was started successfully,
/// false on failure
///
#ifdef USE_STDCXX_CHRONO
template< class Function >
bool StartThread(CThread& th, Function&& f, void* args, const char* name);
#ifdef ENABLE_STDCXX_SYNC
typedef void* (&ThreadFunc) (void*);
bool StartThread(CThread& th, ThreadFunc&& f, void* args, const char* name);
#else
bool StartThread(CThread& th, void* (*f) (void*), void* args, const char* name);
#endif
Expand Down
Loading