toxcore/toxmsi/toxmsi_event.c
2013-10-13 16:16:47 +02:00

215 lines
5.6 KiB
C

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#include <stdlib.h>
#include "toxmsi_event.h"
#include "../toxrtp/toxrtp_helper.h"
#include <assert.h>
#include <stdlib.h>
#include <unistd.h>
static int _unique_id = 1;
/* clear events */
void clear_events (event_container_t** _event_container, size_t* _counter)
{
assert( *_event_container );
free(*_event_container);
*_event_container = NULL;
*_counter = 0;
}
int pop_id ( event_container_t** _event_container, size_t* _counter, int _id )
{
if ( !*_event_container || !*_counter || !_id )
return FAILURE;
event_container_t* _it = *_event_container;
int i;
for ( i = *_counter; i > 0 ; -- i ){
if ( _it->_id == _id ) { /* Hit! */
break;
}
++_it;
}
if ( i ) {
for ( ; i > 0; -- i ){ *_it = *(_it + 1); ++_it; }
-- (*_counter);
*_event_container = realloc(*_event_container, sizeof(event_container_t) * (*_counter)); /* resize */
if ( *_counter )
assert(*_event_container);
return SUCCESS;
} else {
assert(i);
return FAILURE;
}
}
/* main poll for event execution */
void* event_poll( void* _event_handler_p )
{
event_handler_t* _event_handler = _event_handler_p;
uint32_t* _frequms = &_event_handler->_frequms;
while ( _event_handler->_running )
{
if ( _event_handler->_events_count ){
pthread_mutex_lock(&_event_handler->_mutex);
int i;
for ( i = 0; i < _event_handler->_events_count; i ++ ){
_event_handler->_events[i]._event(_event_handler->_events[i]._event_args);
}
clear_events(&_event_handler->_events, &_event_handler->_events_count);
pthread_mutex_unlock(&_event_handler->_mutex);
}
if ( _event_handler->_timed_events_count ){
pthread_mutex_lock(&_event_handler->_mutex);
uint32_t _time = t_time();
if ( _event_handler->_timed_events[0]._timeout < _time ) {
_event_handler->_timed_events[0]._event(_event_handler->_timed_events[0]._event_args);
pop_id(&_event_handler->_timed_events,
&_event_handler->_timed_events_count,
_event_handler->_timed_events[0]._id);
}
pthread_mutex_unlock(&_event_handler->_mutex);
}
usleep(*_frequms);
}
_event_handler->_running = -1;
pthread_exit(NULL);
}
void push_event ( event_container_t** _container, size_t* _counter, event_t _func, event_arg_t _arg )
{
(*_counter)++;
(*_container) = realloc((*_container), sizeof(event_container_t) * (*_counter));
assert((*_container) != NULL);
(*_container[*_counter - 1])._event = _func;
(*_container[*_counter - 1])._event_args = _arg;
(*_container[*_counter - 1])._timeout = 0;
(*_container[*_counter - 1])._id = 0;
}
void throw_event( void* _event_handler_p, event_t _func, event_arg_t _arg )
{
if ( !_func )
return;
event_handler_t* _event_handler = _event_handler_p;
pthread_mutex_lock(&_event_handler->_mutex);
push_event(&_event_handler->_events, &_event_handler->_events_count, _func, _arg);
pthread_mutex_unlock(&_event_handler->_mutex);
}
int throw_timer_event ( void* _event_handler_p, event_t _func, event_arg_t _arg, uint32_t _timeout)
{
if ( !_func )
return FAILURE;
event_handler_t* _event_handler = _event_handler_p;
pthread_mutex_lock(&_event_handler->_mutex);
push_event(&_event_handler->_timed_events, &_event_handler->_timed_events_count, _func, _arg);
size_t _counter = _event_handler->_timed_events_count;
_event_handler->_timed_events[_counter - 1]._timeout = _timeout + t_time();
_event_handler->_timed_events[_counter - 1]._id = _unique_id; ++_unique_id;
/* reorder */
if ( _counter > 1 ) {
int i = _counter - 1;
/* start from behind excluding last added member */
event_container_t* _it = &_event_handler->_timed_events[i - 1];
event_container_t _last_added = _event_handler->_timed_events[i];
for ( ; i > 0; --i ) {
if ( _it->_timeout > _timeout ){
*(_it + 1) = *_it;
*_it = _last_added; -- _it;
}
}
}
pthread_mutex_unlock(&_event_handler->_mutex);
return _event_handler->_timed_events[_counter - 1]._id;
}
int cancel_timer_event ( void* _event_handler_p, int _id )
{
event_handler_t* _event_handler = _event_handler_p;
return pop_id(&_event_handler->_timed_events, &_event_handler->_timed_events_count, _id);
}
event_handler_t* init_event_poll (uint32_t _frequms)
{
event_handler_t* _retu = calloc(sizeof(event_handler_t), 1);
assert(_retu);
/* Initialize basic events */
_retu->_events = NULL ;
/* Initialize timed events */
_retu->_timed_events = NULL;
_retu->_frequms = _frequms;
_retu->_running = 1;
pthread_mutex_init(&_retu->_mutex, NULL);
pthread_create(&_retu->_thread_id, NULL, event_poll, _retu);
int _rc = pthread_detach(_retu->_thread_id);
assert(_rc == 0);
return _retu;
}
int terminate_event_poll(event_handler_t* _handler)
{
if ( !_handler )
return FAILURE;
_handler->_running = 0;
while (_handler->_running != -1); /* Wait for execution */
if (_handler->_events)
clear_events(&_handler->_events, &_handler->_events_count);
if (_handler->_events)
clear_events(&_handler->_timed_events, &_handler->_timed_events_count);
pthread_mutex_destroy( &_handler->_mutex );
free(_handler);
return SUCCESS;
}