summaryrefslogtreecommitdiff
path: root/Source/FusionDale/src/core/messenger.c
diff options
context:
space:
mode:
Diffstat (limited to 'Source/FusionDale/src/core/messenger.c')
-rwxr-xr-xSource/FusionDale/src/core/messenger.c305
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, &notification, fd_messenger_globals );
+}
+