diff options
Diffstat (limited to 'Source/FusionDale/src/core/messenger.c')
-rwxr-xr-x | Source/FusionDale/src/core/messenger.c | 305 |
1 files changed, 305 insertions, 0 deletions
diff --git a/Source/FusionDale/src/core/messenger.c b/Source/FusionDale/src/core/messenger.c new file mode 100755 index 0000000..adae677 --- /dev/null +++ b/Source/FusionDale/src/core/messenger.c @@ -0,0 +1,305 @@ +/* + (c) Copyright 2006-2007 directfb.org + + All rights reserved. + + Written by Denis Oliver Kropp <dok@directfb.org>. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include <config.h> + +#include <direct/debug.h> +#include <direct/messages.h> +#include <direct/util.h> + +#include <fusion/hash.h> +#include <fusion/lock.h> +#include <fusion/shmalloc.h> + +#include <core/dale_core.h> +#include <core/messenger.h> +#include <core/messenger_port.h> + +D_DEBUG_DOMAIN( DC_Mess, "Core/Messenger", "FusionDale Core Messenger" ); + +/**********************************************************************************************************************/ + +static void fd_messenger_notify( CoreMessenger *messenger, + CoreMessengerNotificationFlags flags, + CoreMessengerDispatch *dispatch ); + +/**********************************************************************************************************************/ + +static const ReactionFunc fd_messenger_globals[] = { +/* 0 */ _fd_messenger_port_messenger_listener, + NULL +}; + +static void +messenger_destructor( FusionObject *object, bool zombie, void *ctx ) +{ + CoreMessenger *messenger = (CoreMessenger*) object; + + D_MAGIC_ASSERT( messenger, CoreMessenger ); + + D_DEBUG_AT( DC_Mess, "%s( %p [%lu] )%s\n", __FUNCTION__, messenger, object->id, zombie ? " ZOMBIE!" : "" ); + + fusion_skirmish_destroy( &messenger->lock ); + + D_ASSERT( fusion_hash_size( messenger->hash ) == 0 ); + + fusion_hash_destroy( messenger->hash ); + + D_MAGIC_CLEAR( messenger ); + + fusion_object_destroy( object ); +} + +FusionObjectPool * +fd_messenger_pool_create( const FusionWorld *world ) +{ + return fusion_object_pool_create( "Messenger", sizeof(CoreMessenger), + sizeof(CoreMessengerNotification), + messenger_destructor, NULL, world ); +} + +/**********************************************************************************************************************/ + +DirectResult +fd_messenger_create( CoreDale *core, + CoreMessenger **ret_messenger ) +{ + DirectResult ret; + CoreMessenger *messenger; + + D_ASSERT( core != NULL ); + D_ASSERT( ret_messenger != NULL ); + + D_DEBUG_AT( DC_Mess, "%s( %p )\n", __FUNCTION__, core ); + + /* Create messenger object. */ + messenger = fd_core_create_messenger( core ); + if (!messenger) + return DR_FUSION; + + /* Initialize private data. */ + messenger->shmpool = fd_core_shmpool( core ); + + /* Initialize lock. */ + ret = fusion_skirmish_init( &messenger->lock, "Messenger", fd_core_world(core) ); + if (ret) + goto error; + + /* Initialize hash. */ + ret = fusion_hash_create( messenger->shmpool, HASH_STRING, HASH_PTR, 11, &messenger->hash ); + if (ret) { + D_DERROR( ret, "Core/Messenger: fusion_hash_create() failed!\n" ); + goto error_hash; + } + + /* Activate messenger object. */ + fusion_object_activate( &messenger->object ); + + D_MAGIC_SET( messenger, CoreMessenger ); + + /* Return messenger object. */ + *ret_messenger = messenger; + + return DR_OK; + + +error_hash: + fusion_skirmish_destroy( &messenger->lock ); + +error: + fusion_object_destroy( &messenger->object ); + + return ret; +} + +DirectResult +fd_messenger_create_event( CoreMessenger *messenger, + const char *name, + CoreMessengerEvent **ret_event ) +{ + DirectResult ret; + CoreMessengerEvent *event; + + D_MAGIC_ASSERT( messenger, CoreMessenger ); + D_ASSERT( name != NULL ); + D_ASSERT( ret_event != NULL ); + + /* Allocate event structure. */ + event = SHCALLOC( messenger->shmpool, 1, sizeof(CoreMessengerEvent) ); + if (!event) + return D_OOSHM(); + + /* Set back pointer. */ + event->messenger = messenger; + + /* Initialize event data. */ + event->id = ++messenger->last_event; + event->name = SHSTRDUP( messenger->shmpool, name ); + + if (!event->name) { + ret = D_OOSHM(); + goto error; + } + + /* Insert event into hash table. */ + ret = fusion_hash_insert( messenger->hash, event->name, event ); + if (ret) + goto error; + + /* Set magic. */ + D_MAGIC_SET( event, CoreMessengerEvent ); + + /* Return new event. */ + *ret_event = event; + + return DR_OK; + + +error: + if (event->name) + SHFREE( messenger->shmpool, event->name ); + + SHFREE( messenger->shmpool, event ); + + return ret; +} + +DirectResult +fd_messenger_destroy_event( CoreMessenger *messenger, + CoreMessengerEvent *event ) +{ + DirectResult ret; + void *old_key; + void *old_value; + + D_MAGIC_ASSERT( messenger, CoreMessenger ); + D_MAGIC_ASSERT( event, CoreMessengerEvent ); + + /* Remove event from hash table. */ + ret = fusion_hash_remove( messenger->hash, event->name, &old_key, &old_value ); + if (ret) { + D_BUG( "event '%s' [%lu] not found", event->name, event->id ); + return ret; + } + + D_ASSERT( old_key == event->name ); + D_ASSERT( old_value == event ); + + D_ASSERT( event->name != NULL ); + + SHFREE( messenger->shmpool, event->name ); + + D_MAGIC_CLEAR( event ); + + SHFREE( messenger->shmpool, event ); + + return ret; +} + +DirectResult +fd_messenger_lookup_event( CoreMessenger *messenger, + const char *name, + CoreMessengerEvent **ret_event ) +{ + CoreMessengerEvent *event; + + D_MAGIC_ASSERT( messenger, CoreMessenger ); + D_ASSERT( name != NULL ); + + /* Lookup event in hash table. */ + event = fusion_hash_lookup( messenger->hash, name ); + if (!event) + return DR_ITEMNOTFOUND; + + D_MAGIC_ASSERT( event, CoreMessengerEvent ); + + /* Can be NULL to just check for event existence. */ + if (ret_event) + *ret_event = event; + + return DR_OK; +} + +DirectResult +fd_messenger_dispatch_event( CoreMessenger *messenger, + CoreMessengerEvent *event, + int param, + void *data_ptr, + unsigned int data_size ) +{ + CoreMessengerDispatch *dispatch; + + D_MAGIC_ASSERT( messenger, CoreMessenger ); + D_MAGIC_ASSERT( event, CoreMessengerEvent ); + D_ASSERT( event->id != FDM_EVENT_ID_NONE ); + D_ASSERT( data_ptr != NULL || data_size == 0 ); + + /* Allocate dispatch structure. */ + dispatch = SHCALLOC( messenger->shmpool, 1, sizeof(CoreMessengerDispatch) ); + if (!dispatch) + return D_OOSHM(); + + /* Initialize dispatch structure. */ + dispatch->event_id = event->id; + dispatch->param = param; + dispatch->data = data_ptr; + dispatch->data_size = data_size; + + D_MAGIC_SET( dispatch, CoreMessengerDispatch ); + + direct_list_append( &event->dispatches, &dispatch->link ); + + fd_messenger_notify( messenger, CMNF_DISPATCH, dispatch ); + + if (!dispatch->count) { + direct_list_remove( &event->dispatches, &dispatch->link ); + + D_MAGIC_CLEAR( dispatch ); + + SHFREE( messenger->shmpool, dispatch ); + } + + return DR_OK; +} + +/**********************************************************************************************************************/ + +static void +fd_messenger_notify( CoreMessenger *messenger, + CoreMessengerNotificationFlags flags, + CoreMessengerDispatch *dispatch ) +{ + CoreMessengerNotification notification; + + D_MAGIC_ASSERT( messenger, CoreMessenger ); + D_FLAGS_ASSERT( flags, CMNF_ALL ); + + D_DEBUG_AT( DC_Mess, "%s( %p [%lu], 0x%08x )\n", __FUNCTION__, messenger, messenger->object.id, flags ); + + notification.flags = flags; + notification.messenger = messenger; + notification.dispatch = dispatch; + + fd_messenger_dispatch( messenger, ¬ification, fd_messenger_globals ); +} + |