Merge branch 'master' of https://code.uocat.com/tqcq/sled
This commit is contained in:
commit
8c3ab60c73
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
.cache/
|
||||||
|
out/
|
||||||
|
build/
|
||||||
|
compile_commands.json
|
@ -29,6 +29,7 @@ target_sources(
|
|||||||
src/synchronization/mutex.cc
|
src/synchronization/mutex.cc
|
||||||
src/synchronization/sequence_checker_internal.cc
|
src/synchronization/sequence_checker_internal.cc
|
||||||
src/synchronization/thread_local.cc
|
src/synchronization/thread_local.cc
|
||||||
|
src/system/location.cc
|
||||||
src/system/thread.cc
|
src/system/thread.cc
|
||||||
src/task_queue/pending_task_safety_flag.cc
|
src/task_queue/pending_task_safety_flag.cc
|
||||||
src/task_queue/task_queue_base.cc
|
src/task_queue/task_queue_base.cc
|
||||||
@ -50,3 +51,10 @@ target_include_directories(
|
|||||||
PRIVATE src)
|
PRIVATE src)
|
||||||
|
|
||||||
target_link_libraries(sled PUBLIC rpc_core fmt)
|
target_link_libraries(sled PUBLIC rpc_core fmt)
|
||||||
|
|
||||||
|
find_package(benchmark REQUIRED)
|
||||||
|
|
||||||
|
add_executable(sled_benchmark
|
||||||
|
benchmark/strings/base64_benchmark.cc
|
||||||
|
)
|
||||||
|
target_link_libraries(sled_benchmark PRIVATE sled benchmark::benchmark benchmark::benchmark_main)
|
||||||
|
59
benchmark/strings/base64_benchmark.cc
Normal file
59
benchmark/strings/base64_benchmark.cc
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
#include <benchmark/benchmark.h>
|
||||||
|
#include <sled/random.h>
|
||||||
|
#include <sled/strings/base64.h>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
struct strings {};
|
||||||
|
|
||||||
|
static std::string
|
||||||
|
AllocRandomString(sled::Random &random, int len)
|
||||||
|
{
|
||||||
|
std::stringstream ss;
|
||||||
|
for (int i = len; i > 0; i--) { ss << random.Rand<char>(); }
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
BenchmarkBase64Encode(benchmark::State &state)
|
||||||
|
{
|
||||||
|
state.PauseTiming();
|
||||||
|
sled::Random random(2393);
|
||||||
|
std::vector<std::string> test_data;
|
||||||
|
for (int i = 0; i < state.range(0); i++) {
|
||||||
|
test_data.emplace_back(AllocRandomString(random, state.range(1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
state.ResumeTiming();
|
||||||
|
for (int i = 0; i < state.range(2); i++) {
|
||||||
|
for (const auto &str : test_data) {
|
||||||
|
auto base64 = sled::Base64::Encode(str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string
|
||||||
|
uint2str(unsigned int num)
|
||||||
|
{
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << num;
|
||||||
|
return oss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
test(benchmark::State &state)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 1000000; i++) (void) uint2str(i);
|
||||||
|
state.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
BENCHMARK(test);
|
||||||
|
/*
|
||||||
|
BENCHMARK(BenchmarkBase64Encode)
|
||||||
|
->ArgsProduct({
|
||||||
|
// generate the num of strings
|
||||||
|
benchmark::CreateRange(10, 1000, 10),
|
||||||
|
// generate the length of each string
|
||||||
|
benchmark::CreateRange(10, 1000, 10),
|
||||||
|
benchmark::CreateRange(10, 1000, 10),
|
||||||
|
});
|
||||||
|
*/
|
@ -1,5 +1,30 @@
|
|||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
|
||||||
|
#include <libkern/OSByteOrder.h>
|
||||||
|
|
||||||
|
#define htobe16(x) OSSwapHostToBigInt16(x)
|
||||||
|
#define htole16(x) OSSwapHostToLittleInt16(x)
|
||||||
|
#define be16toh(x) OSSwapBigToHostInt16(x)
|
||||||
|
#define le16toh(x) OSSwapLittleToHostInt16(x)
|
||||||
|
|
||||||
|
#define htobe32(x) OSSwapHostToBigInt32(x)
|
||||||
|
#define htole32(x) OSSwapHostToLittleInt32(x)
|
||||||
|
#define be32toh(x) OSSwapBigToHostInt32(x)
|
||||||
|
#define le32toh(x) OSSwapLittleToHostInt32(x)
|
||||||
|
|
||||||
|
#define htobe64(x) OSSwapHostToBigInt64(x)
|
||||||
|
#define htole64(x) OSSwapHostToLittleInt64(x)
|
||||||
|
#define be64toh(x) OSSwapBigToHostInt64(x)
|
||||||
|
#define le64toh(x) OSSwapLittleToHostInt64(x)
|
||||||
|
|
||||||
|
#define __BYTE_ORDER BYTE_ORDER
|
||||||
|
#define __BIG_ENDIAN BIG_ENDIAN
|
||||||
|
#define __LITTLE_ENDIAN LITTLE_ENDIAN
|
||||||
|
#define __PDP_ENDIAN PDP_ENDIAN
|
||||||
|
#endif
|
||||||
|
|
||||||
inline uint16_t
|
inline uint16_t
|
||||||
HostToNetwork16(uint16_t n)
|
HostToNetwork16(uint16_t n)
|
||||||
{
|
{
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#ifndef LOG_H
|
#ifndef LOG_H
|
||||||
#define LOG_H
|
#define LOG_H
|
||||||
|
#include "sled/system/location.h"
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
|
|
||||||
namespace sled {
|
namespace sled {
|
||||||
@ -32,10 +33,18 @@ void Log(LogLevel level,
|
|||||||
// sled::Log(level, tag, fmt, __FILE__, __FUNCTION__, __VA_ARGS__)
|
// sled::Log(level, tag, fmt, __FILE__, __FUNCTION__, __VA_ARGS__)
|
||||||
|
|
||||||
#define _SLOG(level, tag, fmt_str, ...) \
|
#define _SLOG(level, tag, fmt_str, ...) \
|
||||||
sled::Log(level, tag, fmt::format(fmt_str, #__VA_ARGS__).c_str(), \
|
do { \
|
||||||
__FILE__, __LINE__, __FUNCTION__)
|
std::string __fmt_str; \
|
||||||
|
try { \
|
||||||
|
__fmt_str = fmt::format(fmt_str, ##__VA_ARGS__); \
|
||||||
|
} catch (const std::exception &e) { \
|
||||||
|
__fmt_str = " fmt error: " + std::string(e.what()); \
|
||||||
|
} \
|
||||||
|
sled::Log(level, tag, __fmt_str.c_str(), __FILE__, __LINE__, \
|
||||||
|
__FUNCTION__); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
#define SLOG(level, tag, fmt, ...) _SLOG(level, tag, fmt, #__VA_ARGS__)
|
#define SLOG(level, tag, fmt, ...) _SLOG(level, tag, fmt, ##__VA_ARGS__)
|
||||||
#define SLOG_TRACE(tag, fmt, ...) \
|
#define SLOG_TRACE(tag, fmt, ...) \
|
||||||
SLOG(sled::LogLevel::kTrace, tag, fmt, __VA_ARGS__)
|
SLOG(sled::LogLevel::kTrace, tag, fmt, __VA_ARGS__)
|
||||||
#define SLOG_INFO(tag, fmt, ...) \
|
#define SLOG_INFO(tag, fmt, ...) \
|
||||||
@ -56,8 +65,8 @@ void Log(LogLevel level,
|
|||||||
|
|
||||||
#define SLOG_ASSERT(cond, tag, fmt, ...) \
|
#define SLOG_ASSERT(cond, tag, fmt, ...) \
|
||||||
do { \
|
do { \
|
||||||
if (!(cond)) { \
|
if (!!(cond)) { \
|
||||||
SLOG(sled::LogLevel::kFatal, __VA_ARGS__); \
|
SLOG(sled::LogLevel::kFatal, tag, fmt, ##__VA_ARGS__); \
|
||||||
assert(cond); \
|
assert(cond); \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
@ -75,12 +84,18 @@ void Log(LogLevel level,
|
|||||||
#define LOGF_IF(cond, tag, fmt, ...) \
|
#define LOGF_IF(cond, tag, fmt, ...) \
|
||||||
SLOG_IF(cond, sled::LogLevel::kFatal, tag, fmt, __VA_ARGS__)
|
SLOG_IF(cond, sled::LogLevel::kFatal, tag, fmt, __VA_ARGS__)
|
||||||
|
|
||||||
#define LOGV(tag, fmt, ...) SLOG(sled::LogLevel::kTrace, tag, fmt, #__VA_ARGS__)
|
#define LOGV(tag, fmt, ...) \
|
||||||
#define LOGD(tag, fmt, ...) SLOG(sled::LogLevel::kDebug, tag, fmt, #__VA_ARGS__)
|
SLOG(sled::LogLevel::kTrace, tag, fmt, ##__VA_ARGS__)
|
||||||
#define LOGI(tag, fmt, ...) SLOG(sled::LogLevel::kInfo, tag, fmt, #__VA_ARGS__)
|
#define LOGD(tag, fmt, ...) \
|
||||||
|
SLOG(sled::LogLevel::kDebug, tag, fmt, ##__VA_ARGS__)
|
||||||
|
#define LOGI(tag, fmt, ...) SLOG(sled::LogLevel::kInfo, tag, fmt, ##__VA_ARGS__)
|
||||||
#define LOGW(tag, fmt, ...) \
|
#define LOGW(tag, fmt, ...) \
|
||||||
SLOG(sled::LogLevel::kWarning, tag, fmt, #__VA_ARGS__)
|
SLOG(sled::LogLevel::kWarning, tag, fmt, ##__VA_ARGS__)
|
||||||
#define LOGE(tag, fmt, ...) SLOG(sled::LogLevel::kError, tag, fmt, #__VA_ARGS__)
|
#define LOGE(tag, fmt, ...) \
|
||||||
#define LOGF(tag, fmt, ...) SLOG(sled::LogLevel::kFatal, tag, fmt, #__VA_ARGS__)
|
SLOG(sled::LogLevel::kError, tag, fmt, ##__VA_ARGS__)
|
||||||
|
#define LOGF(tag, fmt, ...) \
|
||||||
|
SLOG(sled::LogLevel::kFatal, tag, fmt, ##__VA_ARGS__)
|
||||||
|
|
||||||
|
#define ASSERT(cond, fmt, ...) SLOG_ASSERT(cond, "ASSERT", fmt, ##__VA_ARGS__)
|
||||||
|
|
||||||
#endif// LOG_H
|
#endif// LOG_H
|
||||||
|
@ -53,9 +53,9 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
static const int kForeverMs = -1;
|
static const int kForeverMs = -1;
|
||||||
static int ToCmsWait(TimeDelta max_wait_duration);
|
static int ToCusWait(TimeDelta max_wait_duration);
|
||||||
|
|
||||||
bool WaitSelect(int cmsWait, bool process_io);
|
bool WaitSelect(int64_t cusWait, bool process_io);
|
||||||
|
|
||||||
uint64_t next_dispatcher_key_ = 0;
|
uint64_t next_dispatcher_key_ = 0;
|
||||||
std::unordered_map<uint64_t, Dispatcher *> dispatcher_by_key_;
|
std::unordered_map<uint64_t, Dispatcher *> dispatcher_by_key_;
|
||||||
|
708
include/sled/numerics/fixed_point_number.h
Normal file
708
include/sled/numerics/fixed_point_number.h
Normal file
@ -0,0 +1,708 @@
|
|||||||
|
/*
|
||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2015 Julius Ikkala
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
*/
|
||||||
|
#ifndef FIXED_POINT_H_
|
||||||
|
#define FIXED_POINT_H_
|
||||||
|
#include <Eigen/Eigen>
|
||||||
|
#include <cmath>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <fmt/ostream.h>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//Fixed-point numbers
|
||||||
|
//==========================================================================
|
||||||
|
namespace fp {
|
||||||
|
/*The fixed-point number class. f is the amount of fractional bits, I is
|
||||||
|
the internal type. If I is signed, q will be signed.*/
|
||||||
|
template<unsigned f, typename I>
|
||||||
|
struct q {
|
||||||
|
I i;
|
||||||
|
|
||||||
|
q(int i = 0); /*Integer literals are int*/
|
||||||
|
q(unsigned u);
|
||||||
|
q(uintmax_t s);
|
||||||
|
q(double d);
|
||||||
|
q(long double d);
|
||||||
|
template<unsigned fb>
|
||||||
|
q(q<fb, I> a);
|
||||||
|
|
||||||
|
operator int() const;
|
||||||
|
operator float() const;
|
||||||
|
operator double() const;
|
||||||
|
operator long double() const;
|
||||||
|
template<unsigned fb>
|
||||||
|
q<f, I> operator+(q<fb, I> b) const;
|
||||||
|
template<unsigned fb>
|
||||||
|
q<f, I> operator-(q<fb, I> b) const;
|
||||||
|
template<unsigned fb>
|
||||||
|
q<f, I> operator*(q<fb, I> b) const;
|
||||||
|
template<unsigned fb>
|
||||||
|
q<f, I> operator/(q<fb, I> b) const;
|
||||||
|
template<unsigned fb>
|
||||||
|
q<f, I> operator%(q<fb, I> b) const;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
q<f, I> operator+(T b) const;
|
||||||
|
template<typename T>
|
||||||
|
q<f, I> operator-(T b) const;
|
||||||
|
template<typename T>
|
||||||
|
q<f, I> operator*(T b) const;
|
||||||
|
template<typename T>
|
||||||
|
q<f, I> operator/(T b) const;
|
||||||
|
template<typename T>
|
||||||
|
q<f, I> operator%(T b) const;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
q<f, I> &operator+=(T b);
|
||||||
|
template<typename T>
|
||||||
|
q<f, I> &operator-=(T b);
|
||||||
|
template<typename T>
|
||||||
|
q<f, I> &operator*=(T b);
|
||||||
|
template<typename T>
|
||||||
|
q<f, I> &operator/=(T b);
|
||||||
|
template<typename T>
|
||||||
|
q<f, I> &operator%=(T b);
|
||||||
|
|
||||||
|
q<f, I> operator-() const;
|
||||||
|
|
||||||
|
template<unsigned fb>
|
||||||
|
q<f, I> &operator=(q<fb, I> b);
|
||||||
|
q<f, I> &operator=(int b);
|
||||||
|
q<f, I> &operator=(double b);
|
||||||
|
q<f, I> &operator=(long double b);
|
||||||
|
|
||||||
|
template<unsigned fb>
|
||||||
|
bool operator>=(q<fb, I> b) const;
|
||||||
|
template<unsigned fb>
|
||||||
|
bool operator>(q<fb, I> b) const;
|
||||||
|
template<unsigned fb>
|
||||||
|
bool operator<=(q<fb, I> b) const;
|
||||||
|
template<unsigned fb>
|
||||||
|
bool operator<(q<fb, I> b) const;
|
||||||
|
template<unsigned fb>
|
||||||
|
bool operator==(q<fb, I> b) const;
|
||||||
|
template<unsigned fb>
|
||||||
|
bool operator!=(q<fb, I> b) const;
|
||||||
|
|
||||||
|
friend std::ostream &operator<<(std::ostream &os, const q<f, I> &fp)
|
||||||
|
{
|
||||||
|
os << (float) fp;
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend std::istream &operator>>(std::istream &is, q<f, I> &fp)
|
||||||
|
{
|
||||||
|
float val;
|
||||||
|
is >> val;
|
||||||
|
fp = val;
|
||||||
|
return is;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef q<16, uint32_t> UQ16_16;
|
||||||
|
typedef q<32, uint64_t> UQ32_32;
|
||||||
|
typedef q<16, uint64_t> UQ48_16;
|
||||||
|
typedef q<16, int32_t> Q16_16;
|
||||||
|
typedef q<32, int64_t> Q32_32;
|
||||||
|
typedef q<16, int64_t> Q48_16;
|
||||||
|
|
||||||
|
/*Returns the absolute value of x*/
|
||||||
|
template<unsigned f, typename I>
|
||||||
|
q<f, I> abs(q<f, I> x);
|
||||||
|
}// namespace fp
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//Internal helper functions and classes
|
||||||
|
//==========================================================================
|
||||||
|
namespace fp_internal {
|
||||||
|
/*Count leading zeroes*/
|
||||||
|
template<typename T>
|
||||||
|
unsigned
|
||||||
|
clz(T x)
|
||||||
|
{
|
||||||
|
unsigned i = 0;
|
||||||
|
while (!(x & (((T) 1) << (sizeof(T) * 8 - 1))) && (x <<= 1)) ++i;
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*Used to select the correct shift operator in compile-time*/
|
||||||
|
template<int shift, bool rsh, bool zero, typename T>
|
||||||
|
struct shifter {
|
||||||
|
static T op(T x);
|
||||||
|
};
|
||||||
|
|
||||||
|
template<int shift, typename T>
|
||||||
|
struct shifter<shift, true, false, T> {
|
||||||
|
static T op(T x) { return x >> shift; };
|
||||||
|
};
|
||||||
|
|
||||||
|
template<int shift, typename T>
|
||||||
|
struct shifter<shift, false, false, T> {
|
||||||
|
static T op(T x) { return x << -shift; };
|
||||||
|
};
|
||||||
|
|
||||||
|
template<int shift, bool rsh, typename T>
|
||||||
|
struct shifter<shift, rsh, true, T> {
|
||||||
|
static T op(T x) { return 0; };
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
constexpr T
|
||||||
|
abs_helper(const T x) noexcept
|
||||||
|
{
|
||||||
|
return (// deal with signed-zeros
|
||||||
|
x == T(0) ? T(0) :
|
||||||
|
// else
|
||||||
|
x < T(0) ? -x
|
||||||
|
: x);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*Signed right shift. Accepts negative values of shift and never
|
||||||
|
complains about too big shifts. Compile-time version.*/
|
||||||
|
template<int shift, typename T>
|
||||||
|
constexpr T
|
||||||
|
signed_rsh(T x)
|
||||||
|
{
|
||||||
|
return shifter<shift, (shift >= 0), (abs_helper(shift) >= sizeof(T) * 8),
|
||||||
|
T>::op(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*Signed right shift, run time version.*/
|
||||||
|
template<typename T>
|
||||||
|
T
|
||||||
|
signed_rsh(T x, int shift)
|
||||||
|
{
|
||||||
|
return std::abs(shift) < sizeof(T) * 8
|
||||||
|
? (shift < 0 ? x << -shift : x >> shift)
|
||||||
|
: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*Signed left shift, compile-time version*/
|
||||||
|
template<int shift, typename T>
|
||||||
|
T
|
||||||
|
signed_lsh(T x)
|
||||||
|
{
|
||||||
|
return signed_rsh<-shift, T>(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*Signed left shift, run time version*/
|
||||||
|
template<typename T>
|
||||||
|
T
|
||||||
|
signed_lsh(T x, int shift)
|
||||||
|
{
|
||||||
|
return std::abs(shift) < sizeof(T) * 8
|
||||||
|
? (shift < 0 ? x >> -shift : x << shift)
|
||||||
|
: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*Multiplies and simultaneously right-shifts the argument values,
|
||||||
|
without losing the high bits. Compile-time version*/
|
||||||
|
template<int shift, typename T>
|
||||||
|
T
|
||||||
|
mul_rsh(T a, T b)
|
||||||
|
{
|
||||||
|
typedef typename std::make_unsigned<T>::type U;
|
||||||
|
static const int bits = sizeof(T) * 8;
|
||||||
|
static const int halfbits = sizeof(T) * 4;
|
||||||
|
static const U lowmask = (((T) 1) << (halfbits)) - 1;
|
||||||
|
static const U highmask = lowmask << (halfbits);
|
||||||
|
T a1 = a >> (halfbits);
|
||||||
|
T a2 = a - (a & highmask);
|
||||||
|
T b1 = b >> (halfbits);
|
||||||
|
T b2 = b - (b & highmask);
|
||||||
|
T a1b1 = a1 * b1;
|
||||||
|
T a1b2 = a1 * b2;
|
||||||
|
T a2b1 = a2 * b1;
|
||||||
|
T a2b2 = a2 * b2;
|
||||||
|
U high = a1b1 + (a2b1 >> (halfbits)) + (a1b2 >> (halfbits));
|
||||||
|
|
||||||
|
U low = a2b2;
|
||||||
|
high += (low += (a2b1 << halfbits)) < a2b2;
|
||||||
|
U tmp = low;
|
||||||
|
high += (low += (a1b2 << halfbits)) < tmp;
|
||||||
|
low = signed_rsh<shift>(low);
|
||||||
|
low += signed_lsh<bits - shift>(high);
|
||||||
|
return low;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*Run time version*/
|
||||||
|
template<typename T>
|
||||||
|
T
|
||||||
|
mul_rsh(T a, T b, int shift)
|
||||||
|
{
|
||||||
|
typedef typename std::make_unsigned<T>::type U;
|
||||||
|
static const int bits = sizeof(T) * 8;
|
||||||
|
static const int halfbits = sizeof(T) * 4;
|
||||||
|
static const U lowmask = (((T) 1) << (halfbits)) - 1;
|
||||||
|
static const U highmask = lowmask << (halfbits);
|
||||||
|
T a1 = a >> (halfbits);
|
||||||
|
T a2 = a - (a & highmask);
|
||||||
|
T b1 = b >> (halfbits);
|
||||||
|
T b2 = b - (b & highmask);
|
||||||
|
T a1b1 = a1 * b1;
|
||||||
|
T a1b2 = a1 * b2;
|
||||||
|
T a2b1 = a2 * b1;
|
||||||
|
T a2b2 = a2 * b2;
|
||||||
|
U high = a1b1 + (a2b1 >> (halfbits)) + (a1b2 >> (halfbits));
|
||||||
|
|
||||||
|
U low = a2b2;
|
||||||
|
high += (low += (a2b1 << halfbits)) < a2b2;
|
||||||
|
U tmp = low;
|
||||||
|
high += (low += (a1b2 << halfbits)) < tmp;
|
||||||
|
low = signed_rsh(low, shift);
|
||||||
|
low += signed_lsh(high, bits - shift);
|
||||||
|
return low;
|
||||||
|
}
|
||||||
|
}// namespace fp_internal
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//Implementation
|
||||||
|
//==========================================================================
|
||||||
|
template<unsigned f, typename I>
|
||||||
|
fp::q<f, I>::q(int u)
|
||||||
|
{
|
||||||
|
i = fp_internal::signed_lsh<f>((I) u);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<unsigned f, typename I>
|
||||||
|
fp::q<f, I>::q(unsigned u)
|
||||||
|
{
|
||||||
|
i = fp_internal::signed_lsh<f>((I) u);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<unsigned f, typename I>
|
||||||
|
fp::q<f, I>::q(uintmax_t s)
|
||||||
|
{
|
||||||
|
i = fp_internal::signed_lsh<f>((I) s);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<unsigned f, typename I>
|
||||||
|
fp::q<f, I>::q(double d)
|
||||||
|
{
|
||||||
|
int exp = 0;
|
||||||
|
double tmp = frexp(d, &exp);
|
||||||
|
i = lroundl(ldexp(tmp, exp + f));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<unsigned f, typename I>
|
||||||
|
fp::q<f, I>::q(long double d)
|
||||||
|
{
|
||||||
|
int exp = 0;
|
||||||
|
long double tmp = frexp(d, &exp);
|
||||||
|
i = llroundl(ldexp(tmp, exp + f));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<unsigned f, typename I>
|
||||||
|
template<unsigned fb>
|
||||||
|
fp::q<f, I>::q(q<fb, I> a)
|
||||||
|
{
|
||||||
|
i = fp_internal::signed_rsh<fb - f>(a.i);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<unsigned f, typename I>
|
||||||
|
fp::q<f, I>::operator int() const
|
||||||
|
{
|
||||||
|
return fp_internal::signed_rsh<f>(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<unsigned f, typename I>
|
||||||
|
fp::q<f, I>::operator float() const
|
||||||
|
{
|
||||||
|
return ldexpf((float) i, -(int) f);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<unsigned f, typename I>
|
||||||
|
fp::q<f, I>::operator double() const
|
||||||
|
{
|
||||||
|
return ldexp((double) i, -(int) f);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<unsigned f, typename I>
|
||||||
|
fp::q<f, I>::operator long double() const
|
||||||
|
{
|
||||||
|
return ldexp((long double) i, -(int) f);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<unsigned f, typename I>
|
||||||
|
template<unsigned fb>
|
||||||
|
fp::q<f, I>
|
||||||
|
fp::q<f, I>::operator+(q<fb, I> b) const
|
||||||
|
{
|
||||||
|
q<f, I> t;
|
||||||
|
t.i = i + fp_internal::signed_rsh<fb - f>(b.i);
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<unsigned f, typename I>
|
||||||
|
template<unsigned fb>
|
||||||
|
fp::q<f, I>
|
||||||
|
fp::q<f, I>::operator-(q<fb, I> b) const
|
||||||
|
{
|
||||||
|
q<f, I> t;
|
||||||
|
t.i = i - fp_internal::signed_rsh<fb - f>(b.i);
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<unsigned f, typename I>
|
||||||
|
template<unsigned fb>
|
||||||
|
fp::q<f, I>
|
||||||
|
fp::q<f, I>::operator*(q<fb, I> b) const
|
||||||
|
{
|
||||||
|
q<f, I> t;
|
||||||
|
t.i = fp_internal::mul_rsh<fb>(i, b.i);
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<unsigned f, typename I>
|
||||||
|
template<unsigned fb>
|
||||||
|
fp::q<f, I>
|
||||||
|
fp::q<f, I>::operator/(q<fb, I> b) const
|
||||||
|
{
|
||||||
|
static const I msb = (I) 1
|
||||||
|
<< (sizeof(I) * 8 - 1);//Most significant bit for the type
|
||||||
|
//Make b positive so that leading zeroes can be properly computed
|
||||||
|
I abs_b = b.i < 0 ? -b.i : b.i;
|
||||||
|
unsigned lz = fp_internal::clz(abs_b);//Amount of leading zeroes
|
||||||
|
//normalize b to [0.5, 1.0[, where all digits are after radix
|
||||||
|
I d = (abs_b << lz);
|
||||||
|
q<sizeof(I) * 8 + 1, typename std::make_unsigned<I>::type> e;
|
||||||
|
e.i = (~d + 1) << 1;//[0, 0.5[
|
||||||
|
//r is the reciprocal of d
|
||||||
|
q<sizeof(I) * 8 - 1, typename std::make_unsigned<I>::type> r(1);
|
||||||
|
for (unsigned i = 0; i < sizeof(I) - 1; ++i) {
|
||||||
|
r = r + r * e;
|
||||||
|
e = e * e;
|
||||||
|
}
|
||||||
|
q<f, I> t;
|
||||||
|
t.i = (I) fp_internal::mul_rsh(//adjust the radix point of (this*r)
|
||||||
|
r.i,
|
||||||
|
(typename std::make_unsigned<I>::type)(this->i < 0 ? -this->i
|
||||||
|
: this->i),
|
||||||
|
sizeof(i) * 16 - fb - lz - (d == msb) - 1);
|
||||||
|
t.i = (b.i < 0) ^ (this->i < 0) ? -t.i : t.i;//set correct sign
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<unsigned f, typename I>
|
||||||
|
template<unsigned fb>
|
||||||
|
fp::q<f, I>
|
||||||
|
fp::q<f, I>::operator%(q<fb, I> b) const
|
||||||
|
{
|
||||||
|
q<f, I> t;
|
||||||
|
t.i = i % fp_internal::signed_rsh<fb - f>(b.i);
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<unsigned f, typename I>
|
||||||
|
template<typename T>
|
||||||
|
fp::q<f, I>
|
||||||
|
fp::q<f, I>::operator+(T b) const
|
||||||
|
{
|
||||||
|
return *this + q<f, I>(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<unsigned f, typename I>
|
||||||
|
template<typename T>
|
||||||
|
fp::q<f, I>
|
||||||
|
fp::q<f, I>::operator-(T b) const
|
||||||
|
{
|
||||||
|
return *this - q<f, I>(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<unsigned f, typename I>
|
||||||
|
template<typename T>
|
||||||
|
fp::q<f, I>
|
||||||
|
fp::q<f, I>::operator*(T b) const
|
||||||
|
{
|
||||||
|
return *this * q<f, I>(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<unsigned f, typename I>
|
||||||
|
template<typename T>
|
||||||
|
fp::q<f, I>
|
||||||
|
fp::q<f, I>::operator/(T b) const
|
||||||
|
{
|
||||||
|
return *this / q<f, I>(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<unsigned f, typename I>
|
||||||
|
template<typename T>
|
||||||
|
fp::q<f, I>
|
||||||
|
fp::q<f, I>::operator%(T b) const
|
||||||
|
{
|
||||||
|
return *this % q<f, I>(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<unsigned f, typename I>
|
||||||
|
template<typename T>
|
||||||
|
fp::q<f, I> &
|
||||||
|
fp::q<f, I>::operator+=(T b)
|
||||||
|
{
|
||||||
|
return *this = *this + b;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<unsigned f, typename I>
|
||||||
|
template<typename T>
|
||||||
|
fp::q<f, I> &
|
||||||
|
fp::q<f, I>::operator-=(T b)
|
||||||
|
{
|
||||||
|
return *this = *this - b;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<unsigned f, typename I>
|
||||||
|
template<typename T>
|
||||||
|
fp::q<f, I> &
|
||||||
|
fp::q<f, I>::operator*=(T b)
|
||||||
|
{
|
||||||
|
return *this = *this * b;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<unsigned f, typename I>
|
||||||
|
template<typename T>
|
||||||
|
fp::q<f, I> &
|
||||||
|
fp::q<f, I>::operator/=(T b)
|
||||||
|
{
|
||||||
|
return *this = *this / b;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<unsigned f, typename I>
|
||||||
|
template<typename T>
|
||||||
|
fp::q<f, I> &
|
||||||
|
fp::q<f, I>::operator%=(T b)
|
||||||
|
{
|
||||||
|
return *this = *this % b;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<unsigned f, typename I>
|
||||||
|
fp::q<f, I>
|
||||||
|
fp::q<f, I>::operator-() const
|
||||||
|
{
|
||||||
|
q<f, I> t;
|
||||||
|
t.i = -i;
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<unsigned f, typename I>
|
||||||
|
template<unsigned fb>
|
||||||
|
fp::q<f, I> &
|
||||||
|
fp::q<f, I>::operator=(q<fb, I> b)
|
||||||
|
{
|
||||||
|
i = fp_internal::signed_rsh<fb - f>(b.i);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<unsigned f, typename I>
|
||||||
|
fp::q<f, I> &
|
||||||
|
fp::q<f, I>::operator=(int b)
|
||||||
|
{
|
||||||
|
i = fp_internal::signed_lsh<f>((I) b);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<unsigned f, typename I>
|
||||||
|
fp::q<f, I> &
|
||||||
|
fp::q<f, I>::operator=(double b)
|
||||||
|
{
|
||||||
|
int exp = 0;
|
||||||
|
double tmp = frexp(b, &exp);
|
||||||
|
i = llroundl(ldexp(tmp, exp + f));
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<unsigned f, typename I>
|
||||||
|
fp::q<f, I> &
|
||||||
|
fp::q<f, I>::operator=(long double b)
|
||||||
|
{
|
||||||
|
int exp = 0;
|
||||||
|
long double tmp = frexp(b, &exp);
|
||||||
|
i = llroundl(ldexp(tmp, exp + f));
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<unsigned f, typename I>
|
||||||
|
template<unsigned fb>
|
||||||
|
bool
|
||||||
|
fp::q<f, I>::operator>=(q<fb, I> b) const
|
||||||
|
{
|
||||||
|
static const unsigned bits = sizeof(I) * 8;
|
||||||
|
I ma = fp_internal::signed_rsh<f>(i);
|
||||||
|
I mb = fp_internal::signed_rsh<fb>(b.i);
|
||||||
|
return (ma > mb)
|
||||||
|
|| ((ma == mb)
|
||||||
|
&& ((typename std::make_unsigned<I>::type)
|
||||||
|
fp_internal::signed_lsh<bits - f>(i)
|
||||||
|
>= (typename std::make_unsigned<I>::type)
|
||||||
|
fp_internal::signed_lsh<bits - fb>(b.i)));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<unsigned f, typename I>
|
||||||
|
template<unsigned fb>
|
||||||
|
bool
|
||||||
|
fp::q<f, I>::operator>(q<fb, I> b) const
|
||||||
|
{
|
||||||
|
static const unsigned bits = sizeof(I) * 8;
|
||||||
|
I ma = fp_internal::signed_rsh<f>(i);
|
||||||
|
I mb = fp_internal::signed_rsh<fb>(b.i);
|
||||||
|
return (ma > mb)
|
||||||
|
|| ((ma == mb)
|
||||||
|
&& ((typename std::make_unsigned<I>::type)
|
||||||
|
fp_internal::signed_lsh<bits - f>(i)
|
||||||
|
> (typename std::make_unsigned<I>::type)
|
||||||
|
fp_internal::signed_lsh<bits - fb>(b.i)));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<unsigned f, typename I>
|
||||||
|
template<unsigned fb>
|
||||||
|
bool
|
||||||
|
fp::q<f, I>::operator<=(q<fb, I> b) const
|
||||||
|
{
|
||||||
|
static const unsigned bits = sizeof(I) * 8;
|
||||||
|
I ma = fp_internal::signed_rsh<f>(i);
|
||||||
|
I mb = fp_internal::signed_rsh<fb>(b.i);
|
||||||
|
return (ma < mb)
|
||||||
|
|| ((ma == mb)
|
||||||
|
&& ((typename std::make_unsigned<I>::type)
|
||||||
|
fp_internal::signed_lsh<bits - f>(i)
|
||||||
|
<= (typename std::make_unsigned<I>::type)
|
||||||
|
fp_internal::signed_lsh<bits - fb>(b.i)));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<unsigned f, typename I>
|
||||||
|
template<unsigned fb>
|
||||||
|
bool
|
||||||
|
fp::q<f, I>::operator<(q<fb, I> b) const
|
||||||
|
{
|
||||||
|
static const unsigned bits = sizeof(I) * 8;
|
||||||
|
I ma = fp_internal::signed_rsh<f>(i);
|
||||||
|
I mb = fp_internal::signed_rsh<fb>(b.i);
|
||||||
|
return (ma < mb)
|
||||||
|
|| ((ma == mb)
|
||||||
|
&& ((typename std::make_unsigned<I>::type)
|
||||||
|
fp_internal::signed_lsh<bits - f>(i)
|
||||||
|
< (typename std::make_unsigned<I>::type)
|
||||||
|
fp_internal::signed_lsh<bits - fb>(b.i)));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<unsigned f, typename I>
|
||||||
|
template<unsigned fb>
|
||||||
|
bool
|
||||||
|
fp::q<f, I>::operator==(q<fb, I> b) const
|
||||||
|
{
|
||||||
|
return fp_internal::signed_rsh<f - fb>(i) == b.i
|
||||||
|
&& fp_internal::signed_rsh<fb - f>(b.i) == i;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<unsigned f, typename I>
|
||||||
|
template<unsigned fb>
|
||||||
|
bool
|
||||||
|
fp::q<f, I>::operator!=(q<fb, I> b) const
|
||||||
|
{
|
||||||
|
return fp_internal::signed_rsh<f - fb>(i) != b.i
|
||||||
|
|| fp_internal::signed_rsh<fb - f>(b.i) != i;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<unsigned f, typename I>
|
||||||
|
fp::q<f, I>
|
||||||
|
fp::abs(q<f, I> x)
|
||||||
|
{
|
||||||
|
return (x.i >= 0 ? x : -x);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace sled {
|
||||||
|
template<unsigned bits, typename T>
|
||||||
|
using FixedPoint = fp::q<bits, T>;
|
||||||
|
|
||||||
|
using FixedFloat = fp::Q32_32;
|
||||||
|
|
||||||
|
template<unsigned bits, typename T>
|
||||||
|
inline const FixedPoint<bits, T>
|
||||||
|
conj(const FixedPoint<bits, T> &val)
|
||||||
|
{
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<unsigned bits, typename T>
|
||||||
|
inline const FixedPoint<bits, T>
|
||||||
|
real(const FixedPoint<bits, T> &val)
|
||||||
|
{
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<unsigned bits, typename T>
|
||||||
|
inline const FixedPoint<bits, T>
|
||||||
|
imag(const FixedPoint<bits, T> &val)
|
||||||
|
{
|
||||||
|
return 0.;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<unsigned bits, typename T>
|
||||||
|
inline const FixedPoint<bits, T>
|
||||||
|
abs(const FixedPoint<bits, T> &val)
|
||||||
|
{
|
||||||
|
return fp::abs(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<unsigned bits, typename T>
|
||||||
|
inline const FixedPoint<bits, T>
|
||||||
|
abs2(const FixedPoint<bits, T> &val)
|
||||||
|
{
|
||||||
|
return val * val;
|
||||||
|
}
|
||||||
|
|
||||||
|
}// namespace sled
|
||||||
|
|
||||||
|
template<unsigned bits, typename T>
|
||||||
|
struct fmt::formatter<sled::FixedPoint<bits, T>> : ostream_formatter {};
|
||||||
|
|
||||||
|
namespace Eigen {
|
||||||
|
template<unsigned bits, typename T>
|
||||||
|
struct NumTraits<sled::FixedPoint<bits, T>> : NumTraits<float> {
|
||||||
|
typedef sled::FixedPoint<bits, T> Real;
|
||||||
|
typedef sled::FixedPoint<bits, T> NonInteger;
|
||||||
|
typedef sled::FixedPoint<bits, T> Nested;
|
||||||
|
|
||||||
|
enum {
|
||||||
|
IsComplex = 0,
|
||||||
|
IsInteger = 0,
|
||||||
|
IsSigned = std::is_signed<T>::value,
|
||||||
|
RequireInitialization = 1,
|
||||||
|
ReadCost = 1,
|
||||||
|
AddCost = 3,
|
||||||
|
MulCost = 3
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename BinaryOp, unsigned bits, typename T>
|
||||||
|
struct ScalarBinaryOpTraits<sled::FixedPoint<bits, T>, float, BinaryOp> {
|
||||||
|
typedef sled::FixedPoint<bits, T> ReturnType;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename BinaryOp, unsigned bits, typename T>
|
||||||
|
struct ScalarBinaryOpTraits<float, sled::FixedPoint<bits, T>, BinaryOp> {
|
||||||
|
typedef sled::FixedPoint<bits, T> ReturnType;
|
||||||
|
};
|
||||||
|
|
||||||
|
}// namespace Eigen
|
||||||
|
|
||||||
|
#endif
|
69
include/sled/queue/circle_queue.h
Normal file
69
include/sled/queue/circle_queue.h
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
/**
|
||||||
|
* @file : circle_queue
|
||||||
|
* @created : 星期六 2 24, 2024 16:06:23 CST
|
||||||
|
* @license : MIT
|
||||||
|
**/
|
||||||
|
|
||||||
|
#ifndef CIRCLE_QUEUE_H
|
||||||
|
#define CIRCLE_QUEUE_H
|
||||||
|
|
||||||
|
#include "sled/log/log.h"
|
||||||
|
#include <array>
|
||||||
|
|
||||||
|
namespace sled {
|
||||||
|
|
||||||
|
template<typename T, size_t LEN>
|
||||||
|
class CircleQueue {
|
||||||
|
static_assert(LEN > 0, "LEN should be greater than 0.");
|
||||||
|
|
||||||
|
public:
|
||||||
|
void Push(T &&val)
|
||||||
|
{
|
||||||
|
ASSERT(size() < LEN, "queue is full.");
|
||||||
|
queue_.get(tail_) = std::move(val);
|
||||||
|
++tail_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Push(const T &val)
|
||||||
|
{
|
||||||
|
ASSERT(size() < LEN, "queue is full.");
|
||||||
|
queue_.get(tail_) = val;
|
||||||
|
++tail_;
|
||||||
|
}
|
||||||
|
|
||||||
|
T &Front()
|
||||||
|
{
|
||||||
|
ASSERT(!empty(), "queue is empty.");
|
||||||
|
return queue_.get(head_);
|
||||||
|
}
|
||||||
|
|
||||||
|
T &Back()
|
||||||
|
{
|
||||||
|
ASSERT(!empty(), "queue is empty.");
|
||||||
|
return queue_.get((tail_ + LEN) % (LEN + 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Pop()
|
||||||
|
{
|
||||||
|
ASSERT(!empty(), "queue is empty.");
|
||||||
|
head_ = (head_ + 1) % (LEN + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t size() const
|
||||||
|
{
|
||||||
|
return tail_ >= head_ ? tail_ - head_ : (LEN + 1) - (head_ - tail_);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool empty() const { return (tail_ + 1) % (LEN + 1) == head_; }
|
||||||
|
|
||||||
|
bool capacity() const { return LEN; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::array<T, LEN + 1> queue_;
|
||||||
|
size_t head_ = 0;
|
||||||
|
size_t tail_ = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
}// namespace sled
|
||||||
|
|
||||||
|
#endif// CIRCLE_QUEUE_H
|
@ -13,13 +13,13 @@ enum class RefCountReleaseStatus { kDroppedLastRef, kOtherRefsRemained };
|
|||||||
|
|
||||||
class RefCountInterface {
|
class RefCountInterface {
|
||||||
public:
|
public:
|
||||||
virtual void AddRef() const = 0;
|
virtual void AddRef() const = 0;
|
||||||
virtual RefCountReleaseStatus Release() const = 0;
|
virtual RefCountReleaseStatus Release() const = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual ~RefCountInterface() = default;
|
virtual ~RefCountInterface() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace sled
|
}// namespace sled
|
||||||
|
|
||||||
#endif // REF_COUNT_H
|
#endif// REF_COUNT_H
|
||||||
|
24
include/sled/reflect/reflect.h
Normal file
24
include/sled/reflect/reflect.h
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
/**
|
||||||
|
* @file : reflect
|
||||||
|
* @created : 星期一 2 26, 2024 09:55:19 CST
|
||||||
|
* @license : MIT
|
||||||
|
**/
|
||||||
|
|
||||||
|
#ifndef SLED_REFLECT_REFLECT_H
|
||||||
|
#define SLED_REFLECT_REFLECT_H
|
||||||
|
|
||||||
|
#if !defined(__NO_META_PARSER__) && !defined(__META_PARSER__)
|
||||||
|
#define __META_PARSER__
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__META_PARSER__)
|
||||||
|
#define REFLECT_CLASS __attribute__((annotate("reflect-class")))
|
||||||
|
#define PROPERTY() __attribute__((annotate("reflect-property")))
|
||||||
|
#define METHOD() __attribute__((annotate("reflect-method")))
|
||||||
|
#else
|
||||||
|
#define REFLECT_CLASS
|
||||||
|
#define PROPERTY()
|
||||||
|
#define METHOD()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif// SLED_REFLECT_REFLECT_H
|
@ -84,6 +84,7 @@ public:
|
|||||||
scoped_refptr<T> &operator=(const scoped_refptr<T> &&r) noexcept
|
scoped_refptr<T> &operator=(const scoped_refptr<T> &&r) noexcept
|
||||||
{
|
{
|
||||||
scoped_refptr<T>(std::move(r)).swap(*this);
|
scoped_refptr<T>(std::move(r)).swap(*this);
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename U>
|
template<typename U>
|
||||||
|
@ -17,10 +17,12 @@ namespace sled {
|
|||||||
namespace internal {
|
namespace internal {
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct HasLockAndUnlock {
|
struct HasLockAndUnlock {
|
||||||
template<typename TClass,
|
template<typename U,
|
||||||
decltype(std::declval<TClass>().Lock()) * = nullptr,
|
decltype(std::declval<U>().Lock()) * = nullptr,
|
||||||
decltype(std::declval<TClass>().Unlock()) * = nullptr>
|
decltype(std::declval<U>().Unlock()) * = nullptr>
|
||||||
static int Test(T);
|
static int Test(int);
|
||||||
|
|
||||||
|
template<typename>
|
||||||
static char Test(...);
|
static char Test(...);
|
||||||
|
|
||||||
static constexpr bool value =
|
static constexpr bool value =
|
||||||
@ -69,45 +71,50 @@ template<typename TLock,
|
|||||||
typename std::enable_if<internal::HasLockAndUnlock<TLock>::value,
|
typename std::enable_if<internal::HasLockAndUnlock<TLock>::value,
|
||||||
TLock>::type * = nullptr>
|
TLock>::type * = nullptr>
|
||||||
class LockGuard final {
|
class LockGuard final {
|
||||||
|
public:
|
||||||
LockGuard(const LockGuard &) = delete;
|
LockGuard(const LockGuard &) = delete;
|
||||||
LockGuard &operator=(const LockGuard &) = delete;
|
LockGuard &operator=(const LockGuard &) = delete;
|
||||||
|
|
||||||
explicit LockGuard(TLock *lock) : lock_(lock) { lock_->Lock(); };
|
explicit LockGuard(TLock *lock) : mutex_(lock) { mutex_->Lock(); };
|
||||||
|
|
||||||
~LockGuard() { lock_->Unlock(); };
|
~LockGuard() { mutex_->Unlock(); };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TLock *lock_;
|
TLock *mutex_;
|
||||||
|
friend class ConditionVariable;
|
||||||
};
|
};
|
||||||
|
|
||||||
class MutexLock final {
|
using MutexLock = LockGuard<Mutex>;
|
||||||
public:
|
using RecursiveMutexLock = LockGuard<RecursiveMutex>;
|
||||||
MutexLock(const MutexLock &) = delete;
|
|
||||||
MutexLock &operator=(const MutexLock &) = delete;
|
|
||||||
|
|
||||||
explicit MutexLock(Mutex *mutex) : mutex_(mutex) { mutex->Lock(); }
|
// class MutexLock final {
|
||||||
|
// public:
|
||||||
~MutexLock() { mutex_->Unlock(); }
|
// MutexLock(const MutexLock &) = delete;
|
||||||
|
// MutexLock &operator=(const MutexLock &) = delete;
|
||||||
private:
|
//
|
||||||
Mutex *mutex_;
|
// explicit MutexLock(Mutex *mutex) : mutex_(mutex) { mutex->Lock(); }
|
||||||
};
|
//
|
||||||
|
// ~MutexLock() { mutex_->Unlock(); }
|
||||||
class RecursiveMutexLock final {
|
//
|
||||||
public:
|
// private:
|
||||||
RecursiveMutexLock(const RecursiveMutexLock &) = delete;
|
// Mutex *mutex_;
|
||||||
RecursiveMutexLock &operator=(const RecursiveMutexLock &) = delete;
|
// };
|
||||||
|
//
|
||||||
explicit RecursiveMutexLock(RecursiveMutex *mutex) : mutex_(mutex)
|
// class RecursiveMutexLock final {
|
||||||
{
|
// public:
|
||||||
mutex->Lock();
|
// RecursiveMutexLock(const RecursiveMutexLock &) = delete;
|
||||||
}
|
// RecursiveMutexLock &operator=(const RecursiveMutexLock &) = delete;
|
||||||
|
//
|
||||||
~RecursiveMutexLock() { mutex_->Unlock(); }
|
// explicit RecursiveMutexLock(RecursiveMutex *mutex) : mutex_(mutex)
|
||||||
|
// {
|
||||||
private:
|
// mutex->Lock();
|
||||||
RecursiveMutex *mutex_;
|
// }
|
||||||
};
|
//
|
||||||
|
// ~RecursiveMutexLock() { mutex_->Unlock(); }
|
||||||
|
//
|
||||||
|
// private:
|
||||||
|
// RecursiveMutex *mutex_;
|
||||||
|
// };
|
||||||
|
|
||||||
class ConditionVariable final {
|
class ConditionVariable final {
|
||||||
public:
|
public:
|
||||||
@ -117,17 +124,18 @@ public:
|
|||||||
ConditionVariable &operator=(const ConditionVariable &) = delete;
|
ConditionVariable &operator=(const ConditionVariable &) = delete;
|
||||||
|
|
||||||
template<typename Predicate>
|
template<typename Predicate>
|
||||||
inline bool Wait(Mutex *mutex, Predicate pred)
|
inline bool Wait(LockGuard<Mutex> &guard, Predicate pred)
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> lock(mutex->impl_, std::adopt_lock);
|
std::unique_lock<std::mutex> lock(guard.mutex_->impl_, std::adopt_lock);
|
||||||
cv_.wait(lock, pred);
|
cv_.wait(lock, pred);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Predicate>
|
template<typename Predicate>
|
||||||
inline bool WaitFor(Mutex *mutex, TimeDelta timeout, Predicate pred)
|
inline bool
|
||||||
|
WaitFor(LockGuard<Mutex> &guard, TimeDelta timeout, Predicate pred)
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> lock(mutex->impl_, std::adopt_lock);
|
std::unique_lock<std::mutex> lock(guard.mutex_->impl_, std::adopt_lock);
|
||||||
if (timeout == kForever) {
|
if (timeout == kForever) {
|
||||||
cv_.wait(lock, pred);
|
cv_.wait(lock, pred);
|
||||||
return true;
|
return true;
|
||||||
|
@ -7,13 +7,30 @@
|
|||||||
#ifndef LOCATION_H
|
#ifndef LOCATION_H
|
||||||
#define LOCATION_H
|
#define LOCATION_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
namespace sled {
|
namespace sled {
|
||||||
|
|
||||||
class Location {
|
class Location final {
|
||||||
public:
|
public:
|
||||||
static Location Current() { return Location(); }
|
Location() = delete;
|
||||||
|
|
||||||
|
static Location Current(const char *file_name = __builtin_FILE(),
|
||||||
|
int file_line = __builtin_LINE(),
|
||||||
|
const char *function = __builtin_FUNCTION());
|
||||||
|
|
||||||
|
std::string ToString() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Location(const char *file_name, int file_line, const char *function);
|
||||||
|
|
||||||
|
const char *file_name;
|
||||||
|
int file_line;
|
||||||
|
const char *function;
|
||||||
};
|
};
|
||||||
|
|
||||||
}// namespace sled
|
}// namespace sled
|
||||||
|
|
||||||
|
#define SLED_FROM_HERE sled::Location::Current();
|
||||||
|
|
||||||
#endif// LOCATION_H
|
#endif// LOCATION_H
|
||||||
|
@ -13,9 +13,12 @@ namespace sled {
|
|||||||
static const int64_t kNumMillisecsPerSec = 1000;
|
static const int64_t kNumMillisecsPerSec = 1000;
|
||||||
static const int64_t kNumMicrosecsPerSec = 1000000;
|
static const int64_t kNumMicrosecsPerSec = 1000000;
|
||||||
static const int64_t kNumNanosecsPerSec = 1000000000;
|
static const int64_t kNumNanosecsPerSec = 1000000000;
|
||||||
static const int64_t kNumMicrosecsPerMillisec = kNumMicrosecsPerSec / kNumMillisecsPerSec;
|
static const int64_t kNumMicrosecsPerMillisec =
|
||||||
static const int64_t kNumNanosecsPerMillisec = kNumNanosecsPerSec / kNumMillisecsPerSec;
|
kNumMicrosecsPerSec / kNumMillisecsPerSec;
|
||||||
static const int64_t kNumNanosecsPerMicrosec = kNumNanosecsPerSec / kNumMicrosecsPerSec;
|
static const int64_t kNumNanosecsPerMillisec =
|
||||||
|
kNumNanosecsPerSec / kNumMillisecsPerSec;
|
||||||
|
static const int64_t kNumNanosecsPerMicrosec =
|
||||||
|
kNumNanosecsPerSec / kNumMicrosecsPerSec;
|
||||||
constexpr int64_t kNtpJan1970Millisecs = 2208988800 * kNumMillisecsPerSec;
|
constexpr int64_t kNtpJan1970Millisecs = 2208988800 * kNumMillisecsPerSec;
|
||||||
|
|
||||||
class ClockInterface {
|
class ClockInterface {
|
||||||
|
@ -77,7 +77,10 @@ public:
|
|||||||
return ToFractionOr<1000>(fallback_value);
|
return ToFractionOr<1000>(fallback_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr int64_t us_or(int64_t fallback_value) const { return ToValueOr(fallback_value); }
|
constexpr int64_t us_or(int64_t fallback_value) const
|
||||||
|
{
|
||||||
|
return ToValueOr(fallback_value);
|
||||||
|
}
|
||||||
|
|
||||||
Timestamp operator+(const TimeDelta delta) const
|
Timestamp operator+(const TimeDelta delta) const
|
||||||
{
|
{
|
||||||
|
29
src/include/sled/ubench.h
Normal file
29
src/include/sled/ubench.h
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
/**
|
||||||
|
* @file : {{FILE}}
|
||||||
|
* @created : {{TIMESTAMP}}
|
||||||
|
* @license : {{LICENSE}}
|
||||||
|
**/
|
||||||
|
|
||||||
|
#ifndef{{MACRO_GUARD } }
|
||||||
|
#define{{MACRO_GUARD } }
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
{
|
||||||
|
CURSOR
|
||||||
|
}
|
||||||
|
}// namespace
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
class {
|
||||||
|
{
|
||||||
|
CAMEL_CLASS
|
||||||
|
}
|
||||||
|
} {
|
||||||
|
public:
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}// namespace
|
||||||
|
|
||||||
|
#endif// {{MACRO_GUARD}}
|
@ -1,8 +1,53 @@
|
|||||||
#include "sled/log/log.h"
|
#include "sled/log/log.h"
|
||||||
|
#include "sled/time_utils.h"
|
||||||
|
#include <ctime>
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
namespace sled {
|
namespace sled {
|
||||||
|
|
||||||
|
class ScopedAtomicWaiter {
|
||||||
|
public:
|
||||||
|
ScopedAtomicWaiter(std::atomic_bool &flag) : flag_(flag)
|
||||||
|
{
|
||||||
|
bool old = flag_.load();
|
||||||
|
while (!flag_.compare_exchange_weak(old, false)) { continue; }
|
||||||
|
}
|
||||||
|
|
||||||
|
~ScopedAtomicWaiter() { flag_.store(true); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::atomic_bool &flag_;
|
||||||
|
};
|
||||||
|
|
||||||
|
static std::string
|
||||||
|
GetCurrentUTCTime()
|
||||||
|
{
|
||||||
|
#if true
|
||||||
|
// struct timespec tp;
|
||||||
|
// clock_gettime(CLOCK_REALTIME, &tp);
|
||||||
|
// int64_t now = tp.tv_sec * kNumNanosecsPerSec + tp.tv_nsec;
|
||||||
|
// std::time_t t = tp.tv_sec;
|
||||||
|
const int64_t now = TimeUTCNanos();
|
||||||
|
std::time_t t = now / kNumNanosecsPerSec;
|
||||||
|
#else
|
||||||
|
std::time_t t = std::time(nullptr);
|
||||||
|
#endif
|
||||||
|
std::tm tm = *std::gmtime(&t);
|
||||||
|
char buf[64];
|
||||||
|
std::strftime(buf, sizeof(buf), "%Y-%m-%dT%H:%M:%S", &tm);
|
||||||
|
std::string result(buf);
|
||||||
|
#if true
|
||||||
|
return result
|
||||||
|
+ fmt::format(".{:03d}Z",
|
||||||
|
static_cast<int>(now % kNumNanosecsPerSec)
|
||||||
|
/ kNumNanosecsPerMillisec);
|
||||||
|
#else
|
||||||
|
return result + "Z";
|
||||||
|
#endif
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Log(LogLevel level,
|
Log(LogLevel level,
|
||||||
const char *tag,
|
const char *tag,
|
||||||
@ -12,11 +57,13 @@ Log(LogLevel level,
|
|||||||
const char *func_name,
|
const char *func_name,
|
||||||
...)
|
...)
|
||||||
{
|
{
|
||||||
|
static std::atomic_bool allow(true);
|
||||||
|
ScopedAtomicWaiter waiter(allow);
|
||||||
int len = file_name ? strlen(file_name) : 0;
|
int len = file_name ? strlen(file_name) : 0;
|
||||||
while (len > 0 && file_name[len - 1] != '/') { len--; }
|
while (len > 0 && file_name[len - 1] != '/') { len--; }
|
||||||
|
|
||||||
auto msg = fmt::format("{}:{}@{} {} {}", file_name + len, line, func_name,
|
auto msg = fmt::format("{} {}:{}@{} {} {}", GetCurrentUTCTime(),
|
||||||
tag, fmt);
|
file_name + len, line, func_name, tag, fmt);
|
||||||
std::cout << msg << std::endl;
|
std::cout << msg << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#include "sled/network/physical_socket_server.h"
|
#include "sled/network/physical_socket_server.h"
|
||||||
|
#include "sled/log/log.h"
|
||||||
#include "sled/network/async_resolver.h"
|
#include "sled/network/async_resolver.h"
|
||||||
#include "sled/network/socket.h"
|
#include "sled/network/socket.h"
|
||||||
#include "sled/synchronization/event.h"
|
#include "sled/synchronization/event.h"
|
||||||
@ -155,11 +156,11 @@ PhysicalSocketServer::Update(Dispatcher *pdispatcher)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
PhysicalSocketServer::ToCmsWait(TimeDelta max_wait_duration)
|
PhysicalSocketServer::ToCusWait(TimeDelta max_wait_duration)
|
||||||
{
|
{
|
||||||
return max_wait_duration == Event::kForever
|
return max_wait_duration == Event::kForever
|
||||||
? kForeverMs
|
? kForeverMs
|
||||||
: max_wait_duration.RoundUpTo(TimeDelta::Millis(1)).ms();
|
: max_wait_duration.RoundUpTo(TimeDelta::Micros(1)).us();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
@ -167,9 +168,9 @@ PhysicalSocketServer::Wait(TimeDelta max_wait_duration, bool process_io)
|
|||||||
|
|
||||||
{
|
{
|
||||||
ScopedSetTrue s(&waiting_);
|
ScopedSetTrue s(&waiting_);
|
||||||
const int cmsWait = ToCmsWait(max_wait_duration);
|
const int64_t cusWait = ToCusWait(max_wait_duration);
|
||||||
|
|
||||||
return WaitSelect(cmsWait, process_io);
|
return WaitSelect(cusWait, process_io);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -216,16 +217,16 @@ ProcessEvents(Dispatcher *pdispatcher,
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
PhysicalSocketServer::WaitSelect(int cmsWait, bool process_io)
|
PhysicalSocketServer::WaitSelect(int64_t cusWait, bool process_io)
|
||||||
{
|
{
|
||||||
struct timeval *ptvWait = nullptr;
|
struct timeval *ptvWait = nullptr;
|
||||||
struct timeval tvWait;
|
struct timeval tvWait;
|
||||||
int64_t stop_us;
|
int64_t stop_us;
|
||||||
if (cmsWait != kForeverMs) {
|
if (cusWait != kForeverMs) {
|
||||||
tvWait.tv_sec = cmsWait / 1000;
|
tvWait.tv_sec = cusWait / sled::kNumMicrosecsPerSec;
|
||||||
tvWait.tv_usec = (cmsWait % 1000) * 1000;
|
tvWait.tv_usec = (cusWait % sled::kNumMicrosecsPerSec);
|
||||||
ptvWait = &tvWait;
|
ptvWait = &tvWait;
|
||||||
stop_us = TimeMicros() + cmsWait * 1000;
|
stop_us = TimeMicros() + cusWait;
|
||||||
}
|
}
|
||||||
|
|
||||||
fd_set fdsRead;
|
fd_set fdsRead;
|
||||||
|
@ -8,6 +8,8 @@
|
|||||||
#include "sled/network/physical_socket_server.h"
|
#include "sled/network/physical_socket_server.h"
|
||||||
|
|
||||||
namespace sled {
|
namespace sled {
|
||||||
|
constexpr TimeDelta SocketServer::kForever;
|
||||||
|
|
||||||
std::unique_ptr<sled::SocketServer>
|
std::unique_ptr<sled::SocketServer>
|
||||||
CreateDefaultSocketServer()
|
CreateDefaultSocketServer()
|
||||||
{
|
{
|
||||||
|
@ -30,9 +30,9 @@ Event::Reset()
|
|||||||
bool
|
bool
|
||||||
Event::Wait(TimeDelta give_up_after, TimeDelta warn_after)
|
Event::Wait(TimeDelta give_up_after, TimeDelta warn_after)
|
||||||
{
|
{
|
||||||
MutexLock lock(&mutex_);
|
MutexLock guard(&mutex_);
|
||||||
bool wait_success =
|
bool wait_success =
|
||||||
cv_.WaitFor(&mutex_, give_up_after, [&] { return event_status_; });
|
cv_.WaitFor(guard, give_up_after, [&] { return event_status_; });
|
||||||
if (!wait_success) { return false; }
|
if (!wait_success) { return false; }
|
||||||
|
|
||||||
if (!is_manual_reset_) { event_status_ = false; }
|
if (!is_manual_reset_) { event_status_ = false; }
|
||||||
|
23
src/system/location.cc
Normal file
23
src/system/location.cc
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#include "sled/system/location.h"
|
||||||
|
|
||||||
|
namespace sled {
|
||||||
|
|
||||||
|
Location
|
||||||
|
Location::Current(const char *file_name, int file_line, const char *function)
|
||||||
|
{
|
||||||
|
return Location(file_name, file_line, function);
|
||||||
|
}
|
||||||
|
|
||||||
|
Location::Location(const char *file_name, int file_line, const char *function)
|
||||||
|
: file_name(file_name),
|
||||||
|
file_line(file_line),
|
||||||
|
function(function)
|
||||||
|
{}
|
||||||
|
|
||||||
|
std::string
|
||||||
|
Location::ToString() const
|
||||||
|
{
|
||||||
|
return std::string(file_name) + ":" + std::to_string(file_line) + " "
|
||||||
|
+ function;
|
||||||
|
}
|
||||||
|
}// namespace sled
|
@ -8,7 +8,8 @@ SystemTimeNanos()
|
|||||||
int64_t ticks;
|
int64_t ticks;
|
||||||
struct timespec ts;
|
struct timespec ts;
|
||||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||||
ticks = kNumNanosecsPerSec * static_cast<int64_t>(ts.tv_sec) + static_cast<int64_t>(ts.tv_nsec);
|
ticks = kNumNanosecsPerSec * static_cast<int64_t>(ts.tv_sec)
|
||||||
|
+ static_cast<int64_t>(ts.tv_nsec);
|
||||||
return ticks;
|
return ticks;
|
||||||
}
|
}
|
||||||
}// namespace sled
|
}// namespace sled
|
||||||
|
@ -22,13 +22,13 @@ TimeMillis()
|
|||||||
int64_t
|
int64_t
|
||||||
TimeMicros()
|
TimeMicros()
|
||||||
{
|
{
|
||||||
if (g_clock) { return g_clock->TimeNanos(); }
|
|
||||||
return TimeNanos() / kNumNanosecsPerMicrosec;
|
return TimeNanos() / kNumNanosecsPerMicrosec;
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t
|
int64_t
|
||||||
TimeNanos()
|
TimeNanos()
|
||||||
{
|
{
|
||||||
|
if (g_clock) { return g_clock->TimeNanos(); }
|
||||||
return SystemTimeNanos();
|
return SystemTimeNanos();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,49 +51,10 @@ TimeDiff(int32_t later, int32_t earlier)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int64_t
|
int64_t
|
||||||
TmToSeconds(const tm &tm)
|
TmToSeconds(const tm &tm_val)
|
||||||
{
|
{
|
||||||
static short int mdays[12] = {31, 28, 31, 30, 31, 30,
|
struct tm *ptm = const_cast<struct tm *>(&tm_val);
|
||||||
31, 31, 30, 31, 30, 31};
|
return ::timegm(ptm);
|
||||||
static short int cumul_mdays[12] = {0, 31, 59, 90, 120, 151,
|
|
||||||
181, 212, 243, 273, 304, 334};
|
|
||||||
int year = tm.tm_year + 1900;
|
|
||||||
int month = tm.tm_mon;
|
|
||||||
int day = tm.tm_mday - 1;// Make 0-based like the rest.
|
|
||||||
int hour = tm.tm_hour;
|
|
||||||
int min = tm.tm_min;
|
|
||||||
int sec = tm.tm_sec;
|
|
||||||
|
|
||||||
bool expiry_in_leap_year =
|
|
||||||
(year % 4 == 0 && (year % 100 != 0 || year % 400 == 0));
|
|
||||||
|
|
||||||
if (year < 1970) return -1;
|
|
||||||
if (month < 0 || month > 11) return -1;
|
|
||||||
if (day < 0
|
|
||||||
|| day >= mdays[month] + (expiry_in_leap_year && month == 2 - 1))
|
|
||||||
return -1;
|
|
||||||
if (hour < 0 || hour > 23) return -1;
|
|
||||||
if (min < 0 || min > 59) return -1;
|
|
||||||
if (sec < 0 || sec > 59) return -1;
|
|
||||||
|
|
||||||
day += cumul_mdays[month];
|
|
||||||
|
|
||||||
// Add number of leap days between 1970 and the expiration year, inclusive.
|
|
||||||
day += ((year / 4 - 1970 / 4) - (year / 100 - 1970 / 100)
|
|
||||||
+ (year / 400 - 1970 / 400));
|
|
||||||
|
|
||||||
// We will have added one day too much above if expiration is during a leap
|
|
||||||
// year, and expiration is in January or February.
|
|
||||||
if (expiry_in_leap_year && month <= 2 - 1)// `month` is zero based.
|
|
||||||
day -= 1;
|
|
||||||
|
|
||||||
// Combine all variables into seconds from 1970-01-01 00:00 (except `month`
|
|
||||||
// which was accumulated into `day` above).
|
|
||||||
return (((static_cast<int64_t>(year - 1970) * 365 + day) * 24 + hour) * 60
|
|
||||||
+ min)
|
|
||||||
* 60
|
|
||||||
+ sec;
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t
|
int64_t
|
||||||
@ -118,11 +79,9 @@ int64_t
|
|||||||
TimeUTCNanos()
|
TimeUTCNanos()
|
||||||
{
|
{
|
||||||
if (g_clock) { return g_clock->TimeNanos() / kNumNanosecsPerMicrosec; }
|
if (g_clock) { return g_clock->TimeNanos() / kNumNanosecsPerMicrosec; }
|
||||||
struct timeval time;
|
struct timespec ts;
|
||||||
gettimeofday(&time, nullptr);
|
clock_gettime(CLOCK_REALTIME, &ts);
|
||||||
int64_t nanosecs =
|
return ts.tv_nsec + ts.tv_sec * kNumNanosecsPerSec;
|
||||||
static_cast<int64_t>(time.tv_sec) * kNumNanosecsPerSec + time.tv_usec;
|
|
||||||
return nanosecs;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}// namespace sled
|
}// namespace sled
|
||||||
|
Loading…
Reference in New Issue
Block a user