From 28b130ecd4bc69c55395db0ba487696a68e26a91 Mon Sep 17 00:00:00 2001 From: Martin Preuss Date: Tue, 7 Jan 2025 22:43:20 +0100 Subject: [PATCH] aqhome: started rewriting IPC module. started with basic event interface using unix fd and timers. --- aqhome/0BUILD | 2 + aqhome/events2/0BUILD | 88 ++++++++++ aqhome/events2/eventloop.c | 79 +++++++++ aqhome/events2/eventloop.h | 32 ++++ aqhome/events2/eventloop_p.h | 25 +++ aqhome/events2/eventloop_select.c | 173 +++++++++++++++++++ aqhome/events2/fdobject.c | 140 +++++++++++++++ aqhome/events2/fdobject.h | 36 ++++ aqhome/events2/fdobject_p.h | 23 +++ aqhome/events2/object.c | 276 ++++++++++++++++++++++++++++++ aqhome/events2/object.h | 121 +++++++++++++ aqhome/events2/object_p.h | 46 +++++ 12 files changed, 1041 insertions(+) create mode 100644 aqhome/events2/0BUILD create mode 100644 aqhome/events2/eventloop.c create mode 100644 aqhome/events2/eventloop.h create mode 100644 aqhome/events2/eventloop_p.h create mode 100644 aqhome/events2/eventloop_select.c create mode 100644 aqhome/events2/fdobject.c create mode 100644 aqhome/events2/fdobject.h create mode 100644 aqhome/events2/fdobject_p.h create mode 100644 aqhome/events2/object.c create mode 100644 aqhome/events2/object.h create mode 100644 aqhome/events2/object_p.h diff --git a/aqhome/0BUILD b/aqhome/0BUILD index 2516366..5208aa9 100644 --- a/aqhome/0BUILD +++ b/aqhome/0BUILD @@ -70,6 +70,7 @@ hexfile data events + events2 client @@ -82,6 +83,7 @@ aqhhexfile aqhdata aqhevents + aqhevents2 aqhclient diff --git a/aqhome/events2/0BUILD b/aqhome/events2/0BUILD new file mode 100644 index 0000000..3968dc1 --- /dev/null +++ b/aqhome/events2/0BUILD @@ -0,0 +1,88 @@ + + + + + + + + $(gwenhywfar_cflags) + $(aqdatabase_cflags) + -I$(topsrcdir) + -I$(topbuilddir) + + + + --include=$(builddir) + --include=$(srcdir) + --include=$(aqdatabase_AQDATABASE_TYPEMAKERDIR)/c + + + + + + $(visibility_cflags) + + + + --api=AQHOME_API + + + + + + + + + + + + + + + + + + $(local/built_headers_pub) + + + + + eventloop.h + object.h + fdobject.h + + + + + eventloop_p.h + object_p.h + fdobject_p.h + + + + + $(local/typefiles) + + eventloop.c + eventloop_select.c + object.c + fdobject.c + + + + + + + + + + + + + + + + + + + diff --git a/aqhome/events2/eventloop.c b/aqhome/events2/eventloop.c new file mode 100644 index 0000000..a37bc0d --- /dev/null +++ b/aqhome/events2/eventloop.c @@ -0,0 +1,79 @@ +/**************************************************************************** + * 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 +#endif + +#include "./eventloop_p.h" + +#include + + + + +AQH_EVENT_LOOP *AQH_EventLoop_new() +{ + AQH_EVENT_LOOP *eventLoop; + + GWEN_NEW_OBJECT(AQH_EVENT_LOOP, eventLoop); + eventLoop->fdObjectList=AQH_Object_List2_new(); + eventLoop->timerObjectList=AQH_Object_List2_new(); + + return eventLoop; +} + + + +void AQH_EventLoop_free(AQH_EVENT_LOOP *eventLoop) +{ + if (eventLoop) { + AQH_Object_List2_free(eventLoop->timerObjectList); + AQH_Object_List2_free(eventLoop->fdObjectList); + } +} + + + +void AQH_EventLoop_AddFdObject(AQH_EVENT_LOOP *eventLoop, AQH_OBJECT *o) +{ + if (eventLoop && o && NULL==AQH_Object_List2_Contains(eventLoop->fdObjectList, o)) { + AQH_Object_List2_PushBack(eventLoop->fdObjectList, o); + } +} + + + +void AQH_EventLoop_DelFdObject(AQH_EVENT_LOOP *eventLoop, AQH_OBJECT *o) +{ + if (eventLoop && o) + AQH_Object_List2_Remove(eventLoop->fdObjectList, o); +} + + + +void AQH_EventLoop_AddTimerObject(AQH_EVENT_LOOP *eventLoop, AQH_OBJECT *o) +{ + if (eventLoop && o && NULL==AQH_Object_List2_Contains(eventLoop->timerObjectList, o)) { + AQH_Object_List2_PushBack(eventLoop->timerObjectList, o); + } +} + + + +void AQH_EventLoop_DelTimerObject(AQH_EVENT_LOOP *eventLoop, AQH_OBJECT *o) +{ + if (eventLoop && o) + AQH_Object_List2_Remove(eventLoop->timerObjectList, o); +} + + + + + + diff --git a/aqhome/events2/eventloop.h b/aqhome/events2/eventloop.h new file mode 100644 index 0000000..9d95bcd --- /dev/null +++ b/aqhome/events2/eventloop.h @@ -0,0 +1,32 @@ +/**************************************************************************** + * 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. + ****************************************************************************/ + +#ifndef AQH_EVENTLOOP_H +#define AQH_EVENTLOOP_H + +typedef struct AQH_EVENT_LOOP AQH_EVENT_LOOP; + + +#include + + + +AQHOME_API AQH_EVENT_LOOP *AQH_EventLoop_new(); +AQHOME_API void AQH_EventLoop_free(AQH_EVENT_LOOP *eventLoop); + +AQHOME_API void AQH_EventLoop_Run(AQH_EVENT_LOOP *eventLoop); + +AQHOME_API void AQH_EventLoop_AddFdObject(AQH_EVENT_LOOP *eventLoop, AQH_OBJECT *o); +AQHOME_API void AQH_EventLoop_DelFdObject(AQH_EVENT_LOOP *eventLoop, AQH_OBJECT *o); + +AQHOME_API void AQH_EventLoop_AddTimerObject(AQH_EVENT_LOOP *eventLoop, AQH_OBJECT *o); +AQHOME_API void AQH_EventLoop_DelTimerObject(AQH_EVENT_LOOP *eventLoop, AQH_OBJECT *o); + + + +#endif diff --git a/aqhome/events2/eventloop_p.h b/aqhome/events2/eventloop_p.h new file mode 100644 index 0000000..e813766 --- /dev/null +++ b/aqhome/events2/eventloop_p.h @@ -0,0 +1,25 @@ +/**************************************************************************** + * 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. + ****************************************************************************/ + +#ifndef AQH_EVENTLOOP_P_H +#define AQH_EVENTLOOP_P_H + +#include "./eventloop.h" + + + +struct AQH_EVENT_LOOP +{ + AQH_OBJECT_LIST2 *fdObjectList; + AQH_OBJECT_LIST2 *timerObjectList; +}; + + + + +#endif diff --git a/aqhome/events2/eventloop_select.c b/aqhome/events2/eventloop_select.c new file mode 100644 index 0000000..fa4381f --- /dev/null +++ b/aqhome/events2/eventloop_select.c @@ -0,0 +1,173 @@ +/**************************************************************************** + * 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 +#endif + +#include "./eventloop_p.h" +#include "./fdobject.h" + +#include + +#include +#include +#include +#include +#include + + + +/* ------------------------------------------------------------------------------------------------ + * 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); + } +} + + + + + + + + + + diff --git a/aqhome/events2/fdobject.c b/aqhome/events2/fdobject.c new file mode 100644 index 0000000..6d1cc56 --- /dev/null +++ b/aqhome/events2/fdobject.c @@ -0,0 +1,140 @@ +/**************************************************************************** + * This file is part of the project Gwenhywfar. + * Gwenhywfar (c) by 2023 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 +#endif + +#include "./fdobject_p.h" + +#include + + + +GWEN_INHERIT(AQH_OBJECT, AQH_FDOBJECT) + + + +/* ------------------------------------------------------------------------------------------------ + * forward declarations + * ------------------------------------------------------------------------------------------------ + */ + +static void GWENHYWFAR_CB _freeData(void *bp, void *p); +static void _cbEnable(AQH_OBJECT *o); +static void _cbDisable(AQH_OBJECT *o); + + + + +/* ------------------------------------------------------------------------------------------------ + * implementations + * ------------------------------------------------------------------------------------------------ + */ + +AQH_OBJECT *AQH_FdObject_new(AQH_EVENT_LOOP *eventLoop, int fd, int mode) +{ + AQH_OBJECT *o; + AQH_FDOBJECT *xo; + + o=AQH_Object_new(eventLoop); + GWEN_NEW_OBJECT(AQH_FDOBJECT, xo); + GWEN_INHERIT_SETDATA(AQH_OBJECT, AQH_FDOBJECT, o, xo, _freeData); + xo->fd=fd; + xo->fdMode=mode; + + AQH_Object_SetEnableFn(o, _cbEnable); + AQH_Object_SetDisableFn(o, _cbDisable); + + return o; +} + + + +void GWENHYWFAR_CB _freeData(GWEN_UNUSED void *bp, void *p) +{ + AQH_FDOBJECT *xo; + + xo=(AQH_FDOBJECT*)p; + GWEN_FREE_OBJECT(xo); +} + + + +int AQH_FdObject_GetFdMode(const AQH_OBJECT *o) +{ + if (o) { + AQH_FDOBJECT *xo; + + xo=GWEN_INHERIT_GETDATA(AQH_OBJECT, AQH_FDOBJECT, o); + if (xo) + return xo->fdMode; + } + + return 0; +} + + + +void AQH_FdObject_SetFdMode(AQH_OBJECT *o, int i) +{ + if (o) { + AQH_FDOBJECT *xo; + + xo=GWEN_INHERIT_GETDATA(AQH_OBJECT, AQH_FDOBJECT, o); + if (xo) + xo->fdMode=i; + } +} + + + +int AQH_FdObject_GetFd(const AQH_OBJECT *o) +{ + if (o) { + AQH_FDOBJECT *xo; + + xo=GWEN_INHERIT_GETDATA(AQH_OBJECT, AQH_FDOBJECT, o); + if (xo) + return xo->fd; + } + + return -1; +} + + + +void _cbEnable(AQH_OBJECT *o) +{ + if (o) { + AQH_EVENT_LOOP *eventLoop; + + eventLoop=AQH_Object_GetEventLoop(o); + if (eventLoop) + AQH_EventLoop_AddFdObject(eventLoop, o); + } +} + + + +void _cbDisable(AQH_OBJECT *o) +{ + if (o) { + AQH_EVENT_LOOP *eventLoop; + + eventLoop=AQH_Object_GetEventLoop(o); + if (eventLoop) + AQH_EventLoop_DelFdObject(eventLoop, o); + } +} + + + + + + diff --git a/aqhome/events2/fdobject.h b/aqhome/events2/fdobject.h new file mode 100644 index 0000000..09a8678 --- /dev/null +++ b/aqhome/events2/fdobject.h @@ -0,0 +1,36 @@ +/**************************************************************************** + * This file is part of the project Gwenhywfar. + * Gwenhywfar (c) by 2023 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. + ****************************************************************************/ + +#ifndef AQH_FDOBJECT_H +#define AQH_FDOBJECT_H + + +#include + + +enum { + AQH_FDOBJECT_FDMODE_READ=1, + AQH_FDOBJECT_FDMODE_WRITE +}; + + +enum { + AQH_FDOBJECT_SIGNAL_ISREADY=AQH_OBJECT_SIGNAL_LAST +}; + + + +AQHOME_API AQH_OBJECT *AQH_FdObject_new(AQH_EVENT_LOOP *eventLoop, int fd, int mode); + +AQHOME_API int AQH_FdObject_GetFdMode(const AQH_OBJECT *o); +AQHOME_API void AQH_FdObject_SetFdMode(AQH_OBJECT *o, int i); + +AQHOME_API int AQH_FdObject_GetFd(const AQH_OBJECT *o); + + +#endif diff --git a/aqhome/events2/fdobject_p.h b/aqhome/events2/fdobject_p.h new file mode 100644 index 0000000..c3793b3 --- /dev/null +++ b/aqhome/events2/fdobject_p.h @@ -0,0 +1,23 @@ +/**************************************************************************** + * This file is part of the project Gwenhywfar. + * Gwenhywfar (c) by 2023 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. + ****************************************************************************/ + +#ifndef AQH_FDOBJECT_P_H +#define AQH_FDOBJECT_P_H + + +#include "./fdobject.h" + + +typedef struct AQH_FDOBJECT AQH_FDOBJECT; +struct AQH_FDOBJECT { + int fdMode; + int fd; +}; + + +#endif diff --git a/aqhome/events2/object.c b/aqhome/events2/object.c new file mode 100644 index 0000000..61a3a24 --- /dev/null +++ b/aqhome/events2/object.c @@ -0,0 +1,276 @@ +/**************************************************************************** + * 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 +#endif + +#include "./object_p.h" + + + +/* ------------------------------------------------------------------------------------------------ + * forward declarations + * ------------------------------------------------------------------------------------------------ + */ + +AQH_LINK *AQH_Link_new(); +void AQH_Link_free(AQH_LINK *ln); + +AQH_LINK *_findLink(AQH_OBJECT *o, uint32_t signalId, uint32_t slotId, AQH_OBJECT *targetObject); + + + +/* ------------------------------------------------------------------------------------------------ + * list, inherit + * ------------------------------------------------------------------------------------------------ + */ + +GWEN_LIST_FUNCTIONS(AQH_LINK, AQH_Link) + +GWEN_INHERIT_FUNCTIONS(AQH_OBJECT) +GWEN_LIST_FUNCTIONS(AQH_OBJECT, AQH_Object) +GWEN_LIST2_FUNCTIONS(AQH_OBJECT, AQH_Object) + + + +/* ------------------------------------------------------------------------------------------------ + * code + * ------------------------------------------------------------------------------------------------ + */ + +AQH_OBJECT *AQH_Object_new(AQH_EVENT_LOOP *eventLoop) +{ + AQH_OBJECT *o; + + GWEN_NEW_OBJECT(AQH_OBJECT, o); + GWEN_INHERIT_INIT(AQH_OBJECT, o); + GWEN_LIST_INIT(AQH_OBJECT, o); + o->eventLoop=eventLoop; + o->linkList=AQH_Link_List_new(); + + return 0; +} + + + +void AQH_Object_free(AQH_OBJECT *o) +{ + if (o) { + GWEN_INHERIT_FINI(AQH_OBJECT, o); + GWEN_LIST_FINI(AQH_OBJECT, o); + + AQH_Link_List_free(o->linkList); + + GWEN_FREE_OBJECT(o); + } +} + + + +uint32_t AQH_Object_GetFlags(const AQH_OBJECT *o) +{ + return o?o->flags:0; +} + + + +void AQH_Object_SetFlags(AQH_OBJECT *o, uint32_t i) +{ + if (o) + o->flags=i; +} + + + +void AQH_Object_AddFlags(AQH_OBJECT *o, uint32_t i) +{ + if (o) + o->flags|=i; +} + + + +void AQH_Object_SubFlags(AQH_OBJECT *o, uint32_t i) +{ + if (o) + o->flags&=~i; +} + + + +AQH_EVENT_LOOP *AQH_Object_GetEventLoop(const AQH_OBJECT *o) +{ + return o?o->eventLoop:NULL; +} + + + +AQH_LINK *_findLink(AQH_OBJECT *o, uint32_t signalId, uint32_t slotId, AQH_OBJECT *targetObject) +{ + if (o) { + AQH_LINK *ln; + + ln=AQH_Link_List_First(o->linkList); + while(ln) { + if (ln->signalIdForSender==signalId && + ln->signalIdForTarget==slotId && + ln->targetObject==targetObject) + return ln; + ln=AQH_Link_List_Next(ln); + } + } + return NULL; +} + + + +void AQH_Object_AddLink(AQH_OBJECT *o, uint32_t signalId, uint32_t slotId, AQH_OBJECT *targetObject) +{ + AQH_LINK *ln; + + ln=_findLink(o, signalId, slotId, targetObject); + if (ln==NULL) { + ln=AQH_Link_new(); + ln->signalIdForSender=signalId; + ln->signalIdForTarget=slotId; + ln->targetObject=targetObject; + AQH_Link_List_Add(ln, o->linkList); + } +} + + + +void AQH_Object_DelLink(AQH_OBJECT *o, uint32_t signalId, uint32_t slotId, AQH_OBJECT *targetObject) +{ + AQH_LINK *ln; + + ln=_findLink(o, signalId, slotId, targetObject); + if (ln) { + AQH_Link_List_Del(ln); + AQH_Link_free(ln); + } +} + + + +int AQH_Object_EmitSignal(AQH_OBJECT *o, uint32_t signalId, int param1, void *param2) +{ + int signalWasHandled=0; + + if (o) { + AQH_LINK *ln; + + ln=AQH_Link_List_First(o->linkList); + while(ln) { + if (ln->signalIdForSender==signalId && ln->targetObject) { + if (AQH_Object_HandleSignal(ln->targetObject, ln->signalIdForTarget, o, param1, param2)) + signalWasHandled=1; + } + ln=AQH_Link_List_Next(ln); + } + } + return signalWasHandled; +} + + + +int AQH_Object_HandleSignal(AQH_OBJECT *o, uint32_t slotId, AQH_OBJECT *senderObject, int param1, void *param2) +{ + if (o && o->signalHandlerFn) + return o->signalHandlerFn(o, slotId, senderObject, param1, param2); + return 0; +} + + + +void AQH_Object_Enable(AQH_OBJECT *o) +{ + if (o && o->enableFn) + o->enableFn(o); +} + + + +void AQH_Object_Disable(AQH_OBJECT *o) +{ + if (o && o->disableFn) + o->disableFn(o); +} + + + +AQH_OBJECT_SIGNALHANDLER_FN AQH_Object_SetSignalHandlerFn(AQH_OBJECT *o, AQH_OBJECT_SIGNALHANDLER_FN f) +{ + if (o) { + AQH_OBJECT_SIGNALHANDLER_FN oldFn; + + oldFn=o->signalHandlerFn; + o->signalHandlerFn=f; + return oldFn; + } + return NULL; +} + + + +AQH_OBJECT_ENABLE_FN AQH_Object_SetEnableFn(AQH_OBJECT *o, AQH_OBJECT_ENABLE_FN f) +{ + if (o) { + AQH_OBJECT_ENABLE_FN oldFn; + + oldFn=o->enableFn; + o->enableFn=f; + return oldFn; + } + return NULL; +} + + + +AQH_OBJECT_DISABLE_FN AQH_Object_SetDisableFn(AQH_OBJECT *o, AQH_OBJECT_DISABLE_FN f) +{ + if (o) { + AQH_OBJECT_DISABLE_FN oldFn; + + oldFn=o->disableFn; + o->disableFn=f; + return oldFn; + } + return NULL; +} + + + + + + +AQH_LINK *AQH_Link_new() +{ + AQH_LINK *ln; + + GWEN_NEW_OBJECT(AQH_LINK, ln); + GWEN_LIST_INIT(AQH_LINK, ln); + + return ln; +} + + + +void AQH_Link_free(AQH_LINK *ln) +{ + if (ln) { + GWEN_LIST_FINI(AQH_LINK, ln); + GWEN_FREE_OBJECT(ln); + } +} + + + + + diff --git a/aqhome/events2/object.h b/aqhome/events2/object.h new file mode 100644 index 0000000..e801c9c --- /dev/null +++ b/aqhome/events2/object.h @@ -0,0 +1,121 @@ +/**************************************************************************** + * 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. + ****************************************************************************/ + +#ifndef AQH_OBJECT_H +#define AQH_OBJECT_H + +#include "aqhome/api.h" + +#include +#include +#include + +#include + + + +#define AQH_OBJECT_FLAGS_FIRE 0x80000000L + + +enum { + AQH_OBJECT_SIGNAL_LAST=10 /* reserve signal ids 0-9 */ +}; + + + +/* ------------------------------------------------------------------------------------------------ + * @name Type Definition + */ +/*@{*/ +typedef struct AQH_OBJECT AQH_OBJECT; +GWEN_INHERIT_FUNCTION_LIB_DEFS(AQH_OBJECT, AQHOME_API) +GWEN_LIST_FUNCTION_LIB_DEFS(AQH_OBJECT, AQH_Object, AQHOME_API) +GWEN_LIST2_FUNCTION_LIB_DEFS(AQH_OBJECT, AQH_Object, AQHOME_API) +/*@}*/ + + +#include + + + +/* ------------------------------------------------------------------------------------------------ + * @name Virtual Function Declarations + */ +/*@{*/ +typedef int (*AQH_OBJECT_SIGNALHANDLER_FN)(AQH_OBJECT *o, uint32_t slotId, AQH_OBJECT *senderObject, int param1, void *param2); +typedef void (*AQH_OBJECT_ENABLE_FN)(AQH_OBJECT *o); +typedef void (*AQH_OBJECT_DISABLE_FN)(AQH_OBJECT *o); +/*@}*/ + + + +/* ------------------------------------------------------------------------------------------------ + * @name Construction, Destruction + */ +/*@{*/ +AQHOME_API AQH_OBJECT *AQH_Object_new(AQH_EVENT_LOOP *eventLoop); +AQHOME_API void AQH_Object_free(AQH_OBJECT *o); +/*@}*/ + + + +/* ------------------------------------------------------------------------------------------------ + * @name Manipulate Flags + */ +/*@{*/ +AQHOME_API uint32_t AQH_Object_GetFlags(const AQH_OBJECT *o); +AQHOME_API void AQH_Object_SetFlags(AQH_OBJECT *o, uint32_t i); +AQHOME_API void AQH_Object_AddFlags(AQH_OBJECT *o, uint32_t i); +AQHOME_API void AQH_Object_SubFlags(AQH_OBJECT *o, uint32_t i); +/*@}*/ + + + +/* ------------------------------------------------------------------------------------------------ + * @name Getters, Setters + */ +/*@{*/ +AQHOME_API AQH_EVENT_LOOP *AQH_Object_GetEventLoop(const AQH_OBJECT *o); +/*@}*/ + + + +/* ------------------------------------------------------------------------------------------------ + * @name Link Handling + */ +/*@{*/ +AQHOME_API void AQH_Object_AddLink(AQH_OBJECT *o, uint32_t signalId, uint32_t slotId, AQH_OBJECT *targetObject); +AQHOME_API void AQH_Object_DelLink(AQH_OBJECT *o, uint32_t signalId, uint32_t slotId, AQH_OBJECT *targetObject); +/*@}*/ + + + +/* ------------------------------------------------------------------------------------------------ + * @name Virtual Function Declarations + */ +/*@{*/ +AQHOME_API int AQH_Object_EmitSignal(AQH_OBJECT *o, uint32_t signalId, int param1, void *param2); +AQHOME_API int AQH_Object_HandleSignal(AQH_OBJECT *o, uint32_t slotId, AQH_OBJECT *senderObject, int param1, void *param2); +AQHOME_API void AQH_Object_Enable(AQH_OBJECT *o); +AQHOME_API void AQH_Object_Disable(AQH_OBJECT *o); +/*@}*/ + + + +/* ------------------------------------------------------------------------------------------------ + * @name Setter for Virtual Functions + */ +/*@{*/ +AQHOME_API AQH_OBJECT_SIGNALHANDLER_FN AQH_Object_SetSignalHandlerFn(AQH_OBJECT *o, AQH_OBJECT_SIGNALHANDLER_FN f); +AQHOME_API AQH_OBJECT_ENABLE_FN AQH_Object_SetEnableFn(AQH_OBJECT *o, AQH_OBJECT_ENABLE_FN f); +AQHOME_API AQH_OBJECT_DISABLE_FN AQH_Object_SetDisableFn(AQH_OBJECT *o, AQH_OBJECT_DISABLE_FN f); +/*@}*/ + + + +#endif diff --git a/aqhome/events2/object_p.h b/aqhome/events2/object_p.h new file mode 100644 index 0000000..b5f5c6e --- /dev/null +++ b/aqhome/events2/object_p.h @@ -0,0 +1,46 @@ +/**************************************************************************** + * This file is part of the project Gwenhywfar. + * Gwenhywfar (c) by 2023 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. + ****************************************************************************/ + +#ifndef AQH_OBJECT_P_H +#define AQH_OBJECT_P_H + + +#include "./object.h" + + +typedef struct AQH_LINK AQH_LINK; +GWEN_LIST_FUNCTION_DEFS(AQH_LINK, AQH_Link) + + + +struct AQH_LINK { + GWEN_LIST_ELEMENT(AQH_LINK) + + uint32_t signalIdForSender; + uint32_t signalIdForTarget; + AQH_OBJECT *targetObject; +}; + + + +struct AQH_OBJECT { + GWEN_INHERIT_ELEMENT(AQH_OBJECT) + GWEN_LIST_ELEMENT(AQH_OBJECT) + + uint32_t flags; + AQH_EVENT_LOOP *eventLoop; + + AQH_LINK_LIST *linkList; + + AQH_OBJECT_SIGNALHANDLER_FN signalHandlerFn; + AQH_OBJECT_ENABLE_FN enableFn; + AQH_OBJECT_DISABLE_FN disableFn; +}; + + +#endif