Added a notification mechanism for sending messages from
another thread to the mainthread in a safe manner. This is used for the DNS lookup code, and can also be used by the signal handler to safely report actions back to the application mainloop without using global variables.
This commit is contained in:
parent
1526d63403
commit
46bdc77066
@ -141,7 +141,7 @@ int net_backend_process()
|
||||
}
|
||||
|
||||
// Process pending DNS results
|
||||
net_dns_process();
|
||||
// net_dns_process();
|
||||
|
||||
g_backend->handler.backend_process(g_backend->data, res);
|
||||
|
||||
|
@ -68,6 +68,11 @@ static void shutdown_free_results(void* ptr)
|
||||
net_dns_result_free(result);
|
||||
}
|
||||
|
||||
static void notify_callback(struct uhub_notify_handle* handle, void* ptr)
|
||||
{
|
||||
net_dns_process();
|
||||
}
|
||||
|
||||
|
||||
// NOTE: Any job manipulating the members of this
|
||||
// struct must lock the mutex!
|
||||
@ -76,6 +81,8 @@ struct net_dns_subsystem
|
||||
struct linked_list* jobs; // currently running jobs
|
||||
struct linked_list* results; // queue of results that are awaiting being delivered to callback.
|
||||
uhub_mutex_t mutex;
|
||||
|
||||
struct uhub_notify_handle* notify_handle; // used to signal back to the event loop that there is something to process.
|
||||
};
|
||||
|
||||
static struct net_dns_subsystem* g_dns = NULL;
|
||||
@ -87,6 +94,7 @@ void net_dns_initialize()
|
||||
g_dns->jobs = list_create();
|
||||
g_dns->results = list_create();
|
||||
uhub_mutex_init(&g_dns->mutex);
|
||||
g_dns->notify_handle = net_notify_create(notify_callback, g_dns);
|
||||
}
|
||||
|
||||
void net_dns_destroy()
|
||||
@ -105,6 +113,7 @@ void net_dns_destroy()
|
||||
list_destroy(g_dns->jobs);
|
||||
list_destroy(g_dns->results);
|
||||
uhub_mutex_destroy(&g_dns->mutex);
|
||||
net_notify_destroy(g_dns->notify_handle);
|
||||
hub_free(g_dns);
|
||||
g_dns = NULL;
|
||||
}
|
||||
@ -113,7 +122,7 @@ void net_dns_process()
|
||||
{
|
||||
struct net_dns_result* result;
|
||||
uhub_mutex_lock(&g_dns->mutex);
|
||||
LOG_DUMP("net_dns_process(): jobs=%d, results=%d", (int) list_size(g_dns->jobs), (int) list_size(g_dns->results));
|
||||
LOG_TRACE("net_dns_process(): jobs=%d, results=%d", (int) list_size(g_dns->jobs), (int) list_size(g_dns->results));
|
||||
|
||||
LIST_FOREACH(struct net_dns_result*, result, g_dns->results,
|
||||
{
|
||||
@ -210,6 +219,7 @@ static void* job_thread_resolve_name(void* ptr)
|
||||
uhub_mutex_lock(&g_dns->mutex);
|
||||
list_remove(g_dns->jobs, job);
|
||||
list_append(g_dns->results, dns_results);
|
||||
net_notify_signal(g_dns->notify_handle, 1);
|
||||
uhub_mutex_unlock(&g_dns->mutex);
|
||||
|
||||
return dns_results;
|
||||
|
102
src/network/notify.c
Normal file
102
src/network/notify.c
Normal file
@ -0,0 +1,102 @@
|
||||
/*
|
||||
* uhub - A tiny ADC p2p connection hub
|
||||
* Copyright (C) 2007-2014, Jan Vidar Krey
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "uhub.h"
|
||||
|
||||
struct uhub_notify_handle
|
||||
{
|
||||
net_notify_callback callback;
|
||||
void* ptr;
|
||||
#ifndef WIN32
|
||||
int pipe_fd[2];
|
||||
struct net_connection* con;
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
* This contains a mechanism to wake up the main thread
|
||||
* in a thread safe manner while it would be blocking
|
||||
* in select() or something equivalent typically invoked from
|
||||
* net_backend_process().
|
||||
*
|
||||
* The main usage is for the DNS resolver to notify the
|
||||
* main thread that there are DNS results to be
|
||||
* processed.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Create a notification handle.
|
||||
*/
|
||||
#ifndef WIN32
|
||||
static void notify_callback(struct net_connection* con, int event, void* ptr)
|
||||
{
|
||||
LOG_TRACE("notify_callback()");
|
||||
struct uhub_notify_handle* handle = (struct uhub_notify_handle*) ptr;
|
||||
char buf;
|
||||
int ret = read(handle->pipe_fd[0], &buf, 1);
|
||||
if (ret == 1)
|
||||
{
|
||||
if (handle->callback)
|
||||
handle->callback(handle, handle->ptr);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
struct uhub_notify_handle* net_notify_create(net_notify_callback cb, void* ptr)
|
||||
{
|
||||
LOG_TRACE("net_notify_create()");
|
||||
struct uhub_notify_handle* handle = (struct uhub_notify_handle*) hub_malloc(sizeof(struct uhub_notify_handle));
|
||||
handle->callback = cb;
|
||||
handle->ptr = ptr;
|
||||
#ifndef WIN32
|
||||
int ret = pipe(handle->pipe_fd);
|
||||
if (ret == -1)
|
||||
{
|
||||
LOG_ERROR("Unable to setup notification pipes.");
|
||||
hub_free(handle);
|
||||
return 0;
|
||||
}
|
||||
|
||||
handle->con = net_con_create();
|
||||
net_con_initialize(handle->con, handle->pipe_fd[0], notify_callback, handle, NET_EVENT_READ);
|
||||
#endif
|
||||
return handle;
|
||||
}
|
||||
|
||||
|
||||
void net_notify_destroy(struct uhub_notify_handle* handle)
|
||||
{
|
||||
LOG_TRACE("net_notify_destroy()");
|
||||
#ifndef WIN32
|
||||
net_con_destroy(handle->con);
|
||||
close(handle->pipe_fd[0]);
|
||||
close(handle->pipe_fd[1]);
|
||||
handle->pipe_fd[0] = -1;
|
||||
handle->pipe_fd[0] = -1;
|
||||
#endif
|
||||
hub_free(handle);
|
||||
}
|
||||
|
||||
void net_notify_signal(struct uhub_notify_handle* handle, char data)
|
||||
{
|
||||
LOG_TRACE("net_notify_signal()");
|
||||
#ifndef WIN32
|
||||
write(handle->pipe_fd[1], &data, 1);
|
||||
#endif
|
||||
}
|
56
src/network/notify.h
Normal file
56
src/network/notify.h
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* uhub - A tiny ADC p2p connection hub
|
||||
* Copyright (C) 2007-2014, Jan Vidar Krey
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef HAVE_UHUB_NETWORK_NOTIFY_API_H
|
||||
#define HAVE_UHUB_NETWORK_NOTIFY_API_H
|
||||
|
||||
struct uhub_notify_handle;
|
||||
|
||||
typedef void (*net_notify_callback)(struct uhub_notify_handle* handle, void* ptr);
|
||||
|
||||
/*
|
||||
* This contains a mechanism to wake up the main thread
|
||||
* in a thread safe manner while it would be blocking
|
||||
* in select() or something equivalent typically invoked from
|
||||
* net_backend_process().
|
||||
*
|
||||
* The main usage is for the DNS resolver to notify the
|
||||
* main thread that there are DNS results to be
|
||||
* processed.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Create a notification handle.
|
||||
*/
|
||||
struct uhub_notify_handle* net_notify_create(net_notify_callback cb, void* ptr);
|
||||
|
||||
/**
|
||||
* Destroy a notification handle.
|
||||
*/
|
||||
void net_notify_destroy(struct uhub_notify_handle*);
|
||||
|
||||
/**
|
||||
* Signal the notification handle, this will surely
|
||||
* interrupt the net_backend_process(), and force it to
|
||||
* process messages.
|
||||
*/
|
||||
void net_notify_signal(struct uhub_notify_handle*, char data);
|
||||
|
||||
|
||||
#endif /* HAVE_UHUB_NETWORK_NOTIFY_API_H */
|
@ -159,8 +159,7 @@ static int handle(struct ADC_client* client, enum ADC_client_callback_type type,
|
||||
static int running = 1;
|
||||
|
||||
#if !defined(WIN32)
|
||||
static int adm_pipes[2] = { -1, -1 };
|
||||
static struct net_connection* adm_con = 0;
|
||||
static struct uhub_notify_handle* notify_handle;
|
||||
|
||||
void adm_handle_signal(int sig)
|
||||
{
|
||||
@ -198,10 +197,6 @@ static int signals[] =
|
||||
0
|
||||
};
|
||||
|
||||
void adm_callback(struct net_connection* con, int event, void* ptr)
|
||||
{
|
||||
}
|
||||
|
||||
void adm_setup_signal_handlers()
|
||||
{
|
||||
sigset_t sig_set;
|
||||
@ -224,22 +219,13 @@ void adm_setup_signal_handlers()
|
||||
|
||||
void adm_setup_control_pipe()
|
||||
{
|
||||
int ret = pipe(adm_pipes);
|
||||
if (ret == -1)
|
||||
{
|
||||
LOG_ERROR("Unable to setup control pipes.");
|
||||
}
|
||||
adm_con = net_con_create();
|
||||
net_con_initialize(adm_con, adm_pipes[0], adm_callback, 0, NET_EVENT_READ);
|
||||
notify_handle = net_notify_create(NULL, NULL);
|
||||
}
|
||||
|
||||
void adm_shutdown_control_pipe()
|
||||
{
|
||||
net_con_destroy(adm_con);
|
||||
close(adm_pipes[0]);
|
||||
close(adm_pipes[1]);
|
||||
adm_pipes[0] = -1;
|
||||
adm_pipes[0] = -1;
|
||||
net_notify_destroy(notify_handle);
|
||||
notify_handle = NULL;
|
||||
}
|
||||
|
||||
void adm_shutdown_signal_handlers()
|
||||
|
@ -75,6 +75,7 @@ extern "C" {
|
||||
#include "adc/message.h"
|
||||
|
||||
#include "network/network.h"
|
||||
#include "network/notify.h"
|
||||
#include "network/connection.h"
|
||||
#include "network/dnsresolver.h"
|
||||
#include "network/ipcalc.h"
|
||||
|
Loading…
Reference in New Issue
Block a user