feat(bar): 按间隔节流 bar_item 更新

- 新增 base/time: time_monotonic_ms 与 time_create_monotonic_timerfd_by_fps
- bar 初始化改用该工具创建 timerfd,移除内联的 itimerspec 拼装
- bar_item_update 按 update_interval_ms 节流,记录 last_updated_time 跳过过早更新
This commit is contained in:
2026-06-16 00:31:07 +08:00
parent 30e9751119
commit ac65180203
5 changed files with 75 additions and 19 deletions

View File

@@ -37,6 +37,7 @@ add_executable(${APP_NAME}
${SOURCE_DIR}/base/color.c ${SOURCE_DIR}/base/color.c
${SOURCE_DIR}/base/log.c ${SOURCE_DIR}/base/log.c
${SOURCE_DIR}/base/process.c ${SOURCE_DIR}/base/process.c
${SOURCE_DIR}/base/time.c
${SOURCE_DIR}/base/window_list.c ${SOURCE_DIR}/base/window_list.c
${SOURCE_DIR}/config/defaults.c ${SOURCE_DIR}/config/defaults.c

View File

@@ -1,12 +1,9 @@
#include "bar/bar.h" #include "bar/bar.h"
#include <assert.h> #include <assert.h>
#include <bits/time.h>
#include <bits/types/struct_itimerspec.h>
#include <cairo.h> #include <cairo.h>
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#include <sys/timerfd.h>
#include <unistd.h> #include <unistd.h>
#include <zdwm/bar.h> #include <zdwm/bar.h>
#include <zdwm/types.h> #include <zdwm/types.h>
@@ -18,6 +15,7 @@
#include "base/array.h" #include "base/array.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/memory.h" #include "base/memory.h"
#include "base/time.h"
#include "core/listeners.h" #include "core/listeners.h"
static zdwm_bar_item_t *bar_add_item( static zdwm_bar_item_t *bar_add_item(
@@ -91,21 +89,7 @@ void bar_init(bar_t *bar, listeners_t *listeners) {
bar_output_add_workspace(bar_output, &bar->config, listeners); bar_output_add_workspace(bar_output, &bar->config, listeners);
} }
bar->timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC); bar->timerfd = time_create_monotonic_timerfd_by_fps(bar->config.fps);
auto interval_ns = 1'000'000'000ULL / bar->config.fps;
struct itimerspec timer_spec = {
.it_interval =
{
.tv_sec = interval_ns / 1'000'000'000,
.tv_nsec = interval_ns % 1'000'000'000,
},
.it_value = {
.tv_sec = 0,
.tv_nsec = interval_ns % 1'000'000'000,
},
};
timerfd_settime(bar->timerfd, 0, &timer_spec, nullptr);
} }
static void bar_side_cleanup(bar_side_t *side) { static void bar_side_cleanup(bar_side_t *side) {
@@ -139,7 +123,15 @@ void bar_cleanup(bar_t *bar) {
static inline void bar_item_update(zdwm_bar_item_t *item) { static inline void bar_item_update(zdwm_bar_item_t *item) {
auto update = item->api.update; auto update = item->api.update;
if (update) update(item, &bar_cell_api, item->state); if (!update) return;
auto update_interval_ms = item->api.update_interval_ms;
auto last_updated_time = item->last_updated_time;
auto now = time_monotonic_ms();
if (now < last_updated_time + update_interval_ms) return;
item->last_updated_time = now;
update(item, &bar_cell_api, item->state);
} }
static inline void bar_side_update(bar_side_t *side) { static inline void bar_side_update(bar_side_t *side) {

View File

@@ -32,6 +32,7 @@ struct zdwm_bar_item_t {
void *state; void *state;
zdwm_bar_item_type_t api; zdwm_bar_item_type_t api;
bool dirty; bool dirty;
uint64_t last_updated_time;
}; };
typedef struct bar_side_t { typedef struct bar_side_t {

56
src/base/time.c Normal file
View File

@@ -0,0 +1,56 @@
#include "base/time.h"
#include <bits/time.h>
#include <bits/types/struct_itimerspec.h>
#include <errno.h>
#include <stdint.h>
#include <string.h>
#include <sys/timerfd.h>
#include <time.h>
#include "base/log.h"
static int time_create_monotonic_timerfd(const struct itimerspec *itimerspec) {
auto timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC);
if (timerfd == -1) {
auto err = errno;
warn("time_create_timerfd failed: %s", strerror(err));
return timerfd;
}
timerfd_settime(timerfd, 0, itimerspec, nullptr);
return timerfd;
}
static constexpr auto NANOSECONDS_OF_ONE_SECOND = 1'000'000'000ULL;
int time_create_monotonic_timerfd_by_fps(uint32_t fps) {
if (fps == 0) fps = 30;
auto interval_ns = NANOSECONDS_OF_ONE_SECOND / fps;
/* clang-format off */
struct itimerspec timer_spec = {
.it_value = {
.tv_sec = 0,
.tv_nsec = interval_ns % NANOSECONDS_OF_ONE_SECOND,
},
.it_interval = {
.tv_sec = interval_ns / NANOSECONDS_OF_ONE_SECOND,
.tv_nsec = interval_ns % NANOSECONDS_OF_ONE_SECOND,
},
};
/* clang-format on */
return time_create_monotonic_timerfd(&timer_spec);
}
static uint64_t time_monotonic_ns(void) {
struct timespec timestamp = {0};
if (clock_gettime(CLOCK_MONOTONIC, &timestamp) == -1) {
warn("clock_gettime failed: %s", strerror(errno));
}
return timestamp.tv_sec * NANOSECONDS_OF_ONE_SECOND + timestamp.tv_nsec;
}
uint64_t time_monotonic_ms(void) { return time_monotonic_ns() / 1'000'000U; }

6
src/base/time.h Normal file
View File

@@ -0,0 +1,6 @@
#pragma once
#include <stdint.h>
int time_create_monotonic_timerfd_by_fps(uint32_t fps);
uint64_t time_monotonic_ms(void);