tg2sip/libtgvoip/webrtc_dsp/rtc_base/checks.h

401 lines
15 KiB
C
Raw Normal View History

Squashed 'libtgvoip/' changes from 6053cf5..cfd62e6 cfd62e6 Why did it change the OS X project 3a58a16 2.4.3 c4a48b3 Updated OS X project 564eada Fix #63 4f64e2e fixes 0c732e2 fixes 12e76ed better logging f015b79 Merge pull request #62 from xvitaly/big-endian a1df90f Set preferred audio session parameters on iOS 59a975b Fixes 8fd89fc Fixes, mic level testing and volume adjustment 243acfa Backported WebRTC upstream patch with Big Endian support. fed3bb7 Detect when proxy does not support UDP and persist that across calls a7546d4 Merge commit '6d03dd9ae4bf48d7344341cdd2d055ebd3a6a42e' into public 6d03dd9 version 69adf70 Use server config for APM + iOS crash fix 0b42ec8 Update iOS project f1b9e63 packet logging beeea45 I apparently still suck at C++ memory management 24fceba Update project 7f54b91 crash fix f85ce99 Save more data in data saving mode f4c4f79 Collect packet stats and accept json string for server config 78e584c New protocol version: optimized packet size 8cf9177 Fixed build on iOS 9dd089d fixed build on android 5caaaaf Updated WebRTC APM cc0cf35 fixed deadlock 02f4835 Rearranged VoIPController methods and added sections 912f73d Updated OS X project 39376df Fixed audio glitches on Windows dfe1f03 Updated project 81daf3f fix 296187a Merge pull request #58 from telegramdesktop/tdesktop 44956ac Merge pull request #57 from UnigramDev/public fb0a2b0 Fix build for Linux. d6cf1b7 Updated UWP wrapper 0f06289 Merge branch 'public' of github.com:grishka/libtgvoip into public dcfad91 Fix #54 162f447 Merge pull request #56 from telegramdesktop/tdesktop a7ee511 Merge remote-tracking branch 'origin/tdesktop' into HEAD 467b148 Removed unused files b1a0b3d 2.3 9b292fd Fix warning in Xcode 10. 8d8522a Merge pull request #53 from UnigramDev/public 646f7d6 Merge branch 'public' into public 14d782b Fixes 68acf59 Added GetSignalBarsCount and GetConnectionState to CXWrapper 761c586 Added GetStats to CXWrapper f643b02 Prevent crash if UWP WASAPI devices aren't found b2ac10e Fixed UWP project 9a1ec51 Fixed build for Windows Phone, fixed some warnings 4aea54f fix git-subtree-dir: libtgvoip git-subtree-split: cfd62e66a825348ac51f49e5d20bf8827fef7a38
2019-02-06 18:22:38 +00:00
/*
* Copyright 2006 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef RTC_BASE_CHECKS_H_
#define RTC_BASE_CHECKS_H_
// If you for some reson need to know if DCHECKs are on, test the value of
// RTC_DCHECK_IS_ON. (Test its value, not if it's defined; it'll always be
// defined, to either a true or a false value.)
#if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)
#define RTC_DCHECK_IS_ON 1
#else
#define RTC_DCHECK_IS_ON 0
#endif
// Annotate a function that will not return control flow to the caller.
#if defined(_MSC_VER)
#define RTC_NORETURN __declspec(noreturn)
#elif defined(__GNUC__)
#define RTC_NORETURN __attribute__ ((__noreturn__))
#else
#define RTC_NORETURN
#endif
#ifdef __cplusplus
extern "C" {
#endif
RTC_NORETURN void rtc_FatalMessage(const char* file, int line, const char* msg);
#ifdef __cplusplus
} // extern "C"
#endif
#ifdef __cplusplus
// C++ version.
#include <string>
#include "rtc_base/numerics/safe_compare.h"
#include "rtc_base/system/inline.h"
// The macros here print a message to stderr and abort under various
// conditions. All will accept additional stream messages. For example:
// RTC_DCHECK_EQ(foo, bar) << "I'm printed when foo != bar.";
//
// - RTC_CHECK(x) is an assertion that x is always true, and that if it isn't,
// it's better to terminate the process than to continue. During development,
// the reason that it's better to terminate might simply be that the error
// handling code isn't in place yet; in production, the reason might be that
// the author of the code truly believes that x will always be true, but that
// she recognizes that if she is wrong, abrupt and unpleasant process
// termination is still better than carrying on with the assumption violated.
//
// RTC_CHECK always evaluates its argument, so it's OK for x to have side
// effects.
//
// - RTC_DCHECK(x) is the same as RTC_CHECK(x)---an assertion that x is always
// true---except that x will only be evaluated in debug builds; in production
// builds, x is simply assumed to be true. This is useful if evaluating x is
// expensive and the expected cost of failing to detect the violated
// assumption is acceptable. You should not handle cases where a production
// build fails to spot a violated condition, even those that would result in
// crashes. If the code needs to cope with the error, make it cope, but don't
// call RTC_DCHECK; if the condition really can't occur, but you'd sleep
// better at night knowing that the process will suicide instead of carrying
// on in case you were wrong, use RTC_CHECK instead of RTC_DCHECK.
//
// RTC_DCHECK only evaluates its argument in debug builds, so if x has visible
// side effects, you need to write e.g.
// bool w = x; RTC_DCHECK(w);
//
// - RTC_CHECK_EQ, _NE, _GT, ..., and RTC_DCHECK_EQ, _NE, _GT, ... are
// specialized variants of RTC_CHECK and RTC_DCHECK that print prettier
// messages if the condition doesn't hold. Prefer them to raw RTC_CHECK and
// RTC_DCHECK.
//
// - FATAL() aborts unconditionally.
//
// TODO(ajm): Ideally, checks.h would be combined with logging.h, but
// consolidation with system_wrappers/logging.h should happen first.
namespace rtc {
namespace webrtc_checks_impl {
enum class CheckArgType : int8_t {
kEnd = 0,
kInt,
kLong,
kLongLong,
kUInt,
kULong,
kULongLong,
kDouble,
kLongDouble,
kCharP,
kStdString,
kVoidP,
// kCheckOp doesn't represent an argument type. Instead, it is sent as the
// first argument from RTC_CHECK_OP to make FatalLog use the next two
// arguments to build the special CHECK_OP error message
// (the "a == b (1 vs. 2)" bit).
kCheckOp,
};
RTC_NORETURN void FatalLog(const char* file,
int line,
const char* message,
const CheckArgType* fmt,
...);
// Wrapper for log arguments. Only ever make values of this type with the
// MakeVal() functions.
template <CheckArgType N, typename T>
struct Val {
static constexpr CheckArgType Type() { return N; }
T GetVal() const { return val; }
T val;
};
inline Val<CheckArgType::kInt, int> MakeVal(int x) {
return {x};
}
inline Val<CheckArgType::kLong, long> MakeVal(long x) {
return {x};
}
inline Val<CheckArgType::kLongLong, long long> MakeVal(long long x) {
return {x};
}
inline Val<CheckArgType::kUInt, unsigned int> MakeVal(unsigned int x) {
return {x};
}
inline Val<CheckArgType::kULong, unsigned long> MakeVal(unsigned long x) {
return {x};
}
inline Val<CheckArgType::kULongLong, unsigned long long> MakeVal(
unsigned long long x) {
return {x};
}
inline Val<CheckArgType::kDouble, double> MakeVal(double x) {
return {x};
}
inline Val<CheckArgType::kLongDouble, long double> MakeVal(long double x) {
return {x};
}
inline Val<CheckArgType::kCharP, const char*> MakeVal(const char* x) {
return {x};
}
inline Val<CheckArgType::kStdString, const std::string*> MakeVal(
const std::string& x) {
return {&x};
}
inline Val<CheckArgType::kVoidP, const void*> MakeVal(const void* x) {
return {x};
}
// Ephemeral type that represents the result of the logging << operator.
template <typename... Ts>
class LogStreamer;
// Base case: Before the first << argument.
template <>
class LogStreamer<> final {
public:
template <
typename U,
typename std::enable_if<std::is_arithmetic<U>::value>::type* = nullptr>
RTC_FORCE_INLINE LogStreamer<decltype(MakeVal(std::declval<U>()))> operator<<(
U arg) const {
return LogStreamer<decltype(MakeVal(std::declval<U>()))>(MakeVal(arg),
this);
}
template <
typename U,
typename std::enable_if<!std::is_arithmetic<U>::value>::type* = nullptr>
RTC_FORCE_INLINE LogStreamer<decltype(MakeVal(std::declval<U>()))> operator<<(
const U& arg) const {
return LogStreamer<decltype(MakeVal(std::declval<U>()))>(MakeVal(arg),
this);
}
template <typename... Us>
RTC_NORETURN RTC_FORCE_INLINE static void Call(const char* file,
const int line,
const char* message,
const Us&... args) {
static constexpr CheckArgType t[] = {Us::Type()..., CheckArgType::kEnd};
FatalLog(file, line, message, t, args.GetVal()...);
}
template <typename... Us>
RTC_NORETURN RTC_FORCE_INLINE static void CallCheckOp(const char* file,
const int line,
const char* message,
const Us&... args) {
static constexpr CheckArgType t[] = {CheckArgType::kCheckOp, Us::Type()...,
CheckArgType::kEnd};
FatalLog(file, line, message, t, args.GetVal()...);
}
};
// Inductive case: We've already seen at least one << argument. The most recent
// one had type `T`, and the earlier ones had types `Ts`.
template <typename T, typename... Ts>
class LogStreamer<T, Ts...> final {
public:
RTC_FORCE_INLINE LogStreamer(T arg, const LogStreamer<Ts...>* prior)
: arg_(arg), prior_(prior) {}
template <
typename U,
typename std::enable_if<std::is_arithmetic<U>::value>::type* = nullptr>
RTC_FORCE_INLINE LogStreamer<decltype(MakeVal(std::declval<U>())), T, Ts...>
operator<<(U arg) const {
return LogStreamer<decltype(MakeVal(std::declval<U>())), T, Ts...>(
MakeVal(arg), this);
}
template <
typename U,
typename std::enable_if<!std::is_arithmetic<U>::value>::type* = nullptr>
RTC_FORCE_INLINE LogStreamer<decltype(MakeVal(std::declval<U>())), T, Ts...>
operator<<(const U& arg) const {
return LogStreamer<decltype(MakeVal(std::declval<U>())), T, Ts...>(
MakeVal(arg), this);
}
template <typename... Us>
RTC_NORETURN RTC_FORCE_INLINE void Call(const char* file,
const int line,
const char* message,
const Us&... args) const {
prior_->Call(file, line, message, arg_, args...);
}
template <typename... Us>
RTC_NORETURN RTC_FORCE_INLINE void CallCheckOp(const char* file,
const int line,
const char* message,
const Us&... args) const {
prior_->CallCheckOp(file, line, message, arg_, args...);
}
private:
// The most recent argument.
T arg_;
// Earlier arguments.
const LogStreamer<Ts...>* prior_;
};
template <bool isCheckOp>
class FatalLogCall final {
public:
FatalLogCall(const char* file, int line, const char* message)
: file_(file), line_(line), message_(message) {}
// This can be any binary operator with precedence lower than <<.
template <typename... Ts>
RTC_NORETURN RTC_FORCE_INLINE void operator&(
const LogStreamer<Ts...>& streamer) {
isCheckOp ? streamer.CallCheckOp(file_, line_, message_)
: streamer.Call(file_, line_, message_);
}
private:
const char* file_;
int line_;
const char* message_;
};
} // namespace webrtc_checks_impl
// The actual stream used isn't important. We reference |ignored| in the code
// but don't evaluate it; this is to avoid "unused variable" warnings (we do so
// in a particularly convoluted way with an extra ?: because that appears to be
// the simplest construct that keeps Visual Studio from complaining about
// condition being unused).
#define RTC_EAT_STREAM_PARAMETERS(ignored) \
(true ? true : ((void)(ignored), true)) \
? static_cast<void>(0) \
: rtc::webrtc_checks_impl::FatalLogCall<false>("", 0, "") & \
rtc::webrtc_checks_impl::LogStreamer<>()
// Call RTC_EAT_STREAM_PARAMETERS with an argument that fails to compile if
// values of the same types as |a| and |b| can't be compared with the given
// operation, and that would evaluate |a| and |b| if evaluated.
#define RTC_EAT_STREAM_PARAMETERS_OP(op, a, b) \
RTC_EAT_STREAM_PARAMETERS(((void)rtc::Safe##op(a, b)))
// RTC_CHECK dies with a fatal error if condition is not true. It is *not*
// controlled by NDEBUG or anything else, so the check will be executed
// regardless of compilation mode.
//
// We make sure RTC_CHECK et al. always evaluates |condition|, as
// doing RTC_CHECK(FunctionWithSideEffect()) is a common idiom.
#define RTC_CHECK(condition) \
while (!(condition)) \
rtc::webrtc_checks_impl::FatalLogCall<false>(__FILE__, __LINE__, \
#condition) & \
rtc::webrtc_checks_impl::LogStreamer<>()
// Helper macro for binary operators.
// Don't use this macro directly in your code, use RTC_CHECK_EQ et al below.
#define RTC_CHECK_OP(name, op, val1, val2) \
while (!rtc::Safe##name((val1), (val2))) \
rtc::webrtc_checks_impl::FatalLogCall<true>(__FILE__, __LINE__, \
#val1 " " #op " " #val2) & \
rtc::webrtc_checks_impl::LogStreamer<>() << (val1) << (val2)
#define RTC_CHECK_EQ(val1, val2) RTC_CHECK_OP(Eq, ==, val1, val2)
#define RTC_CHECK_NE(val1, val2) RTC_CHECK_OP(Ne, !=, val1, val2)
#define RTC_CHECK_LE(val1, val2) RTC_CHECK_OP(Le, <=, val1, val2)
#define RTC_CHECK_LT(val1, val2) RTC_CHECK_OP(Lt, <, val1, val2)
#define RTC_CHECK_GE(val1, val2) RTC_CHECK_OP(Ge, >=, val1, val2)
#define RTC_CHECK_GT(val1, val2) RTC_CHECK_OP(Gt, >, val1, val2)
// The RTC_DCHECK macro is equivalent to RTC_CHECK except that it only generates
// code in debug builds. It does reference the condition parameter in all cases,
// though, so callers won't risk getting warnings about unused variables.
#if RTC_DCHECK_IS_ON
#define RTC_DCHECK(condition) RTC_CHECK(condition)
#define RTC_DCHECK_EQ(v1, v2) RTC_CHECK_EQ(v1, v2)
#define RTC_DCHECK_NE(v1, v2) RTC_CHECK_NE(v1, v2)
#define RTC_DCHECK_LE(v1, v2) RTC_CHECK_LE(v1, v2)
#define RTC_DCHECK_LT(v1, v2) RTC_CHECK_LT(v1, v2)
#define RTC_DCHECK_GE(v1, v2) RTC_CHECK_GE(v1, v2)
#define RTC_DCHECK_GT(v1, v2) RTC_CHECK_GT(v1, v2)
#else
#define RTC_DCHECK(condition) RTC_EAT_STREAM_PARAMETERS(condition)
#define RTC_DCHECK_EQ(v1, v2) RTC_EAT_STREAM_PARAMETERS_OP(Eq, v1, v2)
#define RTC_DCHECK_NE(v1, v2) RTC_EAT_STREAM_PARAMETERS_OP(Ne, v1, v2)
#define RTC_DCHECK_LE(v1, v2) RTC_EAT_STREAM_PARAMETERS_OP(Le, v1, v2)
#define RTC_DCHECK_LT(v1, v2) RTC_EAT_STREAM_PARAMETERS_OP(Lt, v1, v2)
#define RTC_DCHECK_GE(v1, v2) RTC_EAT_STREAM_PARAMETERS_OP(Ge, v1, v2)
#define RTC_DCHECK_GT(v1, v2) RTC_EAT_STREAM_PARAMETERS_OP(Gt, v1, v2)
#endif
#define RTC_UNREACHABLE_CODE_HIT false
#define RTC_NOTREACHED() RTC_DCHECK(RTC_UNREACHABLE_CODE_HIT)
// TODO(bugs.webrtc.org/8454): Add an RTC_ prefix or rename differently.
#define FATAL() \
rtc::webrtc_checks_impl::FatalLogCall<false>(__FILE__, __LINE__, \
"FATAL()") & \
rtc::webrtc_checks_impl::LogStreamer<>()
// Performs the integer division a/b and returns the result. CHECKs that the
// remainder is zero.
template <typename T>
inline T CheckedDivExact(T a, T b) {
RTC_CHECK_EQ(a % b, 0) << a << " is not evenly divisible by " << b;
return a / b;
}
} // namespace rtc
#else // __cplusplus not defined
// C version. Lacks many features compared to the C++ version, but usage
// guidelines are the same.
#define RTC_CHECK(condition) \
do { \
if (!(condition)) { \
rtc_FatalMessage(__FILE__, __LINE__, "CHECK failed: " #condition); \
} \
} while (0)
#define RTC_CHECK_EQ(a, b) RTC_CHECK((a) == (b))
#define RTC_CHECK_NE(a, b) RTC_CHECK((a) != (b))
#define RTC_CHECK_LE(a, b) RTC_CHECK((a) <= (b))
#define RTC_CHECK_LT(a, b) RTC_CHECK((a) < (b))
#define RTC_CHECK_GE(a, b) RTC_CHECK((a) >= (b))
#define RTC_CHECK_GT(a, b) RTC_CHECK((a) > (b))
#define RTC_DCHECK(condition) \
do { \
if (RTC_DCHECK_IS_ON && !(condition)) { \
rtc_FatalMessage(__FILE__, __LINE__, "DCHECK failed: " #condition); \
} \
} while (0)
#define RTC_DCHECK_EQ(a, b) RTC_DCHECK((a) == (b))
#define RTC_DCHECK_NE(a, b) RTC_DCHECK((a) != (b))
#define RTC_DCHECK_LE(a, b) RTC_DCHECK((a) <= (b))
#define RTC_DCHECK_LT(a, b) RTC_DCHECK((a) < (b))
#define RTC_DCHECK_GE(a, b) RTC_DCHECK((a) >= (b))
#define RTC_DCHECK_GT(a, b) RTC_DCHECK((a) > (b))
#endif // __cplusplus
#endif // RTC_BASE_CHECKS_H_