mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-07 13:30:09 -05:00
loop: build loop with SPA interface
This commit is contained in:
parent
80deb6b387
commit
f42268b9a5
6 changed files with 429 additions and 446 deletions
|
|
@ -35,20 +35,20 @@
|
|||
#include <pinos/client/loop.h>
|
||||
#include <pinos/client/log.h>
|
||||
|
||||
struct _PinosSource {
|
||||
typedef struct {
|
||||
SpaSource source;
|
||||
SpaList link;
|
||||
|
||||
bool close;
|
||||
union {
|
||||
PinosSourceIOFunc io;
|
||||
PinosSourceIdleFunc idle;
|
||||
PinosSourceEventFunc event;
|
||||
PinosSourceTimerFunc timer;
|
||||
PinosSourceSignalFunc signal;
|
||||
SpaSourceIOFunc io;
|
||||
SpaSourceIdleFunc idle;
|
||||
SpaSourceEventFunc event;
|
||||
SpaSourceTimerFunc timer;
|
||||
SpaSourceSignalFunc signal;
|
||||
} func;
|
||||
int signal_number;
|
||||
};
|
||||
} SpaSourceImpl;
|
||||
|
||||
#define DATAS_SIZE (4096 * 8)
|
||||
|
||||
|
|
@ -66,20 +66,21 @@ typedef struct {
|
|||
|
||||
SpaList source_list;
|
||||
|
||||
PinosLoopHook pre_func;
|
||||
PinosLoopHook post_func;
|
||||
SpaLoopHook pre_func;
|
||||
SpaLoopHook post_func;
|
||||
void *hook_data;
|
||||
|
||||
int epoll_fd;
|
||||
pthread_t thread;
|
||||
|
||||
SpaLoop loop;
|
||||
SpaLoop loop;
|
||||
SpaLoopControl control;
|
||||
SpaLoopUtils utils;
|
||||
|
||||
PinosSource *event;
|
||||
SpaSource *event;
|
||||
|
||||
SpaRingbuffer buffer;
|
||||
uint8_t buffer_data[DATAS_SIZE];
|
||||
|
||||
int epoll_fd;
|
||||
SpaRingbuffer buffer;
|
||||
uint8_t buffer_data[DATAS_SIZE];
|
||||
} PinosLoopImpl;
|
||||
|
||||
static SpaResult
|
||||
|
|
@ -189,7 +190,7 @@ loop_invoke (SpaLoop *loop,
|
|||
|
||||
spa_ringbuffer_write_advance (&impl->buffer, item->item_size);
|
||||
|
||||
pinos_source_event_signal (impl->event);
|
||||
pinos_loop_signal_event (&impl->this, impl->event);
|
||||
|
||||
if (seq != SPA_ID_INVALID)
|
||||
res = SPA_RESULT_RETURN_ASYNC (seq);
|
||||
|
|
@ -200,8 +201,8 @@ loop_invoke (SpaLoop *loop,
|
|||
}
|
||||
|
||||
static void
|
||||
event_func (PinosSource *source,
|
||||
void *data)
|
||||
event_func (SpaSource *source,
|
||||
void *data)
|
||||
{
|
||||
PinosLoopImpl *impl = data;
|
||||
size_t offset;
|
||||
|
|
@ -213,6 +214,342 @@ event_func (PinosSource *source,
|
|||
}
|
||||
}
|
||||
|
||||
static int
|
||||
loop_get_fd (SpaLoopControl *ctrl)
|
||||
{
|
||||
PinosLoopImpl *impl = SPA_CONTAINER_OF (ctrl, PinosLoopImpl, control);
|
||||
|
||||
return impl->epoll_fd;
|
||||
}
|
||||
|
||||
static void
|
||||
loop_set_hooks (SpaLoopControl *ctrl,
|
||||
SpaLoopHook pre_func,
|
||||
SpaLoopHook post_func,
|
||||
void *data)
|
||||
{
|
||||
PinosLoopImpl *impl = SPA_CONTAINER_OF (ctrl, PinosLoopImpl, control);
|
||||
|
||||
impl->pre_func = pre_func;
|
||||
impl->post_func = post_func;
|
||||
impl->hook_data = data;
|
||||
}
|
||||
|
||||
static void
|
||||
loop_enter (SpaLoopControl *ctrl)
|
||||
{
|
||||
PinosLoopImpl *impl = SPA_CONTAINER_OF (ctrl, PinosLoopImpl, control);
|
||||
impl->thread = pthread_self();
|
||||
}
|
||||
|
||||
static void
|
||||
loop_leave (SpaLoopControl *ctrl)
|
||||
{
|
||||
PinosLoopImpl *impl = SPA_CONTAINER_OF (ctrl, PinosLoopImpl, control);
|
||||
impl->thread = 0;
|
||||
}
|
||||
|
||||
static SpaResult
|
||||
loop_iterate (SpaLoopControl *ctrl,
|
||||
int timeout)
|
||||
{
|
||||
PinosLoopImpl *impl = SPA_CONTAINER_OF (ctrl, PinosLoopImpl, control);
|
||||
struct epoll_event ep[32];
|
||||
int i, nfds, save_errno;
|
||||
|
||||
if (SPA_UNLIKELY (impl->pre_func))
|
||||
impl->pre_func (ctrl, impl->hook_data);
|
||||
|
||||
if (SPA_UNLIKELY ((nfds = epoll_wait (impl->epoll_fd, ep, SPA_N_ELEMENTS (ep), timeout)) < 0))
|
||||
save_errno = errno;
|
||||
|
||||
if (SPA_UNLIKELY (impl->post_func))
|
||||
impl->post_func (ctrl, impl->hook_data);
|
||||
|
||||
if (SPA_UNLIKELY (nfds < 0)) {
|
||||
errno = save_errno;
|
||||
return SPA_RESULT_ERRNO;
|
||||
}
|
||||
|
||||
for (i = 0; i < nfds; i++) {
|
||||
SpaSource *source = ep[i].data.ptr;
|
||||
|
||||
source->rmask = 0;
|
||||
if (ep[i].events & EPOLLIN)
|
||||
source->rmask |= SPA_IO_IN;
|
||||
if (ep[i].events & EPOLLOUT)
|
||||
source->rmask |= SPA_IO_OUT;
|
||||
if (ep[i].events & EPOLLHUP)
|
||||
source->rmask |= SPA_IO_HUP;
|
||||
if (ep[i].events & EPOLLERR)
|
||||
source->rmask |= SPA_IO_ERR;
|
||||
|
||||
source->func (source);
|
||||
}
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
source_io_func (SpaSource *source)
|
||||
{
|
||||
SpaSourceImpl *s = SPA_CONTAINER_OF (source, SpaSourceImpl, source);
|
||||
s->func.io (source, source->fd, source->rmask, source->data);
|
||||
}
|
||||
|
||||
static SpaSource *
|
||||
loop_add_io (SpaLoopUtils *utils,
|
||||
int fd,
|
||||
SpaIO mask,
|
||||
bool close,
|
||||
SpaSourceIOFunc func,
|
||||
void *data)
|
||||
{
|
||||
PinosLoopImpl *impl = SPA_CONTAINER_OF (utils, PinosLoopImpl, utils);
|
||||
SpaSourceImpl *source;
|
||||
|
||||
source = calloc (1, sizeof (SpaSourceImpl));
|
||||
|
||||
source->source.loop = &impl->loop;
|
||||
source->source.func = source_io_func;
|
||||
source->source.data = data;
|
||||
source->source.fd = fd;
|
||||
source->source.mask = mask;
|
||||
source->close = close;
|
||||
source->func.io = func;
|
||||
|
||||
spa_loop_add_source (&impl->loop, &source->source);
|
||||
|
||||
spa_list_insert (&impl->source_list, &source->link);
|
||||
|
||||
return &source->source;
|
||||
}
|
||||
|
||||
static SpaResult
|
||||
loop_update_io (SpaSource *source,
|
||||
SpaIO mask)
|
||||
{
|
||||
source->mask = mask;
|
||||
return spa_loop_update_source (source->loop, source);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
source_idle_func (SpaSource *source)
|
||||
{
|
||||
SpaSourceImpl *s = SPA_CONTAINER_OF (source, SpaSourceImpl, source);
|
||||
s->func.idle (source, source->data);
|
||||
}
|
||||
|
||||
static SpaSource *
|
||||
loop_add_idle (SpaLoopUtils *utils,
|
||||
SpaSourceIdleFunc func,
|
||||
void *data)
|
||||
{
|
||||
PinosLoopImpl *impl = SPA_CONTAINER_OF (utils, PinosLoopImpl, utils);
|
||||
SpaSourceImpl *source;
|
||||
|
||||
source = calloc (1, sizeof (SpaSourceImpl));
|
||||
|
||||
source->source.loop = &impl->loop;
|
||||
source->source.func = source_idle_func;
|
||||
source->source.data = data;
|
||||
source->source.fd = eventfd (0, EFD_CLOEXEC | EFD_NONBLOCK);
|
||||
source->close = true;
|
||||
source->source.mask = SPA_IO_IN;
|
||||
source->func.idle = func;
|
||||
|
||||
spa_loop_add_source (&impl->loop, &source->source);
|
||||
|
||||
spa_list_insert (&impl->source_list, &source->link);
|
||||
|
||||
spa_loop_utils_enable_idle (&impl->utils, &source->source, true);
|
||||
|
||||
return &source->source;
|
||||
}
|
||||
|
||||
static void
|
||||
loop_enable_idle (SpaSource *source,
|
||||
bool enabled)
|
||||
{
|
||||
uint64_t count;
|
||||
|
||||
if (enabled) {
|
||||
count = 1;
|
||||
if (write (source->fd, &count, sizeof (uint64_t)) != sizeof (uint64_t))
|
||||
pinos_log_warn ("loop %p: failed to write idle fd: %s", source, strerror (errno));
|
||||
} else {
|
||||
if (read (source->fd, &count, sizeof (uint64_t)) != sizeof (uint64_t))
|
||||
pinos_log_warn ("loop %p: failed to read idle fd: %s", source, strerror (errno));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
source_event_func (SpaSource *source)
|
||||
{
|
||||
SpaSourceImpl *s = SPA_CONTAINER_OF (source, SpaSourceImpl, source);
|
||||
uint64_t count;
|
||||
|
||||
if (read (source->fd, &count, sizeof (uint64_t)) != sizeof (uint64_t))
|
||||
pinos_log_warn ("loop %p: failed to read event fd: %s", source, strerror (errno));
|
||||
|
||||
s->func.event (source, source->data);
|
||||
}
|
||||
|
||||
static SpaSource *
|
||||
loop_add_event (SpaLoopUtils *utils,
|
||||
SpaSourceEventFunc func,
|
||||
void *data)
|
||||
{
|
||||
PinosLoopImpl *impl = SPA_CONTAINER_OF (utils, PinosLoopImpl, utils);
|
||||
SpaSourceImpl *source;
|
||||
|
||||
source = calloc (1, sizeof (SpaSourceImpl));
|
||||
|
||||
source->source.loop = &impl->loop;
|
||||
source->source.func = source_event_func;
|
||||
source->source.data = data;
|
||||
source->source.fd = eventfd (0, EFD_CLOEXEC | EFD_NONBLOCK);
|
||||
source->source.mask = SPA_IO_IN;
|
||||
source->close = true;
|
||||
source->func.event = func;
|
||||
|
||||
spa_loop_add_source (&impl->loop, &source->source);
|
||||
|
||||
spa_list_insert (&impl->source_list, &source->link);
|
||||
|
||||
return &source->source;
|
||||
}
|
||||
|
||||
static void
|
||||
loop_signal_event (SpaSource *source)
|
||||
{
|
||||
uint64_t count = 1;
|
||||
|
||||
if (write (source->fd, &count, sizeof(uint64_t)) != sizeof(uint64_t))
|
||||
pinos_log_warn ("loop %p: failed to write event fd: %s", source, strerror (errno));
|
||||
}
|
||||
|
||||
static void
|
||||
source_timer_func (SpaSource *source)
|
||||
{
|
||||
SpaSourceImpl *s = SPA_CONTAINER_OF (source, SpaSourceImpl, source);
|
||||
uint64_t expires;
|
||||
|
||||
if (read (source->fd, &expires, sizeof (uint64_t)) != sizeof (uint64_t))
|
||||
pinos_log_warn ("loop %p: failed to read timer fd: %s", source, strerror (errno));
|
||||
|
||||
s->func.timer (source, source->data);
|
||||
}
|
||||
|
||||
static SpaSource *
|
||||
loop_add_timer (SpaLoopUtils *utils,
|
||||
SpaSourceTimerFunc func,
|
||||
void *data)
|
||||
{
|
||||
PinosLoopImpl *impl = SPA_CONTAINER_OF (utils, PinosLoopImpl, utils);
|
||||
SpaSourceImpl *source;
|
||||
|
||||
source = calloc (1, sizeof (SpaSourceImpl));
|
||||
|
||||
source->source.loop = &impl->loop;
|
||||
source->source.func = source_timer_func;
|
||||
source->source.data = data;
|
||||
source->source.fd = timerfd_create (CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK);
|
||||
source->source.mask = SPA_IO_IN;
|
||||
source->close = true;
|
||||
source->func.timer = func;
|
||||
|
||||
spa_loop_add_source (&impl->loop, &source->source);
|
||||
|
||||
spa_list_insert (&impl->source_list, &source->link);
|
||||
|
||||
return &source->source;
|
||||
}
|
||||
|
||||
static SpaResult
|
||||
loop_update_timer (SpaSource *source,
|
||||
struct timespec *value,
|
||||
struct timespec *interval,
|
||||
bool absolute)
|
||||
{
|
||||
struct itimerspec its;
|
||||
int flags = 0;
|
||||
|
||||
spa_zero (its);
|
||||
if (value)
|
||||
its.it_value = *value;
|
||||
if (interval)
|
||||
its.it_interval = *interval;
|
||||
if (absolute)
|
||||
flags |= TFD_TIMER_ABSTIME;
|
||||
|
||||
if (timerfd_settime (source->fd, flags, &its, NULL) < 0)
|
||||
return SPA_RESULT_ERRNO;
|
||||
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
source_signal_func (SpaSource *source)
|
||||
{
|
||||
SpaSourceImpl *s = SPA_CONTAINER_OF (source, SpaSourceImpl, source);
|
||||
struct signalfd_siginfo signal_info;
|
||||
|
||||
if (read (source->fd, &signal_info, sizeof (signal_info)) != sizeof (signal_info))
|
||||
pinos_log_warn ("loop %p: failed to read signal fd: %s", source, strerror (errno));
|
||||
|
||||
s->func.signal (source, s->signal_number, source->data);
|
||||
}
|
||||
|
||||
static SpaSource *
|
||||
loop_add_signal (SpaLoopUtils *utils,
|
||||
int signal_number,
|
||||
SpaSourceSignalFunc func,
|
||||
void *data)
|
||||
{
|
||||
PinosLoopImpl *impl = SPA_CONTAINER_OF (utils, PinosLoopImpl, utils);
|
||||
SpaSourceImpl *source;
|
||||
#if 0
|
||||
sigset_t mask;
|
||||
#endif
|
||||
|
||||
source = calloc (1, sizeof (SpaSourceImpl));
|
||||
|
||||
source->source.loop = &impl->loop;
|
||||
source->source.func = source_signal_func;
|
||||
source->source.data = data;
|
||||
#if 0
|
||||
sigemptyset (&mask);
|
||||
sigaddset (&mask, signal_number);
|
||||
source->source.fd = signalfd (-1, &mask, SFD_CLOEXEC | SFD_NONBLOCK);
|
||||
sigprocmask (SIG_BLOCK, &mask, NULL);
|
||||
#endif
|
||||
source->source.mask = SPA_IO_IN;
|
||||
source->close = true;
|
||||
source->func.signal = func;
|
||||
source->signal_number = signal_number;
|
||||
|
||||
spa_loop_add_source (&impl->loop, &source->source);
|
||||
|
||||
spa_list_insert (&impl->source_list, &source->link);
|
||||
|
||||
return &source->source;
|
||||
}
|
||||
|
||||
static void
|
||||
loop_destroy_source (SpaSource *source)
|
||||
{
|
||||
SpaSourceImpl *s = SPA_CONTAINER_OF (source, SpaSourceImpl, source);
|
||||
|
||||
spa_list_remove (&s->link);
|
||||
|
||||
spa_loop_remove_source (source->loop, source);
|
||||
|
||||
if (source->fd != -1 && s->close)
|
||||
close (source->fd);
|
||||
free (s);
|
||||
}
|
||||
|
||||
PinosLoop *
|
||||
pinos_loop_new (void)
|
||||
{
|
||||
|
|
@ -239,11 +576,32 @@ pinos_loop_new (void)
|
|||
impl->loop.invoke = loop_invoke;
|
||||
this->loop = &impl->loop;
|
||||
|
||||
impl->control.size = sizeof (SpaLoopControl);
|
||||
impl->control.get_fd = loop_get_fd;
|
||||
impl->control.set_hooks = loop_set_hooks;
|
||||
impl->control.enter = loop_enter;
|
||||
impl->control.leave = loop_leave;
|
||||
impl->control.iterate = loop_iterate;
|
||||
this->control = &impl->control;
|
||||
|
||||
impl->utils.size = sizeof (SpaLoopUtils);
|
||||
impl->utils.add_io = loop_add_io;
|
||||
impl->utils.update_io = loop_update_io;
|
||||
impl->utils.add_idle = loop_add_idle;
|
||||
impl->utils.enable_idle = loop_enable_idle;
|
||||
impl->utils.add_event = loop_add_event;
|
||||
impl->utils.signal_event = loop_signal_event;
|
||||
impl->utils.add_timer = loop_add_timer;
|
||||
impl->utils.update_timer = loop_update_timer;
|
||||
impl->utils.add_signal = loop_add_signal;
|
||||
impl->utils.destroy_source = loop_destroy_source;
|
||||
this->utils = &impl->utils;
|
||||
|
||||
spa_ringbuffer_init (&impl->buffer, DATAS_SIZE);
|
||||
|
||||
impl->event = pinos_loop_add_event (this,
|
||||
event_func,
|
||||
impl);
|
||||
impl->event = loop_add_event (&impl->utils,
|
||||
event_func,
|
||||
impl);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
@ -251,347 +609,13 @@ void
|
|||
pinos_loop_destroy (PinosLoop *loop)
|
||||
{
|
||||
PinosLoopImpl *impl = SPA_CONTAINER_OF (loop, PinosLoopImpl, this);
|
||||
PinosSource *source, *tmp;
|
||||
SpaSourceImpl *source, *tmp;
|
||||
|
||||
pinos_signal_emit (&loop->destroy_signal, loop);
|
||||
|
||||
spa_list_for_each_safe (source, tmp, &impl->source_list, link)
|
||||
pinos_source_destroy (source);
|
||||
loop_destroy_source (&source->source);
|
||||
|
||||
close (impl->epoll_fd);
|
||||
free (impl);
|
||||
}
|
||||
|
||||
int
|
||||
pinos_loop_get_fd (PinosLoop *loop)
|
||||
{
|
||||
PinosLoopImpl *impl = SPA_CONTAINER_OF (loop, PinosLoopImpl, this);
|
||||
|
||||
return impl->epoll_fd;
|
||||
}
|
||||
|
||||
void
|
||||
pinos_loop_set_hooks (PinosLoop *loop,
|
||||
PinosLoopHook pre_func,
|
||||
PinosLoopHook post_func,
|
||||
void *data)
|
||||
{
|
||||
PinosLoopImpl *impl = SPA_CONTAINER_OF (loop, PinosLoopImpl, this);
|
||||
|
||||
impl->pre_func = pre_func;
|
||||
impl->post_func = post_func;
|
||||
impl->hook_data = data;
|
||||
}
|
||||
|
||||
void
|
||||
pinos_loop_enter_thread (PinosLoop *loop)
|
||||
{
|
||||
PinosLoopImpl *impl = SPA_CONTAINER_OF (loop, PinosLoopImpl, this);
|
||||
impl->thread = pthread_self();
|
||||
}
|
||||
|
||||
void
|
||||
pinos_loop_leave_thread (PinosLoop *loop)
|
||||
{
|
||||
PinosLoopImpl *impl = SPA_CONTAINER_OF (loop, PinosLoopImpl, this);
|
||||
impl->thread = 0;
|
||||
}
|
||||
|
||||
SpaResult
|
||||
pinos_loop_iterate (PinosLoop *loop,
|
||||
int timeout)
|
||||
{
|
||||
PinosLoopImpl *impl = SPA_CONTAINER_OF (loop, PinosLoopImpl, this);
|
||||
struct epoll_event ep[32];
|
||||
int i, nfds, save_errno;
|
||||
|
||||
if (SPA_UNLIKELY (impl->pre_func))
|
||||
impl->pre_func (loop, impl->hook_data);
|
||||
|
||||
if (SPA_UNLIKELY ((nfds = epoll_wait(impl->epoll_fd, ep, SPA_N_ELEMENTS (ep), timeout)) < 0))
|
||||
save_errno = errno;
|
||||
|
||||
if (SPA_UNLIKELY (impl->post_func))
|
||||
impl->post_func (loop, impl->hook_data);
|
||||
|
||||
if (SPA_UNLIKELY (nfds < 0)) {
|
||||
errno = save_errno;
|
||||
return SPA_RESULT_ERRNO;
|
||||
}
|
||||
|
||||
for (i = 0; i < nfds; i++) {
|
||||
SpaSource *source = ep[i].data.ptr;
|
||||
|
||||
source->rmask = 0;
|
||||
if (ep[i].events & EPOLLIN)
|
||||
source->rmask |= SPA_IO_IN;
|
||||
if (ep[i].events & EPOLLOUT)
|
||||
source->rmask |= SPA_IO_OUT;
|
||||
if (ep[i].events & EPOLLHUP)
|
||||
source->rmask |= SPA_IO_HUP;
|
||||
if (ep[i].events & EPOLLERR)
|
||||
source->rmask |= SPA_IO_ERR;
|
||||
|
||||
source->func (source);
|
||||
}
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
source_io_func (SpaSource *source)
|
||||
{
|
||||
PinosSource *s = SPA_CONTAINER_OF (source, PinosSource, source);
|
||||
s->func.io (s, s->source.fd, s->source.rmask, s->source.data);
|
||||
}
|
||||
|
||||
PinosSource *
|
||||
pinos_loop_add_io (PinosLoop *loop,
|
||||
int fd,
|
||||
SpaIO mask,
|
||||
bool close,
|
||||
PinosSourceIOFunc func,
|
||||
void *data)
|
||||
{
|
||||
PinosLoopImpl *impl = SPA_CONTAINER_OF (loop, PinosLoopImpl, this);
|
||||
PinosSource *source;
|
||||
|
||||
source = calloc (1, sizeof (PinosSource));
|
||||
|
||||
source->source.loop = loop->loop;
|
||||
source->source.func = source_io_func;
|
||||
source->source.data = data;
|
||||
source->source.fd = fd;
|
||||
source->source.mask = mask;
|
||||
source->close = close;
|
||||
source->func.io = func;
|
||||
|
||||
spa_loop_add_source (loop->loop, &source->source);
|
||||
|
||||
spa_list_insert (&impl->source_list, &source->link);
|
||||
|
||||
return source;
|
||||
}
|
||||
|
||||
SpaResult
|
||||
pinos_source_io_update (PinosSource *source,
|
||||
SpaIO mask)
|
||||
{
|
||||
source->source.mask = mask;
|
||||
return spa_loop_update_source (source->source.loop, &source->source);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
source_idle_func (SpaSource *source)
|
||||
{
|
||||
PinosSource *s = SPA_CONTAINER_OF (source, PinosSource, source);
|
||||
s->func.idle (s, s->source.data);
|
||||
}
|
||||
|
||||
PinosSource *
|
||||
pinos_loop_add_idle (PinosLoop *loop,
|
||||
PinosSourceIdleFunc func,
|
||||
void *data)
|
||||
{
|
||||
PinosLoopImpl *impl = SPA_CONTAINER_OF (loop, PinosLoopImpl, this);
|
||||
PinosSource *source;
|
||||
|
||||
source = calloc (1, sizeof (PinosSource));
|
||||
|
||||
source->source.loop = loop->loop;
|
||||
source->source.func = source_idle_func;
|
||||
source->source.data = data;
|
||||
source->source.fd = eventfd (0, EFD_CLOEXEC | EFD_NONBLOCK);
|
||||
source->close = true;
|
||||
source->source.mask = SPA_IO_IN;
|
||||
source->func.idle = func;
|
||||
|
||||
spa_loop_add_source (loop->loop, &source->source);
|
||||
|
||||
spa_list_insert (&impl->source_list, &source->link);
|
||||
|
||||
pinos_source_idle_enable (source, true);
|
||||
|
||||
return source;
|
||||
}
|
||||
|
||||
void
|
||||
pinos_source_idle_enable (PinosSource *source,
|
||||
bool enabled)
|
||||
{
|
||||
uint64_t count;
|
||||
|
||||
if (enabled) {
|
||||
count = 1;
|
||||
if (write (source->source.fd, &count, sizeof (uint64_t)) != sizeof (uint64_t))
|
||||
pinos_log_warn ("loop %p: failed to write idle fd: %s", source, strerror (errno));
|
||||
} else {
|
||||
if (read (source->source.fd, &count, sizeof (uint64_t)) != sizeof (uint64_t))
|
||||
pinos_log_warn ("loop %p: failed to read idle fd: %s", source, strerror (errno));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
source_event_func (SpaSource *source)
|
||||
{
|
||||
PinosSource *s = SPA_CONTAINER_OF (source, PinosSource, source);
|
||||
uint64_t count;
|
||||
|
||||
if (read (source->fd, &count, sizeof (uint64_t)) != sizeof (uint64_t))
|
||||
pinos_log_warn ("loop %p: failed to read event fd: %s", source, strerror (errno));
|
||||
|
||||
s->func.event (s, s->source.data);
|
||||
}
|
||||
|
||||
PinosSource *
|
||||
pinos_loop_add_event (PinosLoop *loop,
|
||||
PinosSourceEventFunc func,
|
||||
void *data)
|
||||
{
|
||||
PinosLoopImpl *impl = SPA_CONTAINER_OF (loop, PinosLoopImpl, this);
|
||||
PinosSource *source;
|
||||
|
||||
source = calloc (1, sizeof (PinosSource));
|
||||
|
||||
source->source.loop = loop->loop;
|
||||
source->source.func = source_event_func;
|
||||
source->source.data = data;
|
||||
source->source.fd = eventfd (0, EFD_CLOEXEC | EFD_NONBLOCK);
|
||||
source->source.mask = SPA_IO_IN;
|
||||
source->close = true;
|
||||
source->func.event = func;
|
||||
|
||||
spa_loop_add_source (loop->loop, &source->source);
|
||||
|
||||
spa_list_insert (&impl->source_list, &source->link);
|
||||
|
||||
return source;
|
||||
}
|
||||
|
||||
void
|
||||
pinos_source_event_signal (PinosSource *source)
|
||||
{
|
||||
uint64_t count = 1;
|
||||
|
||||
if (write (source->source.fd, &count, sizeof(uint64_t)) != sizeof(uint64_t))
|
||||
pinos_log_warn ("loop %p: failed to write event fd: %s", source, strerror (errno));
|
||||
}
|
||||
|
||||
static void
|
||||
source_timer_func (SpaSource *source)
|
||||
{
|
||||
PinosSource *s = SPA_CONTAINER_OF (source, PinosSource, source);
|
||||
uint64_t expires;
|
||||
|
||||
if (read (source->fd, &expires, sizeof (uint64_t)) != sizeof (uint64_t))
|
||||
pinos_log_warn ("loop %p: failed to read timer fd: %s", source, strerror (errno));
|
||||
|
||||
s->func.timer (s, s->source.data);
|
||||
}
|
||||
|
||||
PinosSource *
|
||||
pinos_loop_add_timer (PinosLoop *loop,
|
||||
PinosSourceTimerFunc func,
|
||||
void *data)
|
||||
{
|
||||
PinosLoopImpl *impl = SPA_CONTAINER_OF (loop, PinosLoopImpl, this);
|
||||
PinosSource *source;
|
||||
|
||||
source = calloc (1, sizeof (PinosSource));
|
||||
|
||||
source->source.loop = loop->loop;
|
||||
source->source.func = source_timer_func;
|
||||
source->source.data = data;
|
||||
source->source.fd = timerfd_create (CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK);
|
||||
source->source.mask = SPA_IO_IN;
|
||||
source->close = true;
|
||||
source->func.timer = func;
|
||||
|
||||
spa_loop_add_source (loop->loop, &source->source);
|
||||
|
||||
spa_list_insert (&impl->source_list, &source->link);
|
||||
|
||||
return source;
|
||||
}
|
||||
|
||||
SpaResult
|
||||
pinos_source_timer_update (PinosSource *source,
|
||||
struct timespec *value,
|
||||
struct timespec *interval,
|
||||
bool absolute)
|
||||
{
|
||||
struct itimerspec its;
|
||||
int flags = 0;
|
||||
|
||||
spa_zero (its);
|
||||
if (value)
|
||||
its.it_value = *value;
|
||||
if (interval)
|
||||
its.it_interval = *interval;
|
||||
if (absolute)
|
||||
flags |= TFD_TIMER_ABSTIME;
|
||||
|
||||
if (timerfd_settime (source->source.fd, flags, &its, NULL) < 0)
|
||||
return SPA_RESULT_ERRNO;
|
||||
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
source_signal_func (SpaSource *source)
|
||||
{
|
||||
PinosSource *s = SPA_CONTAINER_OF (source, PinosSource, source);
|
||||
struct signalfd_siginfo signal_info;
|
||||
|
||||
if (read (source->fd, &signal_info, sizeof (signal_info)) != sizeof (signal_info))
|
||||
pinos_log_warn ("loop %p: failed to read signal fd: %s", source, strerror (errno));
|
||||
|
||||
s->func.signal (s, s->signal_number, s->source.data);
|
||||
}
|
||||
|
||||
PinosSource *
|
||||
pinos_loop_add_signal (PinosLoop *loop,
|
||||
int signal_number,
|
||||
PinosSourceSignalFunc func,
|
||||
void *data)
|
||||
{
|
||||
PinosLoopImpl *impl = SPA_CONTAINER_OF (loop, PinosLoopImpl, this);
|
||||
PinosSource *source;
|
||||
#if 0
|
||||
sigset_t mask;
|
||||
#endif
|
||||
|
||||
source = calloc (1, sizeof (PinosSource));
|
||||
|
||||
source->source.loop = loop->loop;
|
||||
source->source.func = source_signal_func;
|
||||
source->source.data = data;
|
||||
#if 0
|
||||
sigemptyset (&mask);
|
||||
sigaddset (&mask, signal_number);
|
||||
source->source.fd = signalfd (-1, &mask, SFD_CLOEXEC | SFD_NONBLOCK);
|
||||
sigprocmask (SIG_BLOCK, &mask, NULL);
|
||||
#endif
|
||||
source->source.mask = SPA_IO_IN;
|
||||
source->close = true;
|
||||
source->func.signal = func;
|
||||
source->signal_number = signal_number;
|
||||
|
||||
spa_loop_add_source (loop->loop, &source->source);
|
||||
|
||||
spa_list_insert (&impl->source_list, &source->link);
|
||||
|
||||
return source;
|
||||
}
|
||||
|
||||
void
|
||||
pinos_source_destroy (PinosSource *source)
|
||||
{
|
||||
spa_list_remove (&source->link);
|
||||
|
||||
spa_loop_remove_source (source->source.loop, &source->source);
|
||||
|
||||
if (source->source.fd != -1 && source->close)
|
||||
close (source->source.fd);
|
||||
free (source);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue