[svn-commits] russell: branch group/timing r122556 - /team/group/timing/res/

SVN commits to the Digium repositories svn-commits at lists.digium.com
Fri Jun 13 08:52:49 CDT 2008


Author: russell
Date: Fri Jun 13 08:52:47 2008
New Revision: 122556

URL: http://svn.digium.com/view/asterisk?view=rev&rev=122556
Log:
set up data structures and implement timing API ... now to add background thread
that does the real work

Modified:
    team/group/timing/res/res_timing_pthread.c

Modified: team/group/timing/res/res_timing_pthread.c
URL: http://svn.digium.com/view/asterisk/team/group/timing/res/res_timing_pthread.c?view=diff&rev=122556&r1=122555&r2=122556
==============================================================================
--- team/group/timing/res/res_timing_pthread.c (original)
+++ team/group/timing/res/res_timing_pthread.c Fri Jun 13 08:52:47 2008
@@ -34,6 +34,7 @@
 #include "asterisk/module.h"
 #include "asterisk/timing.h"
 #include "asterisk/utils.h"
+#include "asterisk/astobj2.h"
 
 static void *timing_funcs_handle;
 
@@ -55,48 +56,234 @@
 	.timer_get_event = pthread_timer_get_event,
 };
 
+static struct ao2_container *pthread_timers;
+#define PTHREAD_TIMER_BUCKETS 563
+
+enum {
+	PIPE_READ =  0,
+	PIPE_WRITE = 1
+};
+
+enum pthread_timer_state {
+	TIMER_STATE_IDLE,
+	TIMER_STATE_TICKING,
+	TIMER_STATE_CONTINUOUS,
+};
+
+struct pthread_timer {
+	int pipe[2];
+	enum pthread_timer_state state;
+	unsigned int rate;
+};
+
+static void pthread_timer_destructor(void *obj);
+static struct pthread_timer *find_timer(int handle, int unlink);
+
 static int pthread_timer_open(void)
 {
+	struct pthread_timer *timer;
+
+	if (!(timer = ao2_alloc(sizeof(*timer), pthread_timer_destructor))) {
+		errno = ENOMEM;
+		return -1;
+	}
+
+	timer->pipe[PIPE_READ] = timer->pipe[PIPE_WRITE] = -1;
+	timer->state = TIMER_STATE_IDLE;
+
+	if (pipe(timer->pipe)) {
+		ao2_ref(timer, -1);
+		return -1;
+	}
+
+	ao2_link(pthread_timers, timer);
+
+	return timer->pipe[PIPE_READ];
+}
+
+static void pthread_timer_close(int handle)
+{
+	struct pthread_timer *timer;
+
+	if (!(timer = find_timer(handle, 1))) {
+		return;
+	}
+
+	ao2_ref(timer, -1);
+}
+
+static int pthread_timer_set_rate(int handle, unsigned int rate)
+{
+	struct pthread_timer *timer;
+
+	if (!(timer = find_timer(handle, 0))) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	ao2_lock(timer);
+	timer->rate = rate;
+	timer->state = rate ? TIMER_STATE_TICKING : TIMER_STATE_IDLE;
+	ao2_unlock(timer);
+
+	ao2_ref(timer, -1);
+
 	return 0;
 }
 
-static void pthread_timer_close(int handle)
-{
-}
-
-static int pthread_timer_set_rate(int handle, unsigned int rate)
-{
+static void pthread_timer_ack(int handle, unsigned int quantity)
+{
+	struct pthread_timer *timer;
+	ssize_t res;
+
+	ast_assert(quantity > 0);
+
+	if (!(timer = find_timer(handle, 0))) {
+		return;
+	}
+
+	do {
+		unsigned char buf[1024];
+
+		res = read(timer->pipe[PIPE_READ], buf, quantity);
+
+		if (res == -1) {
+			if (errno == EAGAIN) {
+				continue;
+			}
+			ast_log(LOG_ERROR, "read failed on timing pipe: %s\n", strerror(errno));
+			break;
+		}
+
+		quantity -= res;
+
+	} while (quantity);
+
+	ao2_ref(timer, -1);
+}
+
+static int pthread_timer_enable_continuous(int handle)
+{
+	struct pthread_timer *timer;
+
+	if (!(timer = find_timer(handle, 0))) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	timer->state = TIMER_STATE_CONTINUOUS;
+
+	ao2_ref(timer, -1);
+
 	return 0;
 }
 
-static void pthread_timer_ack(int handle, unsigned int quantity)
-{
-}
-
-static int pthread_timer_enable_continuous(int handle)
-{
+static int pthread_timer_disable_continuous(int handle)
+{
+	struct pthread_timer *timer;
+
+	if (!(timer = find_timer(handle, 0))) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	timer->state = timer->rate ? TIMER_STATE_TICKING : TIMER_STATE_IDLE;
+
+	ao2_ref(timer, -1);
+
 	return 0;
 }
 
-static int pthread_timer_disable_continuous(int handle)
-{
-	return 0;
-}
-
 static enum ast_timing_event pthread_timer_get_event(int handle)
 {
-	return 0;
+	struct pthread_timer *timer;
+	enum ast_timing_event res = AST_TIMING_EVENT_EXPIRED;
+
+	if (!(timer = find_timer(handle, 0))) {
+		return res;
+	}
+
+	if (timer->state == TIMER_STATE_CONTINUOUS) {
+		res = AST_TIMING_EVENT_CONTINUOUS;
+	}
+
+	ao2_ref(timer, -1);
+
+	return res;
+}
+
+static struct pthread_timer *find_timer(int handle, int unlink)
+{
+	struct pthread_timer *timer;
+	struct pthread_timer tmp_timer;
+	int flags = OBJ_POINTER;
+
+	tmp_timer.pipe[PIPE_READ] = handle;
+
+	if (unlink) {
+		flags |= OBJ_UNLINK;
+	}
+
+	if (!(timer = ao2_find(pthread_timers, &tmp_timer, flags))) {
+		ast_assert(timer != NULL);
+		return NULL;
+	}
+
+	return timer;
+}
+
+static void pthread_timer_destructor(void *obj)
+{
+	struct pthread_timer *timer = obj;
+
+	if (timer->pipe[PIPE_READ] > -1) {
+		close(timer->pipe[PIPE_READ]);
+		timer->pipe[PIPE_READ] = -1;
+	}
+
+	if (timer->pipe[PIPE_WRITE] > -1) {
+		close(timer->pipe[PIPE_WRITE]);
+		timer->pipe[PIPE_WRITE] = -1;
+	}
+}
+
+/*!
+ * \note only PIPE_READ is guaranteed valid 
+ */
+static int pthread_timer_hash(const void *obj, const int flags)
+{
+	const struct pthread_timer *timer = obj;
+
+	return timer->pipe[PIPE_READ];
+}
+
+/*!
+ * \note only PIPE_READ is guaranteed valid 
+ */
+static int pthread_timer_cmp(void *obj, void *arg, int flags)
+{
+	struct pthread_timer *timer1 = obj, *timer2 = arg;
+
+	return (timer1->pipe[PIPE_READ] == timer2->pipe[PIPE_READ]) ? CMP_MATCH : 0;
 }
 
 static int load_module(void)
 {
+	if (!(pthread_timers = ao2_container_alloc(PTHREAD_TIMER_BUCKETS, 
+		pthread_timer_hash, pthread_timer_cmp))) {
+		return AST_MODULE_LOAD_DECLINE;
+	}
+
 	return (timing_funcs_handle = ast_install_timing_functions(&pthread_timing_functions)) ?
 		AST_MODULE_LOAD_SUCCESS : AST_MODULE_LOAD_DECLINE;
 }
 
 static int unload_module(void)
 {
-	/* ast_uninstall_timing_functions(timing_funcs_handle); */
+#if 0
+	ast_uninstall_timing_functions(timing_funcs_handle);
+	ao2_ref(pthread_timers, -1);
+#endif
 
 	/* This module can not currently be unloaded.  No use count handling is being done. */
 




More information about the svn-commits mailing list