From 46976d53f9ccb04187790114e1fcbe98b25c5e6a Mon Sep 17 00:00:00 2001 From: tqcq <99722391+tqcq@users.noreply.github.com> Date: Fri, 23 Feb 2024 18:12:27 +0800 Subject: [PATCH 1/8] feat add todo --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index e69de29..8569112 100644 --- a/README.md +++ b/README.md @@ -0,0 +1,5 @@ +# sled + +- [ ] add log module +- [ ] add http module(cpp-httplib) +- [ ] add ORM module From b1a9a8a17fa028f6d2ee13582cce70671f0bf0d4 Mon Sep 17 00:00:00 2001 From: tqcq <99722391+tqcq@users.noreply.github.com> Date: Sat, 24 Feb 2024 10:31:28 +0800 Subject: [PATCH 2/8] feat fix mutux --- .gitignore | 4 ++ CMakeLists.txt | 7 ++++ benchmark/strings/base64_benchmark.cc | 59 +++++++++++++++++++++++++++ include/sled/byte_order.h | 25 ++++++++++++ include/sled/ref_count.h | 10 ++--- include/sled/synchronization/mutex.h | 13 +++--- include/sled/units/timestamp.h | 5 ++- src/include/sled/ubench.h | 29 +++++++++++++ 8 files changed, 141 insertions(+), 11 deletions(-) create mode 100644 .gitignore create mode 100644 benchmark/strings/base64_benchmark.cc create mode 100644 src/include/sled/ubench.h diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c7e98b2 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +.cache/ +out/ +build/ +compile_commands.json diff --git a/CMakeLists.txt b/CMakeLists.txt index 1213198..e6d0776 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -50,3 +50,10 @@ target_include_directories( PRIVATE src) 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) diff --git a/benchmark/strings/base64_benchmark.cc b/benchmark/strings/base64_benchmark.cc new file mode 100644 index 0000000..c9e2740 --- /dev/null +++ b/benchmark/strings/base64_benchmark.cc @@ -0,0 +1,59 @@ +#include +#include +#include +#include + +struct strings {}; + +static std::string +AllocRandomString(sled::Random &random, int len) +{ + std::stringstream ss; + for (int i = len; i > 0; i--) { ss << random.Rand(); } + return ss.str(); +} + +void +BenchmarkBase64Encode(benchmark::State &state) +{ + state.PauseTiming(); + sled::Random random(2393); + std::vector 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), + }); +*/ diff --git a/include/sled/byte_order.h b/include/sled/byte_order.h index cabf431..c8b4299 100644 --- a/include/sled/byte_order.h +++ b/include/sled/byte_order.h @@ -1,5 +1,30 @@ #include +#if defined(__APPLE__) + +#include + +#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 HostToNetwork16(uint16_t n) { diff --git a/include/sled/ref_count.h b/include/sled/ref_count.h index 7f97ad4..4a49f0a 100644 --- a/include/sled/ref_count.h +++ b/include/sled/ref_count.h @@ -13,13 +13,13 @@ enum class RefCountReleaseStatus { kDroppedLastRef, kOtherRefsRemained }; class RefCountInterface { public: - virtual void AddRef() const = 0; - virtual RefCountReleaseStatus Release() const = 0; + virtual void AddRef() const = 0; + virtual RefCountReleaseStatus Release() const = 0; protected: - virtual ~RefCountInterface() = default; + virtual ~RefCountInterface() = default; }; -} // namespace sled +}// namespace sled -#endif // REF_COUNT_H +#endif// REF_COUNT_H diff --git a/include/sled/synchronization/mutex.h b/include/sled/synchronization/mutex.h index eeeb1ee..23959da 100644 --- a/include/sled/synchronization/mutex.h +++ b/include/sled/synchronization/mutex.h @@ -17,13 +17,15 @@ namespace sled { namespace internal { template struct HasLockAndUnlock { - template().Lock()) * = nullptr, - decltype(std::declval().Unlock()) * = nullptr> - static int Test(T); + template().Lock()) * = nullptr, + decltype(std::declval().Unlock()) * = nullptr> + static int Test(int); + + template static char Test(...); - static constexpr bool value = + static constexpr bool value = std::is_same(0)), int>::value; }; }// namespace internal @@ -69,6 +71,7 @@ template::value, TLock>::type * = nullptr> class LockGuard final { +public: LockGuard(const LockGuard &) = delete; LockGuard &operator=(const LockGuard &) = delete; diff --git a/include/sled/units/timestamp.h b/include/sled/units/timestamp.h index 027be43..fba4906 100644 --- a/include/sled/units/timestamp.h +++ b/include/sled/units/timestamp.h @@ -77,7 +77,10 @@ public: 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 { diff --git a/src/include/sled/ubench.h b/src/include/sled/ubench.h new file mode 100644 index 0000000..17c211a --- /dev/null +++ b/src/include/sled/ubench.h @@ -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}} From 9cc2ec86b722b2332112a9171431b0326a4f8bfe Mon Sep 17 00:00:00 2001 From: tqcq <99722391+tqcq@users.noreply.github.com> Date: Sat, 24 Feb 2024 10:40:15 +0800 Subject: [PATCH 3/8] fix replace MutexLock by LockGuard --- include/sled/synchronization/mutex.h | 75 +++++++++++++++------------- src/synchronization/event.cc | 2 +- 2 files changed, 41 insertions(+), 36 deletions(-) diff --git a/include/sled/synchronization/mutex.h b/include/sled/synchronization/mutex.h index 23959da..95a5766 100644 --- a/include/sled/synchronization/mutex.h +++ b/include/sled/synchronization/mutex.h @@ -25,7 +25,7 @@ struct HasLockAndUnlock { template static char Test(...); - static constexpr bool value = + static constexpr bool value = std::is_same(0)), int>::value; }; }// namespace internal @@ -75,42 +75,46 @@ public: LockGuard(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: - TLock *lock_; + TLock *mutex_; + friend class ConditionVariable; }; -class MutexLock final { -public: - MutexLock(const MutexLock &) = delete; - MutexLock &operator=(const MutexLock &) = delete; +using MutexLock = LockGuard; +using RecursiveMutexLock = LockGuard; - explicit MutexLock(Mutex *mutex) : mutex_(mutex) { mutex->Lock(); } - - ~MutexLock() { mutex_->Unlock(); } - -private: - Mutex *mutex_; -}; - -class RecursiveMutexLock final { -public: - RecursiveMutexLock(const RecursiveMutexLock &) = delete; - RecursiveMutexLock &operator=(const RecursiveMutexLock &) = delete; - - explicit RecursiveMutexLock(RecursiveMutex *mutex) : mutex_(mutex) - { - mutex->Lock(); - } - - ~RecursiveMutexLock() { mutex_->Unlock(); } - -private: - RecursiveMutex *mutex_; -}; +// class MutexLock final { +// public: +// MutexLock(const MutexLock &) = delete; +// MutexLock &operator=(const MutexLock &) = delete; +// +// explicit MutexLock(Mutex *mutex) : mutex_(mutex) { mutex->Lock(); } +// +// ~MutexLock() { mutex_->Unlock(); } +// +// private: +// Mutex *mutex_; +// }; +// +// class RecursiveMutexLock final { +// public: +// RecursiveMutexLock(const RecursiveMutexLock &) = delete; +// RecursiveMutexLock &operator=(const RecursiveMutexLock &) = delete; +// +// explicit RecursiveMutexLock(RecursiveMutex *mutex) : mutex_(mutex) +// { +// mutex->Lock(); +// } +// +// ~RecursiveMutexLock() { mutex_->Unlock(); } +// +// private: +// RecursiveMutex *mutex_; +// }; class ConditionVariable final { public: @@ -120,17 +124,18 @@ public: ConditionVariable &operator=(const ConditionVariable &) = delete; template - inline bool Wait(Mutex *mutex, Predicate pred) + inline bool Wait(LockGuard &guard, Predicate pred) { - std::unique_lock lock(mutex->impl_, std::adopt_lock); + std::unique_lock lock(guard.mutex_->impl_, std::adopt_lock); cv_.wait(lock, pred); return true; } template - inline bool WaitFor(Mutex *mutex, TimeDelta timeout, Predicate pred) + inline bool + WaitFor(LockGuard &guard, TimeDelta timeout, Predicate pred) { - std::unique_lock lock(mutex->impl_, std::adopt_lock); + std::unique_lock lock(guard.mutex_->impl_, std::adopt_lock); if (timeout == kForever) { cv_.wait(lock, pred); return true; diff --git a/src/synchronization/event.cc b/src/synchronization/event.cc index 95744cd..28e09a6 100644 --- a/src/synchronization/event.cc +++ b/src/synchronization/event.cc @@ -32,7 +32,7 @@ Event::Wait(TimeDelta give_up_after, TimeDelta warn_after) { MutexLock lock(&mutex_); bool wait_success = - cv_.WaitFor(&mutex_, give_up_after, [&] { return event_status_; }); + cv_.WaitFor(lock, give_up_after, [&] { return event_status_; }); if (!wait_success) { return false; } if (!is_manual_reset_) { event_status_ = false; } From 37cbad0b993caedf1960e997636c9884421b7008 Mon Sep 17 00:00:00 2001 From: tqcq <99722391+tqcq@users.noreply.github.com> Date: Sat, 24 Feb 2024 10:44:01 +0800 Subject: [PATCH 4/8] fix undefined ref --- src/network/socket_server.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/network/socket_server.cc b/src/network/socket_server.cc index 3c6ec30..2e577de 100644 --- a/src/network/socket_server.cc +++ b/src/network/socket_server.cc @@ -8,6 +8,8 @@ #include "sled/network/physical_socket_server.h" namespace sled { +constexpr TimeDelta SocketServer::kForever; + std::unique_ptr CreateDefaultSocketServer() { From f11904132fd17af42063bf4d1fb37b9286d000d9 Mon Sep 17 00:00:00 2001 From: tqcq <99722391+tqcq@users.noreply.github.com> Date: Sat, 24 Feb 2024 16:20:55 +0800 Subject: [PATCH 5/8] feat add circle_queue --- include/sled/log/log.h | 22 ++++--- include/sled/network/physical_socket_server.h | 4 +- include/sled/queue/circle_queue.h | 63 +++++++++++++++++++ src/network/physical_socket_server.cc | 19 +++--- src/time_utils.cc | 2 +- 5 files changed, 90 insertions(+), 20 deletions(-) create mode 100644 include/sled/queue/circle_queue.h diff --git a/include/sled/log/log.h b/include/sled/log/log.h index a2a30f5..d83f4ed 100644 --- a/include/sled/log/log.h +++ b/include/sled/log/log.h @@ -32,10 +32,10 @@ void Log(LogLevel level, // sled::Log(level, tag, fmt, __FILE__, __FUNCTION__, __VA_ARGS__) #define _SLOG(level, tag, fmt_str, ...) \ - sled::Log(level, tag, fmt::format(fmt_str, #__VA_ARGS__).c_str(), \ + sled::Log(level, tag, fmt::format(fmt_str, ##__VA_ARGS__).c_str(), \ __FILE__, __LINE__, __FUNCTION__) -#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, ...) \ SLOG(sled::LogLevel::kTrace, tag, fmt, __VA_ARGS__) #define SLOG_INFO(tag, fmt, ...) \ @@ -75,12 +75,18 @@ void Log(LogLevel level, #define LOGF_IF(cond, tag, fmt, ...) \ SLOG_IF(cond, sled::LogLevel::kFatal, tag, fmt, __VA_ARGS__) -#define LOGV(tag, fmt, ...) SLOG(sled::LogLevel::kTrace, 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 LOGV(tag, fmt, ...) \ + SLOG(sled::LogLevel::kTrace, 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, ...) \ - SLOG(sled::LogLevel::kWarning, tag, fmt, #__VA_ARGS__) -#define LOGE(tag, fmt, ...) SLOG(sled::LogLevel::kError, tag, fmt, #__VA_ARGS__) -#define LOGF(tag, fmt, ...) SLOG(sled::LogLevel::kFatal, 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 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 diff --git a/include/sled/network/physical_socket_server.h b/include/sled/network/physical_socket_server.h index 2b54a17..c87eca2 100644 --- a/include/sled/network/physical_socket_server.h +++ b/include/sled/network/physical_socket_server.h @@ -53,9 +53,9 @@ public: private: 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; std::unordered_map dispatcher_by_key_; diff --git a/include/sled/queue/circle_queue.h b/include/sled/queue/circle_queue.h new file mode 100644 index 0000000..5cf41a8 --- /dev/null +++ b/include/sled/queue/circle_queue.h @@ -0,0 +1,63 @@ +/** + * @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 + +namespace sled { + +template +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()); + return queue_.get(head_); + } + + void Pop() + { + ASSERT(!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 queue_; + size_t head_ = 0; + size_t tail_ = 0; +}; + +}// namespace sled + +#endif// CIRCLE_QUEUE_H diff --git a/src/network/physical_socket_server.cc b/src/network/physical_socket_server.cc index a36d218..d107b73 100644 --- a/src/network/physical_socket_server.cc +++ b/src/network/physical_socket_server.cc @@ -1,4 +1,5 @@ #include "sled/network/physical_socket_server.h" +#include "sled/log/log.h" #include "sled/network/async_resolver.h" #include "sled/network/socket.h" #include "sled/synchronization/event.h" @@ -155,11 +156,11 @@ PhysicalSocketServer::Update(Dispatcher *pdispatcher) } int -PhysicalSocketServer::ToCmsWait(TimeDelta max_wait_duration) +PhysicalSocketServer::ToCusWait(TimeDelta max_wait_duration) { return max_wait_duration == Event::kForever ? kForeverMs - : max_wait_duration.RoundUpTo(TimeDelta::Millis(1)).ms(); + : max_wait_duration.RoundUpTo(TimeDelta::Micros(1)).us(); } bool @@ -167,9 +168,9 @@ PhysicalSocketServer::Wait(TimeDelta max_wait_duration, bool process_io) { 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 @@ -216,16 +217,16 @@ ProcessEvents(Dispatcher *pdispatcher, } bool -PhysicalSocketServer::WaitSelect(int cmsWait, bool process_io) +PhysicalSocketServer::WaitSelect(int64_t cusWait, bool process_io) { struct timeval *ptvWait = nullptr; struct timeval tvWait; int64_t stop_us; - if (cmsWait != kForeverMs) { - tvWait.tv_sec = cmsWait / 1000; - tvWait.tv_usec = (cmsWait % 1000) * 1000; + if (cusWait != kForeverMs) { + tvWait.tv_sec = cusWait / sled::kNumMicrosecsPerSec; + tvWait.tv_usec = (cusWait % sled::kNumMicrosecsPerSec); ptvWait = &tvWait; - stop_us = TimeMicros() + cmsWait * 1000; + stop_us = TimeMicros() + cusWait; } fd_set fdsRead; diff --git a/src/time_utils.cc b/src/time_utils.cc index 479eceb..98b46bd 100644 --- a/src/time_utils.cc +++ b/src/time_utils.cc @@ -22,13 +22,13 @@ TimeMillis() int64_t TimeMicros() { - if (g_clock) { return g_clock->TimeNanos(); } return TimeNanos() / kNumNanosecsPerMicrosec; } int64_t TimeNanos() { + if (g_clock) { return g_clock->TimeNanos(); } return SystemTimeNanos(); } From e3fd80811a9fa2f0d152f0c5a45db0fd43a9cdc9 Mon Sep 17 00:00:00 2001 From: tqcq <99722391+tqcq@users.noreply.github.com> Date: Sat, 24 Feb 2024 16:28:13 +0800 Subject: [PATCH 6/8] feat add circle_queue --- include/sled/queue/circle_queue.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/sled/queue/circle_queue.h b/include/sled/queue/circle_queue.h index 5cf41a8..06d7f67 100644 --- a/include/sled/queue/circle_queue.h +++ b/include/sled/queue/circle_queue.h @@ -37,6 +37,12 @@ public: return queue_.get(head_); } + T &Back() + { + ASSERT(!empty()); + return queue_.get((tail_ + LEN) % (LEN + 1)); + } + void Pop() { ASSERT(!empty()); From d4deb0ae03e0ce8b2a8eb254faa4482d08404c1a Mon Sep 17 00:00:00 2001 From: tqcq <99722391+tqcq@users.noreply.github.com> Date: Sun, 25 Feb 2024 19:04:21 +0800 Subject: [PATCH 7/8] fix scoped_refptr --- include/sled/log/log.h | 6 +- include/sled/numerics/fixed_point_number.h | 708 +++++++++++++++++++++ include/sled/queue/circle_queue.h | 12 +- include/sled/scoped_refptr.h | 1 + src/log/log.cc | 17 + src/synchronization/event.cc | 4 +- 6 files changed, 737 insertions(+), 11 deletions(-) create mode 100644 include/sled/numerics/fixed_point_number.h diff --git a/include/sled/log/log.h b/include/sled/log/log.h index d83f4ed..f31641c 100644 --- a/include/sled/log/log.h +++ b/include/sled/log/log.h @@ -56,8 +56,8 @@ void Log(LogLevel level, #define SLOG_ASSERT(cond, tag, fmt, ...) \ do { \ - if (!(cond)) { \ - SLOG(sled::LogLevel::kFatal, __VA_ARGS__); \ + if (!!(cond)) { \ + SLOG(sled::LogLevel::kFatal, tag, fmt, ##__VA_ARGS__); \ assert(cond); \ } \ } while (0) @@ -87,6 +87,6 @@ void Log(LogLevel level, #define LOGF(tag, fmt, ...) \ SLOG(sled::LogLevel::kFatal, tag, fmt, ##__VA_ARGS__) -#define ASSERT(cond, fmt, ...) SLOG_ASSERT(cond, "ASSERT", fmt, ##__VA_ARGS__); +#define ASSERT(cond, fmt, ...) SLOG_ASSERT(cond, "ASSERT", fmt, ##__VA_ARGS__) #endif// LOG_H diff --git a/include/sled/numerics/fixed_point_number.h b/include/sled/numerics/fixed_point_number.h new file mode 100644 index 0000000..fdc3238 --- /dev/null +++ b/include/sled/numerics/fixed_point_number.h @@ -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 +#include +#include +#include +#include + +//========================================================================== +//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 +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 + q(q a); + + operator int() const; + operator float() const; + operator double() const; + operator long double() const; + template + q operator+(q b) const; + template + q operator-(q b) const; + template + q operator*(q b) const; + template + q operator/(q b) const; + template + q operator%(q b) const; + + template + q operator+(T b) const; + template + q operator-(T b) const; + template + q operator*(T b) const; + template + q operator/(T b) const; + template + q operator%(T b) const; + + template + q &operator+=(T b); + template + q &operator-=(T b); + template + q &operator*=(T b); + template + q &operator/=(T b); + template + q &operator%=(T b); + + q operator-() const; + + template + q &operator=(q b); + q &operator=(int b); + q &operator=(double b); + q &operator=(long double b); + + template + bool operator>=(q b) const; + template + bool operator>(q b) const; + template + bool operator<=(q b) const; + template + bool operator<(q b) const; + template + bool operator==(q b) const; + template + bool operator!=(q b) const; + + friend std::ostream &operator<<(std::ostream &os, const q &fp) + { + os << (float) fp; + return os; + } + + friend std::istream &operator>>(std::istream &is, q &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 +q abs(q x); +}// namespace fp + +//========================================================================== +//Internal helper functions and classes +//========================================================================== +namespace fp_internal { +/*Count leading zeroes*/ +template +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 +struct shifter { + static T op(T x); +}; + +template +struct shifter { + static T op(T x) { return x >> shift; }; +}; + +template +struct shifter { + static T op(T x) { return x << -shift; }; +}; + +template +struct shifter { + static T op(T x) { return 0; }; +}; + +template +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 +constexpr T +signed_rsh(T x) +{ + return shifter= 0), (abs_helper(shift) >= sizeof(T) * 8), + T>::op(x); +} + +/*Signed right shift, run time version.*/ +template +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 +T +signed_lsh(T x) +{ + return signed_rsh<-shift, T>(x); +} + +/*Signed left shift, run time version*/ +template +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 +T +mul_rsh(T a, T b) +{ + typedef typename std::make_unsigned::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); + low += signed_lsh(high); + return low; +} + +/*Run time version*/ +template +T +mul_rsh(T a, T b, int shift) +{ + typedef typename std::make_unsigned::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 +fp::q::q(int u) +{ + i = fp_internal::signed_lsh((I) u); +} + +template +fp::q::q(unsigned u) +{ + i = fp_internal::signed_lsh((I) u); +} + +template +fp::q::q(uintmax_t s) +{ + i = fp_internal::signed_lsh((I) s); +} + +template +fp::q::q(double d) +{ + int exp = 0; + double tmp = frexp(d, &exp); + i = lroundl(ldexp(tmp, exp + f)); +} + +template +fp::q::q(long double d) +{ + int exp = 0; + long double tmp = frexp(d, &exp); + i = llroundl(ldexp(tmp, exp + f)); +} + +template +template +fp::q::q(q a) +{ + i = fp_internal::signed_rsh(a.i); +} + +template +fp::q::operator int() const +{ + return fp_internal::signed_rsh(i); +} + +template +fp::q::operator float() const +{ + return ldexpf((float) i, -(int) f); +} + +template +fp::q::operator double() const +{ + return ldexp((double) i, -(int) f); +} + +template +fp::q::operator long double() const +{ + return ldexp((long double) i, -(int) f); +} + +template +template +fp::q +fp::q::operator+(q b) const +{ + q t; + t.i = i + fp_internal::signed_rsh(b.i); + return t; +} + +template +template +fp::q +fp::q::operator-(q b) const +{ + q t; + t.i = i - fp_internal::signed_rsh(b.i); + return t; +} + +template +template +fp::q +fp::q::operator*(q b) const +{ + q t; + t.i = fp_internal::mul_rsh(i, b.i); + return t; +} + +template +template +fp::q +fp::q::operator/(q 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::type> e; + e.i = (~d + 1) << 1;//[0, 0.5[ + //r is the reciprocal of d + q::type> r(1); + for (unsigned i = 0; i < sizeof(I) - 1; ++i) { + r = r + r * e; + e = e * e; + } + q t; + t.i = (I) fp_internal::mul_rsh(//adjust the radix point of (this*r) + r.i, + (typename std::make_unsigned::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 +template +fp::q +fp::q::operator%(q b) const +{ + q t; + t.i = i % fp_internal::signed_rsh(b.i); + return t; +} + +template +template +fp::q +fp::q::operator+(T b) const +{ + return *this + q(b); +} + +template +template +fp::q +fp::q::operator-(T b) const +{ + return *this - q(b); +} + +template +template +fp::q +fp::q::operator*(T b) const +{ + return *this * q(b); +} + +template +template +fp::q +fp::q::operator/(T b) const +{ + return *this / q(b); +} + +template +template +fp::q +fp::q::operator%(T b) const +{ + return *this % q(b); +} + +template +template +fp::q & +fp::q::operator+=(T b) +{ + return *this = *this + b; +} + +template +template +fp::q & +fp::q::operator-=(T b) +{ + return *this = *this - b; +} + +template +template +fp::q & +fp::q::operator*=(T b) +{ + return *this = *this * b; +} + +template +template +fp::q & +fp::q::operator/=(T b) +{ + return *this = *this / b; +} + +template +template +fp::q & +fp::q::operator%=(T b) +{ + return *this = *this % b; +} + +template +fp::q +fp::q::operator-() const +{ + q t; + t.i = -i; + return t; +} + +template +template +fp::q & +fp::q::operator=(q b) +{ + i = fp_internal::signed_rsh(b.i); + return *this; +} + +template +fp::q & +fp::q::operator=(int b) +{ + i = fp_internal::signed_lsh((I) b); + return *this; +} + +template +fp::q & +fp::q::operator=(double b) +{ + int exp = 0; + double tmp = frexp(b, &exp); + i = llroundl(ldexp(tmp, exp + f)); + return *this; +} + +template +fp::q & +fp::q::operator=(long double b) +{ + int exp = 0; + long double tmp = frexp(b, &exp); + i = llroundl(ldexp(tmp, exp + f)); + return *this; +} + +template +template +bool +fp::q::operator>=(q b) const +{ + static const unsigned bits = sizeof(I) * 8; + I ma = fp_internal::signed_rsh(i); + I mb = fp_internal::signed_rsh(b.i); + return (ma > mb) + || ((ma == mb) + && ((typename std::make_unsigned::type) + fp_internal::signed_lsh(i) + >= (typename std::make_unsigned::type) + fp_internal::signed_lsh(b.i))); +} + +template +template +bool +fp::q::operator>(q b) const +{ + static const unsigned bits = sizeof(I) * 8; + I ma = fp_internal::signed_rsh(i); + I mb = fp_internal::signed_rsh(b.i); + return (ma > mb) + || ((ma == mb) + && ((typename std::make_unsigned::type) + fp_internal::signed_lsh(i) + > (typename std::make_unsigned::type) + fp_internal::signed_lsh(b.i))); +} + +template +template +bool +fp::q::operator<=(q b) const +{ + static const unsigned bits = sizeof(I) * 8; + I ma = fp_internal::signed_rsh(i); + I mb = fp_internal::signed_rsh(b.i); + return (ma < mb) + || ((ma == mb) + && ((typename std::make_unsigned::type) + fp_internal::signed_lsh(i) + <= (typename std::make_unsigned::type) + fp_internal::signed_lsh(b.i))); +} + +template +template +bool +fp::q::operator<(q b) const +{ + static const unsigned bits = sizeof(I) * 8; + I ma = fp_internal::signed_rsh(i); + I mb = fp_internal::signed_rsh(b.i); + return (ma < mb) + || ((ma == mb) + && ((typename std::make_unsigned::type) + fp_internal::signed_lsh(i) + < (typename std::make_unsigned::type) + fp_internal::signed_lsh(b.i))); +} + +template +template +bool +fp::q::operator==(q b) const +{ + return fp_internal::signed_rsh(i) == b.i + && fp_internal::signed_rsh(b.i) == i; +} + +template +template +bool +fp::q::operator!=(q b) const +{ + return fp_internal::signed_rsh(i) != b.i + || fp_internal::signed_rsh(b.i) != i; +} + +template +fp::q +fp::abs(q x) +{ + return (x.i >= 0 ? x : -x); +} + +namespace sled { +template +using FixedPoint = fp::q; + +using FixedFloat = fp::Q32_32; + +template +inline const FixedPoint +conj(const FixedPoint &val) +{ + return val; +} + +template +inline const FixedPoint +real(const FixedPoint &val) +{ + return val; +} + +template +inline const FixedPoint +imag(const FixedPoint &val) +{ + return 0.; +} + +template +inline const FixedPoint +abs(const FixedPoint &val) +{ + return fp::abs(val); +} + +template +inline const FixedPoint +abs2(const FixedPoint &val) +{ + return val * val; +} + +}// namespace sled + +template +struct fmt::formatter> : ostream_formatter {}; + +namespace Eigen { +template +struct NumTraits> : NumTraits { + typedef sled::FixedPoint Real; + typedef sled::FixedPoint NonInteger; + typedef sled::FixedPoint Nested; + + enum { + IsComplex = 0, + IsInteger = 0, + IsSigned = std::is_signed::value, + RequireInitialization = 1, + ReadCost = 1, + AddCost = 3, + MulCost = 3 + }; +}; + +template +struct ScalarBinaryOpTraits, float, BinaryOp> { + typedef sled::FixedPoint ReturnType; +}; + +template +struct ScalarBinaryOpTraits, BinaryOp> { + typedef sled::FixedPoint ReturnType; +}; + +}// namespace Eigen + +#endif diff --git a/include/sled/queue/circle_queue.h b/include/sled/queue/circle_queue.h index 06d7f67..11eafd8 100644 --- a/include/sled/queue/circle_queue.h +++ b/include/sled/queue/circle_queue.h @@ -14,38 +14,38 @@ namespace sled { template class CircleQueue { - static_assert(LEN > 0, "LEN should be greater than 0"); + static_assert(LEN > 0, "LEN should be greater than 0."); public: void Push(T &&val) { - ASSERT(size() < LEN, "queue is full"); + ASSERT(size() < LEN, "queue is full."); queue_.get(tail_) = std::move(val); ++tail_; } void Push(const T &val) { - ASSERT(size() < LEN, "queue is full"); + ASSERT(size() < LEN, "queue is full."); queue_.get(tail_) = val; ++tail_; } T &Front() { - ASSERT(!empty()); + ASSERT(!empty(), "queue is empty."); return queue_.get(head_); } T &Back() { - ASSERT(!empty()); + ASSERT(!empty(), "queue is empty."); return queue_.get((tail_ + LEN) % (LEN + 1)); } void Pop() { - ASSERT(!empty()); + ASSERT(!empty(), "queue is empty."); head_ = (head_ + 1) % (LEN + 1); } diff --git a/include/sled/scoped_refptr.h b/include/sled/scoped_refptr.h index c55abb4..7d2f731 100644 --- a/include/sled/scoped_refptr.h +++ b/include/sled/scoped_refptr.h @@ -84,6 +84,7 @@ public: scoped_refptr &operator=(const scoped_refptr &&r) noexcept { scoped_refptr(std::move(r)).swap(*this); + return *this; } template diff --git a/src/log/log.cc b/src/log/log.cc index 7499256..f050167 100644 --- a/src/log/log.cc +++ b/src/log/log.cc @@ -3,6 +3,21 @@ #include 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_; +}; + void Log(LogLevel level, const char *tag, @@ -12,6 +27,8 @@ Log(LogLevel level, const char *func_name, ...) { + static std::atomic_bool allow(true); + ScopedAtomicWaiter waiter(allow); int len = file_name ? strlen(file_name) : 0; while (len > 0 && file_name[len - 1] != '/') { len--; } diff --git a/src/synchronization/event.cc b/src/synchronization/event.cc index 28e09a6..5b160cc 100644 --- a/src/synchronization/event.cc +++ b/src/synchronization/event.cc @@ -30,9 +30,9 @@ Event::Reset() bool Event::Wait(TimeDelta give_up_after, TimeDelta warn_after) { - MutexLock lock(&mutex_); + MutexLock guard(&mutex_); bool wait_success = - cv_.WaitFor(lock, give_up_after, [&] { return event_status_; }); + cv_.WaitFor(guard, give_up_after, [&] { return event_status_; }); if (!wait_success) { return false; } if (!is_manual_reset_) { event_status_ = false; } From b4e2d0fd664d4f4b093007a3f2adbca5f26285eb Mon Sep 17 00:00:00 2001 From: tqcq <99722391+tqcq@users.noreply.github.com> Date: Wed, 28 Feb 2024 00:23:29 +0800 Subject: [PATCH 8/8] feat update --- CMakeLists.txt | 1 + include/sled/log/log.h | 13 +++++++-- include/sled/reflect/reflect.h | 24 +++++++++++++++ include/sled/system/location.h | 21 ++++++++++++-- include/sled/time_utils.h | 9 ++++-- src/log/log.cc | 34 ++++++++++++++++++++-- src/system/location.cc | 23 +++++++++++++++ src/system_time.cc | 3 +- src/time_utils.cc | 53 ++++------------------------------ 9 files changed, 124 insertions(+), 57 deletions(-) create mode 100644 include/sled/reflect/reflect.h create mode 100644 src/system/location.cc diff --git a/CMakeLists.txt b/CMakeLists.txt index e6d0776..031542f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -29,6 +29,7 @@ target_sources( src/synchronization/mutex.cc src/synchronization/sequence_checker_internal.cc src/synchronization/thread_local.cc + src/system/location.cc src/system/thread.cc src/task_queue/pending_task_safety_flag.cc src/task_queue/task_queue_base.cc diff --git a/include/sled/log/log.h b/include/sled/log/log.h index f31641c..46efac1 100644 --- a/include/sled/log/log.h +++ b/include/sled/log/log.h @@ -6,6 +6,7 @@ #ifndef LOG_H #define LOG_H +#include "sled/system/location.h" #include namespace sled { @@ -32,8 +33,16 @@ void Log(LogLevel level, // sled::Log(level, tag, fmt, __FILE__, __FUNCTION__, __VA_ARGS__) #define _SLOG(level, tag, fmt_str, ...) \ - sled::Log(level, tag, fmt::format(fmt_str, ##__VA_ARGS__).c_str(), \ - __FILE__, __LINE__, __FUNCTION__) + do { \ + 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_TRACE(tag, fmt, ...) \ diff --git a/include/sled/reflect/reflect.h b/include/sled/reflect/reflect.h new file mode 100644 index 0000000..b11f23e --- /dev/null +++ b/include/sled/reflect/reflect.h @@ -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 diff --git a/include/sled/system/location.h b/include/sled/system/location.h index 96dafc4..ca2360c 100644 --- a/include/sled/system/location.h +++ b/include/sled/system/location.h @@ -7,13 +7,30 @@ #ifndef LOCATION_H #define LOCATION_H +#include + namespace sled { -class Location { +class Location final { 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 +#define SLED_FROM_HERE sled::Location::Current(); + #endif// LOCATION_H diff --git a/include/sled/time_utils.h b/include/sled/time_utils.h index 3e56107..4378291 100644 --- a/include/sled/time_utils.h +++ b/include/sled/time_utils.h @@ -13,9 +13,12 @@ namespace sled { static const int64_t kNumMillisecsPerSec = 1000; static const int64_t kNumMicrosecsPerSec = 1000000; static const int64_t kNumNanosecsPerSec = 1000000000; -static const int64_t kNumMicrosecsPerMillisec = kNumMicrosecsPerSec / kNumMillisecsPerSec; -static const int64_t kNumNanosecsPerMillisec = kNumNanosecsPerSec / kNumMillisecsPerSec; -static const int64_t kNumNanosecsPerMicrosec = kNumNanosecsPerSec / kNumMicrosecsPerSec; +static const int64_t kNumMicrosecsPerMillisec = + kNumMicrosecsPerSec / kNumMillisecsPerSec; +static const int64_t kNumNanosecsPerMillisec = + kNumNanosecsPerSec / kNumMillisecsPerSec; +static const int64_t kNumNanosecsPerMicrosec = + kNumNanosecsPerSec / kNumMicrosecsPerSec; constexpr int64_t kNtpJan1970Millisecs = 2208988800 * kNumMillisecsPerSec; class ClockInterface { diff --git a/src/log/log.cc b/src/log/log.cc index f050167..c9bae1f 100644 --- a/src/log/log.cc +++ b/src/log/log.cc @@ -1,4 +1,6 @@ #include "sled/log/log.h" +#include "sled/time_utils.h" +#include #include #include @@ -18,6 +20,34 @@ 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(now % kNumNanosecsPerSec) + / kNumNanosecsPerMillisec); +#else + return result + "Z"; +#endif + return result; +} + void Log(LogLevel level, const char *tag, @@ -32,8 +62,8 @@ Log(LogLevel level, int len = file_name ? strlen(file_name) : 0; while (len > 0 && file_name[len - 1] != '/') { len--; } - auto msg = fmt::format("{}:{}@{} {} {}", file_name + len, line, func_name, - tag, fmt); + auto msg = fmt::format("{} {}:{}@{} {} {}", GetCurrentUTCTime(), + file_name + len, line, func_name, tag, fmt); std::cout << msg << std::endl; } diff --git a/src/system/location.cc b/src/system/location.cc new file mode 100644 index 0000000..65ab064 --- /dev/null +++ b/src/system/location.cc @@ -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 diff --git a/src/system_time.cc b/src/system_time.cc index 9f71a49..99b57ea 100644 --- a/src/system_time.cc +++ b/src/system_time.cc @@ -8,7 +8,8 @@ SystemTimeNanos() int64_t ticks; struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); - ticks = kNumNanosecsPerSec * static_cast(ts.tv_sec) + static_cast(ts.tv_nsec); + ticks = kNumNanosecsPerSec * static_cast(ts.tv_sec) + + static_cast(ts.tv_nsec); return ticks; } }// namespace sled diff --git a/src/time_utils.cc b/src/time_utils.cc index 98b46bd..e0ef69b 100644 --- a/src/time_utils.cc +++ b/src/time_utils.cc @@ -51,49 +51,10 @@ TimeDiff(int32_t later, int32_t earlier) } int64_t -TmToSeconds(const tm &tm) +TmToSeconds(const tm &tm_val) { - static short int mdays[12] = {31, 28, 31, 30, 31, 30, - 31, 31, 30, 31, 30, 31}; - 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(year - 1970) * 365 + day) * 24 + hour) * 60 - + min) - * 60 - + sec; - return -1; + struct tm *ptm = const_cast(&tm_val); + return ::timegm(ptm); } int64_t @@ -118,11 +79,9 @@ int64_t TimeUTCNanos() { if (g_clock) { return g_clock->TimeNanos() / kNumNanosecsPerMicrosec; } - struct timeval time; - gettimeofday(&time, nullptr); - int64_t nanosecs = - static_cast(time.tv_sec) * kNumNanosecsPerSec + time.tv_usec; - return nanosecs; + struct timespec ts; + clock_gettime(CLOCK_REALTIME, &ts); + return ts.tv_nsec + ts.tv_sec * kNumNanosecsPerSec; } }// namespace sled