3#ifndef USE_NATIVE_64BIT_TIME
8#ifdef ESPHOME_DEBUG_SCHEDULER
12#ifdef ESPHOME_THREAD_MULTI_ATOMICS
19#ifdef ESPHOME_DEBUG_SCHEDULER
20static const char *
const TAG =
"time_64";
23uint64_t Millis64Impl::compute(uint32_t now) {
25 static constexpr uint32_t HALF_MAX_UINT32 = std::numeric_limits<uint32_t>::max() / 2;
28#ifdef ESPHOME_THREAD_MULTI_ATOMICS
40 static std::atomic<uint32_t> last_millis{0};
46 static std::atomic<uint16_t> millis_major{0};
47#elif !defined(ESPHOME_THREAD_SINGLE)
50 static uint16_t millis_major{0};
53 static uint16_t millis_major{0};
68#ifdef ESPHOME_THREAD_SINGLE
72 uint16_t major = millis_major;
76 if (now < last && (last - now) > HALF_MAX_UINT32) {
80#ifdef ESPHOME_DEBUG_SCHEDULER
81 ESP_LOGD(TAG,
"Detected true 32-bit rollover at %" PRIu32
"ms (was %" PRIu32
")", now, last);
83 }
else if (now > last) {
89 return now + (
static_cast<uint64_t
>(major) << 32);
91#elif defined(ESPHOME_THREAD_MULTI_NO_ATOMICS)
97 uint16_t major = millis_major;
102 static constexpr uint32_t ROLLOVER_WINDOW = 10000;
105 bool near_rollover = (last > (std::numeric_limits<uint32_t>::max() - ROLLOVER_WINDOW)) || (now < ROLLOVER_WINDOW);
107 if (near_rollover || (now < last && (last - now) > HALF_MAX_UINT32)) {
109 LockGuard guard{lock};
113 if (now < last && (last - now) > HALF_MAX_UINT32) {
117#ifdef ESPHOME_DEBUG_SCHEDULER
118 ESP_LOGD(TAG,
"Detected true 32-bit rollover at %" PRIu32
"ms (was %" PRIu32
")", now, last);
123 }
else if (now > last) {
136 return now + (
static_cast<uint64_t
>(major) << 32);
138#elif defined(ESPHOME_THREAD_MULTI_ATOMICS)
147 uint16_t major = millis_major.load(std::memory_order_acquire);
155 uint32_t last = last_millis.load(std::memory_order_acquire);
159 if (now < last && (last - now) > HALF_MAX_UINT32) {
161 LockGuard guard{lock};
163 last = last_millis.load(std::memory_order_relaxed);
165 if (now < last && (last - now) > HALF_MAX_UINT32) {
167 millis_major.fetch_add(1, std::memory_order_relaxed);
169#ifdef ESPHOME_DEBUG_SCHEDULER
170 ESP_LOGD(TAG,
"Detected true 32-bit rollover at %" PRIu32
"ms (was %" PRIu32
")", now, last);
178 last_millis.store(now, std::memory_order_release);
182 while (now > last && (now - last) < HALF_MAX_UINT32) {
183 if (last_millis.compare_exchange_weak(last, now,
184 std::memory_order_release,
185 std::memory_order_relaxed)) {
192 uint16_t major_end = millis_major.load(std::memory_order_relaxed);
193 if (major_end == major)
194 return now + (
static_cast<uint64_t
>(major) << 32);
197 __builtin_unreachable();
201 "No platform threading model defined. One of ESPHOME_THREAD_SINGLE, ESPHOME_THREAD_MULTI_NO_ATOMICS, or ESPHOME_THREAD_MULTI_ATOMICS must be defined."
Providing packet encoding functions for exchanging data with a remote host.