174 lines
3.9 KiB
C
174 lines
3.9 KiB
C
/****************************************************************************
|
|
* This file is part of the project AqHome.
|
|
* AqHome (c) by 2025 Martin Preuss, all rights reserved.
|
|
*
|
|
* The license for this file can be found in the file COPYING which you
|
|
* should have received along with this file.
|
|
****************************************************************************/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
# include <config.h>
|
|
#endif
|
|
|
|
#include "./eventloop_p.h"
|
|
#include "./fdobject.h"
|
|
|
|
#include <gwenhywfar/debug.h>
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <sys/select.h>
|
|
#include <errno.h>
|
|
#include <string.h>
|
|
|
|
|
|
|
|
/* ------------------------------------------------------------------------------------------------
|
|
* forward declarations
|
|
* ------------------------------------------------------------------------------------------------
|
|
*/
|
|
|
|
static int _sampleFdsIntoSet(AQH_OBJECT_LIST2 *ol, fd_set *fds, int mode);
|
|
static void _markReadyFdObjects(AQH_OBJECT_LIST2 *ol, fd_set *fds, int mode);
|
|
static void _signalReadyFdObjects(AQH_OBJECT_LIST2 *ol);
|
|
|
|
|
|
|
|
/* ------------------------------------------------------------------------------------------------
|
|
* code
|
|
* ------------------------------------------------------------------------------------------------
|
|
*/
|
|
|
|
void AQH_EventLoop_Run(AQH_EVENT_LOOP *eventLoop)
|
|
{
|
|
fd_set fdRead;
|
|
fd_set fdWrite;
|
|
int highestFd=-1;
|
|
int rv;
|
|
|
|
FD_ZERO(&fdRead);
|
|
FD_ZERO(&fdWrite);
|
|
|
|
highestFd=_sampleFdsIntoSet(eventLoop->fdObjectList, &fdRead, AQH_FDOBJECT_FDMODE_READ);
|
|
rv=_sampleFdsIntoSet(eventLoop->fdObjectList, &fdWrite, AQH_FDOBJECT_FDMODE_WRITE);
|
|
highestFd=(rv>highestFd)?rv:highestFd;
|
|
|
|
if (highestFd>-1) {
|
|
struct timeval tv;
|
|
|
|
tv.tv_sec=0;
|
|
tv.tv_usec=200000;
|
|
rv=select(highestFd+1, &fdRead, &fdWrite, NULL, &tv);
|
|
if (rv>0) {
|
|
/* some fds became active */
|
|
_markReadyFdObjects(eventLoop->fdObjectList, &fdRead, AQH_FDOBJECT_FDMODE_READ);
|
|
_markReadyFdObjects(eventLoop->fdObjectList, &fdWrite, AQH_FDOBJECT_FDMODE_WRITE);
|
|
_signalReadyFdObjects(eventLoop->fdObjectList);
|
|
}
|
|
else if (rv<0) {
|
|
if (errno!=EINTR) {
|
|
/* error */
|
|
DBG_ERROR(AQH_LOGDOMAIN, "Error on SELECT: %d (%s)", errno, strerror(errno));
|
|
}
|
|
}
|
|
else {
|
|
/* no fd became active (TODO: maybe signal deep idle objects?) */
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
int _sampleFdsIntoSet(AQH_OBJECT_LIST2 *ol, fd_set *fds, int mode)
|
|
{
|
|
AQH_OBJECT_LIST2_ITERATOR *it;
|
|
int highestFd=-1;
|
|
|
|
it=AQH_Object_List2_First(ol);
|
|
if (it) {
|
|
AQH_OBJECT *o;
|
|
|
|
o=AQH_Object_List2Iterator_Data(it);
|
|
while(o) {
|
|
int m;
|
|
|
|
m=AQH_FdObject_GetFdMode(o);
|
|
if (m==mode) {
|
|
int fd;
|
|
|
|
fd=AQH_FdObject_GetFd(o);
|
|
if (fd>-1) {
|
|
highestFd=(fd>highestFd)?fd:highestFd;
|
|
FD_SET(fd, fds);
|
|
}
|
|
}
|
|
o=AQH_Object_List2Iterator_Next(it);
|
|
}
|
|
AQH_Object_List2Iterator_free(it);
|
|
}
|
|
|
|
return highestFd;
|
|
}
|
|
|
|
|
|
|
|
void _markReadyFdObjects(AQH_OBJECT_LIST2 *ol, fd_set *fds, int mode)
|
|
{
|
|
AQH_OBJECT_LIST2_ITERATOR *it;
|
|
|
|
it=AQH_Object_List2_First(ol);
|
|
if (it) {
|
|
AQH_OBJECT *o;
|
|
|
|
o=AQH_Object_List2Iterator_Data(it);
|
|
while(o) {
|
|
int m;
|
|
|
|
m=AQH_FdObject_GetFdMode(o);
|
|
if (m==mode) {
|
|
int fd;
|
|
|
|
fd=AQH_FdObject_GetFd(o);
|
|
if (FD_ISSET(fd, fds))
|
|
AQH_Object_AddFlags(o, AQH_OBJECT_FLAGS_FIRE);
|
|
}
|
|
o=AQH_Object_List2Iterator_Next(it);
|
|
}
|
|
|
|
AQH_Object_List2Iterator_free(it);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void _signalReadyFdObjects(AQH_OBJECT_LIST2 *ol)
|
|
{
|
|
AQH_OBJECT_LIST2_ITERATOR *it;
|
|
|
|
it=AQH_Object_List2_First(ol);
|
|
if (it) {
|
|
AQH_OBJECT *o;
|
|
|
|
o=AQH_Object_List2Iterator_Data(it);
|
|
while(o) {
|
|
if (AQH_Object_GetFlags(o) & AQH_OBJECT_FLAGS_FIRE) {
|
|
AQH_Object_SubFlags(o, AQH_OBJECT_FLAGS_FIRE);
|
|
AQH_Object_EmitSignal(o, AQH_FDOBJECT_SIGNAL_ISREADY, 0, NULL);
|
|
}
|
|
o=AQH_Object_List2Iterator_Next(it);
|
|
}
|
|
|
|
AQH_Object_List2Iterator_free(it);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|