summaryrefslogtreecommitdiff
path: root/Source/FusionDale/src/coma/component.c
diff options
context:
space:
mode:
Diffstat (limited to 'Source/FusionDale/src/coma/component.c')
-rwxr-xr-xSource/FusionDale/src/coma/component.c352
1 files changed, 352 insertions, 0 deletions
diff --git a/Source/FusionDale/src/coma/component.c b/Source/FusionDale/src/coma/component.c
new file mode 100755
index 0000000..4e6a2fc
--- /dev/null
+++ b/Source/FusionDale/src/coma/component.c
@@ -0,0 +1,352 @@
+/*
+ (c) Copyright 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/interface.h>
+#include <direct/messages.h>
+#include <direct/util.h>
+
+#include <fusion/call.h>
+#include <fusion/fusion.h>
+#include <fusion/hash.h>
+#include <fusion/lock.h>
+#include <fusion/shmalloc.h>
+
+#include <coma/coma.h>
+#include <coma/component.h>
+
+D_DEBUG_DOMAIN( Coma_Component, "Coma/Component", "Coma Component" );
+
+/**********************************************************************************************************************/
+
+struct __COMA_ComaNotification {
+ int magic;
+
+ ComaNotificationID id;
+ ComaNotificationFlags flags;
+
+ ComaComponent *component;
+
+ ComaNotifyFunc notify_func;
+ void *notify_ctx;
+};
+
+/**********************************************************************************************************************/
+
+static const ReactionFunc coma_component_globals[] = {
+ NULL
+};
+
+static void
+component_destructor( FusionObject *object, bool zombie, void *ctx )
+{
+ Coma *coma = ctx;
+ ComaComponent *component = (ComaComponent*) object;
+
+ D_MAGIC_ASSERT( component, ComaComponent );
+
+ D_DEBUG_AT( Coma_Component, "%s( %p [%lu] )%s\n", __FUNCTION__, component, object->id, zombie ? " ZOMBIE!" : "" );
+
+ _coma_internal_remove_component( coma, component );
+
+ fusion_skirmish_destroy( &component->lock );
+
+ fusion_call_destroy( &component->method_call );
+ fusion_call_destroy( &component->notify_call );
+
+ if (component->notifications) {
+ D_ASSERT( component->num_notifications > 0 );
+
+ SHFREE( component->shmpool, component->notifications );
+ }
+ else
+ D_ASSERT( component->num_notifications == 0 );
+
+ SHFREE( component->shmpool, component->name );
+
+ D_MAGIC_CLEAR( component );
+
+ fusion_object_destroy( object );
+}
+
+FusionObjectPool *
+coma_component_pool_create( Coma *coma )
+{
+ return fusion_object_pool_create( "Component", sizeof(ComaComponent), sizeof(void*),
+ component_destructor, coma, coma_world(coma) );
+}
+
+/**********************************************************************************************************************/
+
+static FusionCallHandlerResult
+method_call_handler( int caller,
+ int call_arg,
+ void *call_ptr,
+ void *ctx,
+ unsigned int serial,
+ int *ret_val )
+{
+ ComaComponent *component = ctx;
+
+ D_MAGIC_ASSERT( component, ComaComponent );
+ D_ASSUME( component->active );
+ D_ASSERT( component->method_func != NULL );
+
+ component->method_func( component->method_ctx, call_arg, call_ptr, serial );
+
+ return FCHR_RETAIN;
+}
+
+static FusionCallHandlerResult
+notify_call_handler( int caller,
+ int call_arg,
+ void *call_ptr,
+ void *ctx,
+ unsigned int serial,
+ int *ret_val )
+{
+ ComaNotification *notification;
+ ComaComponent *component = ctx;
+
+ D_MAGIC_ASSERT( component, ComaComponent );
+ D_ASSUME( component->active );
+
+ D_ASSERT( call_arg >= 0 );
+ D_ASSERT( call_arg < component->num_notifications );
+
+ notification = &component->notifications[call_arg];
+
+ D_MAGIC_ASSERT( notification, ComaNotification );
+
+ if (notification->notify_func)
+ notification->notify_func( notification->notify_ctx, call_arg, call_ptr );
+
+ if (call_ptr && (notification->flags & CNF_DEALLOC_ARG))
+ SHFREE( component->shmpool, call_ptr );
+
+ return FCHR_RETURN;
+}
+
+/**********************************************************************************************************************/
+
+DirectResult
+coma_component_init( ComaComponent *component,
+ Coma *coma,
+ const char *name,
+ ComaMethodFunc func,
+ int num_notifications,
+ void *ctx )
+{
+ DirectResult ret;
+ FusionWorld *world;
+
+ D_ASSERT( component != NULL );
+ D_ASSERT( coma != NULL );
+ D_ASSERT( name != NULL );
+ D_ASSERT( func != NULL );
+ D_ASSERT( num_notifications >= 0 );
+
+ D_DEBUG_AT( Coma_Component, "%s( %p, %p, '%s', %p, %d, %p )\n", __FUNCTION__,
+ component, coma, name, func, num_notifications, ctx );
+
+ world = coma_world( coma );
+
+ component->shmpool = coma_shmpool( coma );
+
+ /* Initialize lock. */
+ ret = fusion_skirmish_init( &component->lock, "Component", world );
+ if (ret)
+ return ret;
+
+ /* Set name. */
+ component->name = SHSTRDUP( component->shmpool, name );
+ if (!component->name) {
+ ret = D_OOSHM();
+ goto error;
+ }
+
+ /* Create notification table. */
+ if (num_notifications) {
+ component->notifications = SHCALLOC( component->shmpool, num_notifications, sizeof(ComaNotification) );
+ if (!component->notifications) {
+ ret = D_OOSHM();
+ goto error;
+ }
+
+ component->num_notifications = num_notifications;
+ }
+
+ /* Remember creator. */
+ component->provider = fusion_id( world );
+
+ /* Initialize calls. */
+ fusion_call_init( &component->method_call, method_call_handler, component, world );
+ fusion_call_init( &component->notify_call, notify_call_handler, component, world );
+
+ /* Setup notification dispatch callback. */
+ fusion_reactor_set_dispatch_callback( component->object.reactor, &component->notify_call, NULL );
+
+ /* Change name of the reactor to something more specific than just "Component" from object pool. */
+ fusion_reactor_set_name( component->object.reactor, name );
+
+ /* Setup method invocation handler. */
+ component->method_func = func;
+ component->method_ctx = ctx;
+
+ D_MAGIC_SET( component, ComaComponent );
+
+ return DR_OK;
+
+
+error:
+ if (component->notifications)
+ SHFREE( component->shmpool, component->notifications );
+
+ if (component->name)
+ SHFREE( component->shmpool, component->name );
+
+ fusion_skirmish_destroy( &component->lock );
+
+ return ret;
+}
+
+DirectResult
+coma_component_lock( ComaComponent *component )
+{
+ D_MAGIC_ASSERT( component, ComaComponent );
+
+ return fusion_skirmish_prevail( &component->lock );
+}
+
+DirectResult
+coma_component_unlock( ComaComponent *component )
+{
+ D_MAGIC_ASSERT( component, ComaComponent );
+
+ return fusion_skirmish_dismiss( &component->lock );
+}
+
+DirectResult
+coma_component_activate( ComaComponent *component )
+{
+ DirectResult ret;
+
+ D_MAGIC_ASSERT( component, ComaComponent );
+ FUSION_SKIRMISH_ASSERT( &component->lock );
+ D_ASSUME( !component->active );
+
+ D_DEBUG_AT( Coma_Component, "%s( %p ) <- '%s'\n", __FUNCTION__, component, component->name );
+
+ if (component->active)
+ return DR_BUSY;
+
+ component->active = true;
+
+ ret = fusion_skirmish_notify( &component->lock );
+ if (ret)
+ D_DERROR( ret, "Coma/Component: fusion_skirmish_notify() failed!\n" );
+
+ return ret;
+}
+
+DirectResult
+coma_component_init_notification( ComaComponent *component,
+ ComaNotificationID id,
+ ComaNotifyFunc func,
+ void *ctx,
+ ComaNotificationFlags flags )
+{
+ ComaNotification *notification;
+
+ D_MAGIC_ASSERT( component, ComaComponent );
+ FUSION_SKIRMISH_ASSERT( &component->lock );
+ D_ASSUME( !component->active );
+
+ D_DEBUG_AT( Coma_Component, "%s( %p, %lu - %p )\n", __FUNCTION__, component, id, func );
+
+ if (id < 0 || id >= component->num_notifications)
+ return DR_LIMITEXCEEDED;
+
+ notification = &component->notifications[id];
+ if (notification->component) {
+ D_MAGIC_ASSERT( notification, ComaNotification );
+ return DR_BUSY;
+ }
+
+ notification->id = id;
+ notification->flags = flags;
+ notification->component = component;
+ notification->notify_func = func;
+ notification->notify_ctx = ctx;
+
+ D_MAGIC_SET( notification, ComaNotification );
+
+ return DR_OK;
+}
+
+DirectResult
+coma_component_call( ComaComponent *component,
+ ComaMethodID method,
+ void *arg,
+ int *ret_val )
+{
+ D_MAGIC_ASSERT( component, ComaComponent );
+ D_ASSUME( component->active );
+
+ D_DEBUG_AT( Coma_Component, "%s( %p, %lu - %p, %p )\n", __FUNCTION__, component, method, arg, ret_val );
+
+ return fusion_call_execute( &component->method_call, FCEF_NONE, method, arg, ret_val );
+}
+
+DirectResult
+coma_component_return( ComaComponent *component,
+ unsigned int serial,
+ int val )
+{
+ D_MAGIC_ASSERT( component, ComaComponent );
+ D_ASSUME( component->active );
+
+ D_DEBUG_AT( Coma_Component, "%s( %p, %u - %d )\n", __FUNCTION__, component, serial, val );
+
+ return fusion_call_return( &component->method_call, serial, val );
+}
+
+DirectResult
+coma_component_notify( ComaComponent *component,
+ ComaNotificationID id,
+ void *arg )
+{
+ D_MAGIC_ASSERT( component, ComaComponent );
+ D_ASSUME( component->active );
+
+ D_DEBUG_AT( Coma_Component, "%s( %p [%lu], %lu - %p )\n", __FUNCTION__,
+ component, component->object.id, id, arg );
+
+ D_ASSERT( id >= 0 );
+ D_ASSERT( id < component->num_notifications );
+
+ return coma_component_dispatch_channel( component, id, &arg, sizeof(void*), coma_component_globals );
+}
+