try out a queue API to notify "listeners" of the session
I was always unsure on what to do: a callback or a simple queue for dc_event_t. But since we already have dc_event_t (and ref counting) this seemed like the best solution.
This commit is contained in:
parent
551e67c823
commit
bd88d735eb
@ -83,6 +83,23 @@ dc_account_t dc_session_me(dc_session_t s);
|
||||
*/
|
||||
dc_api_t dc_session_api(dc_session_t s);
|
||||
|
||||
/**
|
||||
* Queue API. If you enable queuing the session will keep the events from the
|
||||
* web socket around for you to handle. Please note that all internal states
|
||||
* will already have been upgraded, and changed once you pull these events
|
||||
* from the queue. Also note that if you enable queuing but never pull these
|
||||
* events from the queue they will pile up, and use a lot of memory.
|
||||
*
|
||||
* If you disable queuing then the queue is deleted, and no more events are
|
||||
* placed into the queue.
|
||||
*
|
||||
* dc_session_pop_event() will remove an event from the queue for you to handle.
|
||||
* You will have to call dc_unref() on it yourself to cleanup any internal data
|
||||
* of the event. It will return NULL if no event is in the queue.
|
||||
*/
|
||||
void dc_session_enable_queue(dc_session_t s, bool enable);
|
||||
dc_event_t dc_session_pop_event(dc_session_t s);
|
||||
|
||||
/**
|
||||
* access to the internal account cache
|
||||
*/
|
||||
|
@ -32,6 +32,9 @@ struct dc_session_
|
||||
GHashTable *accounts;
|
||||
GHashTable *channels;
|
||||
GHashTable *guilds;
|
||||
|
||||
GQueue *queue;
|
||||
pthread_mutex_t *mutex;
|
||||
};
|
||||
|
||||
/* event handlers
|
||||
@ -50,6 +53,16 @@ static void dc_session_free(dc_session_t s)
|
||||
{
|
||||
return_if_true(s == NULL,);
|
||||
|
||||
if (s->mutex != NULL) {
|
||||
pthread_mutex_lock(s->mutex);
|
||||
if (s->queue != NULL) {
|
||||
g_queue_free_full(s->queue, (GDestroyNotify)dc_unref);
|
||||
s->queue = NULL;
|
||||
}
|
||||
pthread_mutex_destroy(s->mutex);
|
||||
s->mutex = NULL;
|
||||
}
|
||||
|
||||
if (s->accounts != NULL) {
|
||||
g_hash_table_unref(s->accounts);
|
||||
s->accounts = NULL;
|
||||
@ -189,6 +202,14 @@ static void dc_session_handler(dc_gateway_t gw, dc_event_t e, void *p)
|
||||
h(s, e);
|
||||
}
|
||||
|
||||
/* add to queue, if the queue is enabled
|
||||
*/
|
||||
pthread_mutex_lock(s->mutex);
|
||||
if (s->queue != NULL) {
|
||||
g_queue_push_tail(s->queue, dc_ref(e));
|
||||
}
|
||||
pthread_mutex_unlock(s->mutex);
|
||||
|
||||
#ifdef DEBUG
|
||||
char *str = NULL;
|
||||
str = json_dumps(dc_event_payload(e), 0);
|
||||
@ -223,6 +244,9 @@ dc_session_t dc_session_new(dc_loop_t loop)
|
||||
);
|
||||
goto_if_true(s->channels == NULL, error);
|
||||
|
||||
s->mutex = calloc(1, sizeof(pthread_mutex_t));
|
||||
goto_if_true(s->mutex == NULL, error);
|
||||
|
||||
s->loop = dc_ref(loop);
|
||||
|
||||
s->api = dc_api_new();
|
||||
@ -337,6 +361,38 @@ bool dc_session_equal_me(dc_session_t s, dc_account_t a)
|
||||
);
|
||||
}
|
||||
|
||||
void dc_session_enable_queue(dc_session_t s, bool enable)
|
||||
{
|
||||
return_if_true(s == NULL,);
|
||||
|
||||
return_if_true(enable == true && s->queue != NULL,);
|
||||
return_if_true(enable == false && s->queue == NULL,);
|
||||
|
||||
if (enable) {
|
||||
pthread_mutex_lock(s->mutex);
|
||||
s->queue = g_queue_new();
|
||||
pthread_mutex_unlock(s->mutex);
|
||||
} else {
|
||||
pthread_mutex_lock(s->mutex);
|
||||
g_queue_free_full(s->queue, (GDestroyNotify)dc_unref);
|
||||
s->queue = NULL;
|
||||
pthread_mutex_unlock(s->mutex);
|
||||
}
|
||||
}
|
||||
|
||||
dc_event_t dc_session_pop_event(dc_session_t s)
|
||||
{
|
||||
return_if_true(s == NULL || s->queue == NULL, NULL);
|
||||
|
||||
dc_event_t e = NULL;
|
||||
|
||||
pthread_mutex_lock(s->mutex);
|
||||
e = g_queue_pop_head(s->queue);
|
||||
pthread_mutex_unlock(s->mutex);
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
bool dc_session_equal_me_fullname(dc_session_t s, char const *a)
|
||||
{
|
||||
return_if_true(s == NULL || s->login == NULL || a == NULL, false);
|
||||
|
@ -51,6 +51,10 @@ bool ncdc_cmd_login(ncdc_mainwindow_t n, size_t ac,
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* enable queueing
|
||||
*/
|
||||
dc_session_enable_queue(s, true);
|
||||
|
||||
g_ptr_array_add(sessions, s);
|
||||
} else {
|
||||
s = g_ptr_array_index(sessions, idx);
|
||||
@ -68,14 +72,7 @@ bool ncdc_cmd_login(ncdc_mainwindow_t n, size_t ac,
|
||||
dc_unref(current_session);
|
||||
current_session = dc_ref(s);
|
||||
|
||||
LOG(n, L"login: %ls: authentication successful, waiting for ready "
|
||||
L"from websocket...", av[1]);
|
||||
|
||||
while (!dc_session_is_ready(current_session))
|
||||
;
|
||||
|
||||
LOG(n, L"login: %ls: ready", av[1]);
|
||||
ncdc_mainwindow_update_guilds(n);
|
||||
LOG(n, L"login: %ls: authentication successful", av[1]);
|
||||
|
||||
ret = true;
|
||||
|
||||
|
@ -477,10 +477,38 @@ void ncdc_mainwindow_switch_view(ncdc_mainwindow_t n, ncdc_textview_t v)
|
||||
}
|
||||
}
|
||||
|
||||
static void ncdc_mainwindow_handle_events(ncdc_mainwindow_t n)
|
||||
{
|
||||
if (!is_logged_in()) {
|
||||
return;
|
||||
}
|
||||
|
||||
dc_event_t e = NULL;
|
||||
|
||||
e = dc_session_pop_event(current_session);
|
||||
if (e == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (dc_event_type_code(e)) {
|
||||
case DC_EVENT_TYPE_READY:
|
||||
{
|
||||
LOG(n, L"connection to discord is ready");
|
||||
ncdc_mainwindow_update_guilds(n);
|
||||
} break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
|
||||
dc_unref(e);
|
||||
}
|
||||
|
||||
void ncdc_mainwindow_refresh(ncdc_mainwindow_t n)
|
||||
{
|
||||
ncdc_textview_t v = 0;
|
||||
|
||||
ncdc_mainwindow_handle_events(n);
|
||||
|
||||
ncdc_treeview_render(n->guildview, n->guilds, n->guilds_h, n->guilds_w);
|
||||
wnoutrefresh(n->guilds);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user