From 47b7d22be41f372175aa32c32d5ccff50aaab068 Mon Sep 17 00:00:00 2001 From: lcsmuller Date: Sat, 21 May 2022 14:29:25 -0300 Subject: [PATCH 1/2] wip(discord-rest): move bucket's pthread_cond_t to individual 'struct discord_context' --- include/discord-internal.h | 18 +++++++++--------- src/discord-rest.c | 31 ++++++++++++++++++++----------- src/discord-rest_async.c | 20 +++++++++++++------- src/discord-rest_ratelimit.c | 9 ++++----- 4 files changed, 46 insertions(+), 32 deletions(-) diff --git a/include/discord-internal.h b/include/discord-internal.h index 41964eb41..70df0253e 100644 --- a/include/discord-internal.h +++ b/include/discord-internal.h @@ -17,7 +17,7 @@ #include "jsmn.h" #include "jsmn-find.h" -#include "logconf.h" /* struct logconf */ +#include "logconf.h" #include "user-agent.h" #include "websockets.h" #include "work.h" @@ -251,11 +251,13 @@ struct discord_context { char key[DISCORD_ROUTE_LEN]; /** the connection handler assigned */ struct ua_conn *conn; - /** the request bucket's queue entry */ - QUEUE entry; /** current retry attempt (stop at rest->retry_limit) */ int retry_attempt; + /** the request bucket's queue entry */ + QUEUE entry; + /** synchronize synchronous requests */ + pthread_cond_t *cond; }; /** @brief The handle used for handling asynchronous requests */ @@ -352,7 +354,8 @@ struct discord_context *discord_async_start_context( struct ccord_szbuf *body, enum http_method method, char endpoint[DISCORD_ENDPT_LEN], - char key[DISCORD_ROUTE_LEN]); + char key[DISCORD_ROUTE_LEN], + struct discord_bucket *b); /** @} DiscordInternalRESTAsync */ @@ -470,11 +473,8 @@ struct discord_bucket { * @note @ref DISCORD_BUCKET_TIMEOUT if bucket is being ratelimited */ struct discord_context *performing_cxt; - /** wait and notify synchronous requests */ - struct { - pthread_cond_t cond; - pthread_mutex_t lock; - } sync; + /** synchronize bucket */ + pthread_mutex_t lock; }; /** diff --git a/src/discord-rest.c b/src/discord-rest.c index 832c55fd7..60a9378a0 100644 --- a/src/discord-rest.c +++ b/src/discord-rest.c @@ -224,8 +224,7 @@ _discord_rest_check_action(struct discord_rest *rest, struct CURLMsg *msg) curl_easy_getinfo(msg->easy_handle, CURLINFO_PRIVATE, &cxt); - pthread_mutex_lock(&cxt->b->sync.lock); - + pthread_mutex_lock(&cxt->b->lock); resp = (struct discord_response){ .data = cxt->dispatch.data, .keep = cxt->dispatch.keep, .code = CCORD_OK }; @@ -312,9 +311,9 @@ _discord_rest_check_action(struct discord_rest *rest, struct CURLMsg *msg) cxt->b->performing_cxt = NULL; if (!retry || !discord_async_retry_context(&rest->async, cxt, wait_ms)) { discord_async_recycle_context(&rest->async, cxt); - pthread_cond_signal(&cxt->b->sync.cond); + if (cxt->cond) pthread_cond_signal(cxt->cond); } - pthread_mutex_unlock(&cxt->b->sync.lock); + pthread_mutex_unlock(&cxt->b->lock); return resp.code; } @@ -426,17 +425,27 @@ _discord_rest_start_context(struct discord_rest *rest, char endpoint[DISCORD_ENDPT_LEN], char key[DISCORD_ROUTE_LEN]) { - struct discord_context *cxt = discord_async_start_context( - &rest->async, req, body, method, endpoint, key); + struct discord_bucket *b = discord_bucket_get(&rest->ratelimiter, key); + struct discord_context *cxt; - pthread_mutex_lock(&cxt->b->sync.lock); + pthread_mutex_lock(&b->lock); - discord_bucket_add_context(cxt->b, cxt, cxt->dispatch.high_p); + cxt = discord_async_start_context( + &rest->async, req, body, method, endpoint, key, b); - if (cxt->dispatch.sync) - pthread_cond_wait(&cxt->b->sync.cond, &cxt->b->sync.lock); + if (cxt->dispatch.sync) { +#if 0 + cxt->cond = &(pthread_cond_t)PTHREAD_COND_INITIALIZER; +#else + pthread_cond_t cond; + pthread_cond_init(&cond, NULL); + cxt->cond = &cond; +#endif + pthread_cond_wait(cxt->cond, &b->lock); + + } - pthread_mutex_unlock(&cxt->b->sync.lock); + pthread_mutex_unlock(&b->lock); return CCORD_OK; } diff --git a/src/discord-rest_async.c b/src/discord-rest_async.c index f6812708f..947d6347b 100644 --- a/src/discord-rest_async.c +++ b/src/discord-rest_async.c @@ -107,9 +107,12 @@ discord_async_add_request(struct discord_async *async, curl_easy_setopt(ehandle, CURLOPT_PRIVATE, cxt); /* initiate libcurl transfer */ - return curl_multi_add_handle(async->mhandle, ehandle) - ? CCORD_CURLM_INTERNAL - : CCORD_OK; + if (curl_multi_add_handle(async->mhandle, ehandle) != CURLM_OK) + return CCORD_CURLM_INTERNAL; + + io_poller_wakeup(async->io_poller); + + return CCORD_OK; } bool @@ -198,7 +201,8 @@ discord_async_start_context(struct discord_async *async, struct ccord_szbuf *body, enum http_method method, char endpoint[DISCORD_ENDPT_LEN], - char key[DISCORD_ROUTE_LEN]) + char key[DISCORD_ROUTE_LEN], + struct discord_bucket *b) { struct discord_rest *rest = CONTAINEROF(async, struct discord_rest, async); struct discord *client = CLIENT(rest, rest); @@ -227,8 +231,8 @@ discord_async_start_context(struct discord_async *async, memcpy(cxt->endpoint, endpoint, sizeof(cxt->endpoint)); /* copy bucket's key */ memcpy(cxt->key, key, sizeof(cxt->key)); - /* bucket pertaining to the request */ - cxt->b = discord_bucket_get(&rest->ratelimiter, key); + + cxt->cond = NULL; if (req->dispatch.keep) { CCORDcode code = discord_refcounter_incr(&client->refcounter, @@ -246,6 +250,8 @@ discord_async_start_context(struct discord_async *async, req->dispatch.cleanup, false); } - io_poller_wakeup(async->io_poller); + /* bucket pertaining to the request */ + discord_bucket_add_context(b, cxt, cxt->dispatch.high_p); + return cxt; } diff --git a/src/discord-rest_ratelimit.c b/src/discord-rest_ratelimit.c index fff833f8a..a4fc832b1 100644 --- a/src/discord-rest_ratelimit.c +++ b/src/discord-rest_ratelimit.c @@ -36,8 +36,7 @@ struct _discord_route { static void _discord_bucket_cleanup(struct discord_bucket *b) { - pthread_cond_destroy(&b->sync.cond); - pthread_mutex_destroy(&b->sync.lock); + pthread_mutex_destroy(&b->lock); free(b); } @@ -131,9 +130,7 @@ _discord_bucket_init(struct discord_ratelimiter *rl, b->remaining = 1; b->limit = limit; - ASSERT_S(!pthread_cond_init(&b->sync.cond, NULL), - "Couldn't initialize bucket's cond"); - ASSERT_S(!pthread_mutex_init(&b->sync.lock, NULL), + ASSERT_S(!pthread_mutex_init(&b->lock, NULL), "Couldn't initialize bucket's mutex"); QUEUE_INIT(&b->pending_queue); @@ -423,6 +420,8 @@ discord_bucket_add_context(struct discord_bucket *b, QUEUE_INSERT_HEAD(&b->pending_queue, &cxt->entry); else QUEUE_INSERT_TAIL(&b->pending_queue, &cxt->entry); + + cxt->b = b; } struct discord_context * From a30f2b47fe67aae90d837e147fb96b0ee040807d Mon Sep 17 00:00:00 2001 From: lcsmuller Date: Sat, 21 May 2022 14:45:00 -0300 Subject: [PATCH 2/2] fix(discord-rest_async.c): move io_poller_wakeup() back to discord_async_start_context() --- src/discord-rest.c | 7 ------- src/discord-rest_async.c | 11 +++++------ 2 files changed, 5 insertions(+), 13 deletions(-) diff --git a/src/discord-rest.c b/src/discord-rest.c index 60a9378a0..a2d0e953c 100644 --- a/src/discord-rest.c +++ b/src/discord-rest.c @@ -434,15 +434,8 @@ _discord_rest_start_context(struct discord_rest *rest, &rest->async, req, body, method, endpoint, key, b); if (cxt->dispatch.sync) { -#if 0 cxt->cond = &(pthread_cond_t)PTHREAD_COND_INITIALIZER; -#else - pthread_cond_t cond; - pthread_cond_init(&cond, NULL); - cxt->cond = &cond; -#endif pthread_cond_wait(cxt->cond, &b->lock); - } pthread_mutex_unlock(&b->lock); diff --git a/src/discord-rest_async.c b/src/discord-rest_async.c index 947d6347b..2778458e7 100644 --- a/src/discord-rest_async.c +++ b/src/discord-rest_async.c @@ -107,12 +107,9 @@ discord_async_add_request(struct discord_async *async, curl_easy_setopt(ehandle, CURLOPT_PRIVATE, cxt); /* initiate libcurl transfer */ - if (curl_multi_add_handle(async->mhandle, ehandle) != CURLM_OK) - return CCORD_CURLM_INTERNAL; - - io_poller_wakeup(async->io_poller); - - return CCORD_OK; + return (curl_multi_add_handle(async->mhandle, ehandle) != CURLM_OK) + ? CCORD_CURLM_INTERNAL + : CCORD_OK; } bool @@ -253,5 +250,7 @@ discord_async_start_context(struct discord_async *async, /* bucket pertaining to the request */ discord_bucket_add_context(b, cxt, cxt->dispatch.high_p); + io_poller_wakeup(async->io_poller); + return cxt; }