Skip to content

Commit

Permalink
feat(timers): add timers support
Browse files Browse the repository at this point in the history
  • Loading branch information
Anotra committed Mar 24, 2022
1 parent 5dcc700 commit 38f3eb6
Show file tree
Hide file tree
Showing 5 changed files with 117 additions and 1 deletion.
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ DISCORD_OBJS = $(OBJDIR)/$(SRC_DIR)/concord-once.o \
$(OBJDIR)/$(SRC_DIR)/discord-ratelimit.o \
$(OBJDIR)/$(SRC_DIR)/discord-client.o \
$(OBJDIR)/$(SRC_DIR)/discord-gateway.o \
$(OBJDIR)/$(SRC_DIR)/discord-timer.o \
$(OBJDIR)/$(SRC_DIR)/discord-misc.o \
$(OBJDIR)/$(SRC_DIR)/application_command.o \
$(OBJDIR)/$(SRC_DIR)/interaction.o \
Expand Down
18 changes: 18 additions & 0 deletions include/discord-internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include "uthash.h"
#include "queue.h"
#include "heap-inl.h"
#include "priority_queue.h"

/** @brief Return 1 if string isn't considered empty */
#define NOT_EMPTY_STR(str) ((str) && *(str))
Expand Down Expand Up @@ -684,6 +685,18 @@ void discord_gateway_send_presence_update(struct discord_gateway *gw);

/** @} DiscordInternalGateway */

struct discord_timer {
priority_queue *q;
};

void discord_timers_init(struct discord *client);
void discord_timers_cleanup(struct discord *client);
void discord_timers_run(struct discord *client, struct discord_timer *timer);
unsigned discord_timer_ctl(
struct discord *client, struct discord_timer *timer, unsigned id,
discord_ev_timer cb, void *data,
int64_t start_after, int64_t interval, int flags);

/**
* @brief The Discord client handler
*
Expand All @@ -707,6 +720,11 @@ struct discord {
/** the client's user structure */
struct discord_user self;

struct {
struct discord_timer internal;
struct discord_timer user;
} timers;

/** wakeup timer handle */
struct {
/** callback to be triggered on timer's timeout */
Expand Down
7 changes: 7 additions & 0 deletions include/discord.h
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,13 @@ struct logconf *discord_get_logconf(struct discord *client);
*/
struct io_poller *discord_get_io_poller(struct discord *client);

typedef void (*discord_ev_timer)
(struct discord *client, unsigned id, void *data, int flags);

unsigned discord_timer(
struct discord *client, unsigned id, discord_ev_timer cb,
void *data, int64_t start_after, int64_t interval, int flags);

/** @} Discord */

#endif /* DISCORD_H */
5 changes: 4 additions & 1 deletion src/discord-client.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ static void
_discord_init(struct discord *new_client)
{
ccord_global_init();

discord_timers_init(new_client);
new_client->io_poller = io_poller_create();
discord_adapter_init(&new_client->adapter, &new_client->conf,
&new_client->token);
Expand Down Expand Up @@ -97,6 +97,7 @@ void
discord_cleanup(struct discord *client)
{
if (client->is_original) {
discord_timers_cleanup(client);
logconf_cleanup(&client->conf);
discord_adapter_cleanup(&client->adapter);
discord_gateway_cleanup(&client->gw);
Expand Down Expand Up @@ -355,6 +356,8 @@ discord_run(struct discord *client)
break;

now = (int64_t)cog_timestamp_ms();
discord_timers_run(client, &client->timers.internal);
discord_timers_run(client, &client->timers.user);

/* check for pending wakeup timers */
if (client->wakeup_timer.next != -1
Expand Down
87 changes: 87 additions & 0 deletions src/discord-timer.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@

#include "discord.h"
#include "discord-internal.h"

struct timer_data {
discord_ev_timer cb;
void *data;
int64_t interval;
int flags;
};

static int
cmp_timers(const void *a, const void *b) {
const int64_t l = *(int64_t *)a;
const int64_t r = *(int64_t *)b;
if (l == r || (l < 0 && r < 0))
return 0;
if (l < 0) return 1;
if (r < 0) return -1;
return l > r ? 1 : -1;
}

void
discord_timers_init(struct discord *client) {
client->timers.internal.q =
priority_queue_create(sizeof(int64_t), sizeof(struct timer_data),
cmp_timers, 0);
client->timers.user.q =
priority_queue_create(sizeof(int64_t), sizeof(struct timer_data),
cmp_timers, 0);
}

void
discord_timers_cleanup(struct discord *client) {
priority_queue_destroy(client->timers.user.q);
priority_queue_destroy(client->timers.internal.q);
}

unsigned
discord_timer_ctl(
struct discord *client, struct discord_timer *timer, unsigned id,
discord_ev_timer timer_cb,
void *data, int64_t start_after, int64_t interval, int flags)
{
struct timer_data tdata = {
.cb = timer_cb,
.data = data,
.interval = interval,
.flags = flags,
};
int64_t now = start_after >= 0
? (int64_t)discord_timestamp_us(client) + start_after * 1000
: -1;
if (!id) {
return priority_queue_push(timer->q, &now, &tdata);
} else {
return priority_queue_update(timer->q, id, &now, &tdata) ? id : 0;
}
}

void
discord_timers_run(struct discord *client, struct discord_timer *timer) {
const int64_t now = (int64_t)discord_timestamp_us(client);
priority_queue_id id;
struct timer_data data;
for (int64_t trigger;
(id = priority_queue_peek(timer->q, &trigger, &data));)
{
if (trigger > now || trigger == -1) return;
if (data.cb)
data.cb(client, id, data.data, 0);
if (data.interval) {
int64_t next = now + data.interval * 1000;
priority_queue_update(timer->q, id, &next, &data);
} else priority_queue_pop(timer->q, NULL, NULL);
}
}

unsigned
discord_timer(
struct discord *client, unsigned id,
discord_ev_timer timer_cb, void *data,
int64_t start_after, int64_t interval, int flags)
{
return discord_timer_ctl(client, &client->timers.user, id, timer_cb, data,
start_after, interval, flags);
}

0 comments on commit 38f3eb6

Please sign in to comment.