Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Timer Wrapper Functions, and Refactoring #58

Merged
merged 24 commits into from
Apr 17, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
1af7947
fix(discord-timer.c): make timer delay -1 disable a timer
Anotra Apr 13, 2022
7f49653
refactor(discord-timer.c): rework delete and cancel logic. add DISCOR…
Anotra Apr 13, 2022
d3a6e01
feat(discord-timer): added DISCORD_TIMER_INTERVAL_FIXED
Anotra Apr 13, 2022
5ec231b
refactor(discord-timer.c): remove flag DISCORD_TIMER_DONT_UPDATE
Anotra Apr 13, 2022
6a0c32b
feat(discord-timer.c): added wrapper functions for common methods ass…
Anotra Apr 13, 2022
4ac8816
feat(discord-timers.c): added discord_timer_interval() function
Anotra Apr 13, 2022
2c6afed
refactor(discord-client.c): use µseconds in event loop instead of ms
Anotra Apr 15, 2022
babb2e7
fix(discord-timers.c): allow 0 interval timers
Anotra Apr 15, 2022
e923b6d
docs(timers.c): update discord timer example
Anotra Apr 15, 2022
a094f47
fix(discord-client.c): fix logic for determining how long to sleep
Anotra Apr 16, 2022
bc3420e
docs(timers.c): update timer example
Anotra Apr 16, 2022
07ec9dd
refactor(discord-timer.c): make code easier to read
Anotra Apr 16, 2022
55f54aa
fix(discord-timer.c): add a hard limit on the number of timers that c…
Anotra Apr 16, 2022
d1b9325
fix(discord-timer.c): limit amount of time discord_timers_run will be…
Anotra Apr 16, 2022
1d672ad
feat(cog-utils): implement cog_sleep_us
Anotra Apr 16, 2022
ad52d80
chore(discord-client.c): integrate cog_sleep_us into event loop, and …
Anotra Apr 16, 2022
628ed54
chore: apply clang formatting
Anotra Apr 16, 2022
fa2b4a7
refactor(discord-client.c): add BREAK_ON_FAIL macro to simplify event…
Anotra Apr 16, 2022
9fb463a
chore(discord-client.c): move discord_set_on_ready to its related fun…
Anotra Apr 16, 2022
25a28a3
refactor(discord-client): move event loop to a new file discord-loop.c
Anotra Apr 16, 2022
3660e13
refactor(discord-loop.c): poll again after running timers
Anotra Apr 16, 2022
59636a2
fix(discord-loop.c): fix BREAK_ON_FAIL - how did this happen?
Anotra Apr 17, 2022
ac27693
refactor(discord-loop.c): add poll_errno to capture poll errors
Anotra Apr 17, 2022
fc46ecc
refactor(discord-loop.c): add extra params to macros CALL_IO_POLLER_P…
Anotra Apr 17, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 = $(SRC_DIR)/concord-once.o \
$(SRC_DIR)/discord-adapter_ratelimit.o \
$(SRC_DIR)/discord-adapter_refcount.o \
$(SRC_DIR)/discord-client.o \
$(SRC_DIR)/discord-loop.o \
$(SRC_DIR)/discord-gateway.o \
$(SRC_DIR)/discord-timer.o \
$(SRC_DIR)/discord-misc.o \
Expand Down
34 changes: 34 additions & 0 deletions cog-utils/cog-utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,40 @@ cog_sleep_ms(const long tms)
return ret;
}

int
cog_sleep_us(const long tms)
{
int ret;

#if _POSIX_C_SOURCE >= 199309L
struct timespec ts;

if (tms < 0) {
errno = EINVAL;
return -1;
}

ts.tv_sec = tms / 1000000;
ts.tv_nsec = (tms % 1000000) * 1000;

do {
ret = nanosleep(&ts, &ts);
} while (ret && errno == EINTR);
#else
struct timeval timeout;
long _tms = tms;

timeout.tv_sec = _tms / 1000000L;
_tms = tms % 1000000L;
timeout.tv_usec = (int)_tms;
select(0, NULL, NULL, NULL, &timeout);

ret = 0;
#endif

return ret;
}

/* returns current timestamp in milliseconds */
uint64_t
cog_timestamp_ms(void)
Expand Down
13 changes: 11 additions & 2 deletions cog-utils/cog-utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -141,13 +141,22 @@ size_t cog_strndup(const char src[], size_t len, char **p_dest);
size_t cog_asprintf(char **strp, const char fmt[], ...);

/**
* @brief Sleep for milliseconds amount
* @brief Sleep for amount of milliseconds
*
* @param tms milliseconds amount to sleep for
* @param tms amount of milliseconds to sleep for
* @return 0 on success, -1 on error with an `errno` set to indicate the error
*/
int cog_sleep_ms(const long tms);


/**
* @brief Sleep for amount of microseconds
*
* @param tms amount of microseconds to sleep for
* @return 0 on success, -1 on error with an `errno` set to indicate the error
*/
int cog_sleep_us(const long tms);

/**
* @brief Get the current timestamp in milliseconds
*
Expand Down
90 changes: 48 additions & 42 deletions examples/timers.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,70 +2,76 @@
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include <signal.h>

#include "discord.h"

static int interrupted = 0;

static void
on_sigint(int sig) {
interrupted = 1;
print_timer_info(struct discord_timer *timer)
{
printf("Timer id:%u flags:%i "
"delay:%" PRIi64 " interval:%" PRIi64 " repeat:%" PRIi64 "\n",
timer->id, timer->flags, timer->delay, timer->interval,
timer->repeat);
}

static void
one_shot_timer_cb(struct discord *client, struct discord_timer *timer) {
printf("one_shot_timer_cb %u triggered with flags %i\n",
timer->id, timer->flags);
one_shot_timer_cb(struct discord *client, struct discord_timer *timer)
{
print_timer_info(timer);
if (~timer->flags & DISCORD_TIMER_CANCELED) {
// if timer is not canceled
puts(timer->data);

//DO NOT IGNORE CANCELATION
if (timer->flags & DISCORD_TIMER_CANCELED) {
puts("Timer has been canceled");
return;
}
if (interrupted) {
puts("Shutdown Canceled");
return;
}
puts(timer->data);
discord_shutdown(client);
// timers can be updated in the callback (see below)
if (0) {
timer->interval += 100;
timer->repeat = 1;
return; // skip free(timer->data);
}
}
else {
puts("ONE SHOT TIMER CANCELED");
}
free(timer->data);
}

static void
repeating_timer_cb(struct discord *client, struct discord_timer *timer) {
printf("repeating_timer_cb %u triggered with flags %i\n",
timer->id, timer->flags);
printf("%"PRIi64", %"PRIi64"\n", timer->interval, timer->repeat);
if (timer->repeat == 0)
puts("Shutting down soon, press ctrl + c to cancel");
repeating_timer_cb(struct discord *client, struct discord_timer *timer)
{
print_timer_info(timer);
if (timer->flags & DISCORD_TIMER_CANCELED) {
printf("TIMER WITH ID %u CANCELED\n", timer->id);
return;
}
printf("SHUTTING DOWN IN %" PRIi64 " SECONDS\n", timer->repeat);
if (!timer->repeat) {
discord_shutdown(client);
}
}

int
main(int argc, char *argv[])
{
const char *config_file = argc > 1 ? argv[1] : "../config.json";

signal(SIGINT, on_sigint);
ccord_global_init();

struct discord *client = discord_config_init(config_file);

//create one shot auto deleting timer
unsigned one_shot_timer_id =
discord_timer(client, one_shot_timer_cb, "Shutting Down", 5000);

discord_timer_ctl(client, &(struct discord_timer) {
.id = 0, /* 0 to create a new timer */
.cb = repeating_timer_cb,
.data = &one_shot_timer_id,
.delay = 0, /* start right away */
.interval = 100,
.repeat = 10, /* -1 for infinity, 0 for never */
.flags = DISCORD_TIMER_DELETE_AUTO,
});
discord_timer(client, one_shot_timer_cb, strdup("Hello World"), 1000);
discord_timer(client, one_shot_timer_cb, strdup("Hello World!!!!!!"),
5000);

// start a one shot timer that will never get a chance to run
discord_timer(client, one_shot_timer_cb, strdup("Hello World"), 15000);

discord_timer_interval(client, repeating_timer_cb, NULL, 0, 1000, 10);

// start 3 timers that will never get a chance to run
for (int i = 0; i < 3; i++)
discord_timer(client, repeating_timer_cb, NULL, 20 * 1000);

discord_run(client);

// discord_cleanup will cancel all timers that are still active
discord_cleanup(client);
ccord_global_cleanup();
}
}
39 changes: 21 additions & 18 deletions include/discord-internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ struct discord_adapter {
} * global;

/** idle request handles */
QUEUE(struct discord_context) *idleq;
QUEUE(struct discord_context) * idleq;

/** max amount of retries before a failed request gives up */
int retry_limit;
Expand Down Expand Up @@ -682,67 +682,70 @@ void discord_gateway_send_presence_update(struct discord_gateway *gw);

struct discord_timers {
priority_queue *q;
struct discord_timer *currently_being_run;
struct {
struct discord_timer *timer;
bool skip_update_phase;
} active;
};

/**
* @brief prepare timers for usage
*
*
* @param client the client created with discord_init()
*/
void discord_timers_init(struct discord *client);

/**
* @brief cleanup timers and call cancel any running ones
*
*
* @param client the client created with discord_init()
*/
void discord_timers_cleanup(struct discord *client);

/**
* @brief run all timers that are due
*
*
* @param client the client created with discord_init()
* @param timers the timers to run
*/
void discord_timers_run(struct discord *client, struct discord_timers *timers);

/**
* @brief modifies or creates a timer
*
*
* @param client the client created with discord_init()
* @param timers the timer group to perform this operation on
* @param timer the timer that should be modified
* @return the id of the timer
*/
unsigned _discord_timer_ctl(
struct discord *client,
struct discord_timers *timers,
struct discord_timer *timer);
unsigned _discord_timer_ctl(struct discord *client,
struct discord_timers *timers,
struct discord_timer *timer);

/**
* @brief modifies or creates a timer
*
*
* @param client the client created with discord_init()
* @param timer the timer that should be modified
* @return unsigned the id of the timer
*/
unsigned discord_internal_timer_ctl(
struct discord *client,
struct discord_timer *timer);
unsigned discord_internal_timer_ctl(struct discord *client,
struct discord_timer *timer);

/**
* @brief creates a one shot timer that automatically
* deletes itself upon completion
*
*
* @param client the client created with discord_init()
* @param cb the callback that should be called when timer triggers
* @param data user data
* @param delay delay before timer should start in milliseconds
* @return unsigned
* @return unsigned
*/
unsigned discord_internal_timer(struct discord *client, discord_ev_timer cb,
void *data, int64_t delay);
unsigned discord_internal_timer(struct discord *client,
discord_ev_timer cb,
void *data,
int64_t delay);

/** @} DiscordInternalTimer */
/**
Expand Down
Loading