File: [Platon] / libco / libco / co_o_small.c (download)
Revision 1.1, Sun Mar 30 10:26:58 2003 UTC (21 years ago) by yenar
add implementation of basic object flavour: 'small' - mostly comes
from co_object.c, with some improvements [co_o_small.c, co_o_small.h]
|
/***{{{*******************************************************************
* This file is part of libco - object library for C *
* Copyright (c) 2002 *
* Peter Rockai (yenar) <yenar@host.sk> *
* *
* 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 *
*******************************************************************}}}***/
/* {{{ file description */
/**
* @file co_o_small.c
* @brief Implementation of "small" object flavour.
**/
/* }}} */
/* {{{ includes */
#include "co_util.h"
#include "co_object.h"
#include "co_o_small.h"
#include "co_exception.h"
#include "co_conv.h"
/* }}} */
#include "co_o_small.cometa"
/* {{{ */
static void co_o_small_msg_recov (void *o, const void *ignore)
{
(void) ignore;
((co_o_small) o) -> msg_depth --;
}
/* }}} */
/* {{{ */
static inline co_v co_o_small_msg2 (co this, co self, co_id_t message,
va_list ap)
/// Default, table-driven message handler for object (internal).
/**
* This function shouldn't be used in any explicit way. It will be
* assigned to objects which do not implement it's own message-arrival
* handler automatically.
*
* @internal
**/
{
co_o_small head = this;
co_meth_entry def = 0;
co_meth_entry cur = 0;
unsigned i;
for (i = 0; i < head -> meth_ar -> n; i ++) {
cur = head -> meth_ar -> meth + i;
CO_DEBUG (3, "trying handler %d == message %d",
cur -> message, message);
if (message == cur -> message)
return cur -> handler (this, self, message, ap);
if (cur -> message == COM (default))
def = cur;
}
// fallback to default method
if (def)
return def -> handler (this, self, message, ap);
COX_THROW (message_unhandled);
// just to silence compiler
CO_RETURN (int, 0xBAD0);
}
/* }}} */
/* {{{ */
static co_v co_o_small_msg (co _o, co s, co_id_t a, va_list ap)
{
co_o_small o = _o;
int db;
volatile co_v rv;
#if DEBUGLVL > 0
char __msg_id [128];
int __lastdbg = __co_debug_msg_level;
#endif
db = o -> destroy;
o -> msg_depth ++;
cox_stack_push (COX_STACK_MESG, o, co_o_small_msg_recov, 0);
CO_DEBUG (1, "processing: o = %p, s = %p, msg = %d", o, s, a);
/* {{{ debug */
#if DEBUGLVL > 0
__co_debug_msg_level ++;
sprintf (__msg_id, "unknown %d (FIXME)", a);
//snprintf (__msg_id, 128, "%s/%s",
// __co_type_array [o -> t] . name, __co_action_array [a]);
CO_DEBUG2 (2, "---------------------------------------------------"
"-----------------------------\n");
CO_DEBUG2 (2, " BEGIN HANDLE MESSAGE | %23s | %p\n", __msg_id, o);
#endif
/* }}} */
//rv = o -> __co_msg (o, s, a, ap);
rv = co_o_small_msg2 (o, s, a, ap);
// FIXME: whuum, this is err, hacky
/* if (a == COM (destroy2))
return rv; */
/* {{{ debug */
#if DEBUGLVL > 0
CO_DEBUG2 (2, " END HANDLE MESSAGE | %23s | %p\n", __msg_id, o);
CO_DEBUG2 (2, "---------------------------------------------------"
"-----------------------------\n");
__co_debug_msg_level --;
#endif
/* }}} */
// FIXME? this might be a race condition; OTOH this way it's faster
o -> msg_depth --;
cox_stack_pop (COX_STACK_MESG, o, false);
// FIXME?
if ((!db) && (! (o -> msg_depth)) && o -> destroy)
co_o_small_msg2 (o, o, COM (destroy2), 0);
return rv;
} /* }}} */
/* {{{ */
void co_o_small_bless (co _o)
{
co_o_small o = _o;
o -> destroy = 0;
o -> data = 0;
o -> msg_handle = co_o_small_msg;
o -> msg_depth = 0;
}
/* }}} */
/* {{{ */
co co_o_small_new (void)
{
co_o_small this;
this = new (co_o_small_s);
co_o_small_bless (this);
cox_pop (this);
CO_PUSH (this);
return this;
}
/* }}} */
/* {{{ */
co_v co_o_small_delete (co _o, co self, co_id_t message, va_list ap)
{
co_o_small o = _o;
o -> destroy = 1;
CO_DEBUG (3, "postponed object deletion: %p", o);
//if (o -> destroy)
// return; // already being destroyed :)
/* if (o -> msg_depth) {
o -> destroy = 1;
CO_DEBUG (3, "postponed object deletion: %p", o);
} else {
CO_DEBUG (3, "immediate object deletion: %p", o);
M (o, destroy2);
} */
CO_RETURN (int, 0);
} /* }}} */
/* {{{ */
co_v co_o_small_destroy (co _o, co self, co_id_t message, va_list ap)
{
co_o_small o = _o;
M (o, destroy);
free (o);
CO_RETURN (int, 0);
} /* }}} */
/* {{{ */
co_v co_has_method (co this, co self, co_id_t message, va_list ap)
/// Reflection message handler.
{
co_o_small head = this;
co_id_t find = va_arg (ap, co_id_t);
unsigned i;
(void) message; (void) self;
CO_DEBUG (3, "co_has_method called");
for (i = 0; i < head -> meth_ar -> n; i ++) {
// cur = head -> meth_ar -> meth + i;
if (find == head -> meth_ar -> meth [i] . message) {
CO_DEBUG (3, "found[%d]: %d", i, find);
CO_RETURN (int, 1);
}
}
CO_RETURN (int, 0);
}
/* }}} */
/* {{{ */
void *co_meth_array_new (void)
{
co_meth_array ar;
ar = cox_malloc (sizeof (co_meth_array_s));
ar -> n = 0;
ar -> size = 4;
ar -> meth = cox_malloc (sizeof (co_meth_entry_s) * 4);
cox_pop (ar -> meth);
cox_pop (ar);
return ar;
}
/* }}} */
/* {{{ */
void *co_meth_array_dup (co_meth_array src)
{
co_meth_array dest;
dest = cox_malloc (sizeof (co_meth_array_s));
dest -> n = src -> n;
dest -> size = src -> size;
dest -> meth = cox_malloc (sizeof (co_meth_entry_s) * dest -> size);
memcpy (dest -> meth, src -> meth, src -> n * sizeof (co_meth_entry_s));
cox_pop (dest -> meth);
cox_pop (dest);
return dest;
}
/* }}} */
/* {{{ */
co_id_t co_meth_add (co_meth_array ar, co_id_t msg, co_message_handler handl)
{
if (ar -> n >= ar -> size) {
CO_DEBUG (2, "growing %p", ar);
ar -> size *= 2;
ar -> meth = realloc (ar -> meth, ar -> size *
sizeof (co_meth_entry_s));
}
ar -> meth [ar -> n] . message = msg;
ar -> meth [ar -> n] . handler = handl;
//ar -> master [ar -> n] . name = name;
//co_meth_sort (ar);
ar -> n ++;
return msg;
}
/* }}} */
/* {{{ */
void co_meth_array_free (co_meth_array ar)
{
free (ar -> meth);
free (ar);
}
/* }}} */
/* {{{ */
void co_o_small_copy (co_o_small dest, co_o_small src)
{
dest -> type = src -> type;
dest -> msg_handle = src -> msg_handle;
dest -> data = src -> data;
dest -> meth_ar = src -> meth_ar;
CO_RETURN (co, dest);
}
/* }}} */
/* {{{ */
co_v co_o_small_clone_min (co this, co self, co_id_t message, va_list ap)
{
co_o_small dest, o = this;
(void) message; (void) self; (void) ap;
CO_DEBUG (2, "called");
dest = co_o_small_new ();
dest -> type = o -> type;
dest -> msg_handle = o -> msg_handle;
// dest -> destroy = o -> destroy; // ?!
dest -> data = o -> data;
dest -> meth_ar = o -> meth_ar;
CO_RETURN (co, dest);
}
/* }}} */
/* {{{ */
co_v co_o_small_clone (co this, co self, co_id_t message, va_list ap)
{
co_o_small dest, o = this;
CO_DEBUG (2, "called");
dest = co_o_small_clone_min (this, self, message, ap) . _co;
M (dest, data_copy_from, this);
CO_RETURN (co, dest);
}
/* }}} */
/* {{{ */
co_v co_o_small_clone_deep (co this, co self, co_id_t message, va_list ap)
{
co_o_small dest, o = this;
CO_DEBUG (2, "called");
dest = co_o_small_clone_min (this, self, message, ap) . _co;
M (dest, data_copy_deep_from, this);
CO_RETURN (co, dest);
}
/* }}} */
#if 0
/* {{{ */
co_v co_clone_shallow (co this, co self, co_id_t message, va_list ap)
{
//co_o_small head = this;
co dest;
(void) message; (void) self; (void) ap;
CO_RETURN (co, this);
}
/* }}} */
/* {{{ */
co_v co_clone_deep (co this, co self, co_id_t message, va_list ap)
{
co n = M (this, sclone) . _co;
M (n, copy_deep, this); // ask object to copy over its data
CO_RETURN (co, n);
}
/* }}} */
/* {{{ */
co_v co_clone_full (co this, co self, co_id_t message, va_list ap)
{
co n = M (this, dclone) . _co;
((co_o_small) n) -> meth_ar =
co_meth_array_dup (((co_o_small) this) -> meth_ar);
CO_RETURN (co, n);
}
/* }}} */
/* {{{ */
co_v co_clone_clean (co this, co self, co_id_t message, va_list ap)
{
co n = M (this, sclone) . _co;
M (n, clean);
CO_RETURN (co, n);
}
/* }}} */
/* {{{ */
co_v co_clone_clean_full (co this, co self, co_id_t message, va_list ap)
{
co n = M (this, sclone) . _co;
M (n, clean);
((co_o_small) n) -> meth_ar =
co_meth_array_dup (((co_o_small) this) -> meth_ar);
CO_RETURN (co, n);
}
/* }}} */
/* {{{ */
static void __co_del (co o)
/// Delete object (internal).
/**
* Is identical to co_del_f, but internal. Use co_del_f instead.
**/
{
CO_DEBUG (3, "performing object destruction: %p", o);
((co_o_head) o) -> destroy = 1;
CO_EV (o, destroyed);
co_o_destroy (o);
((co_o_small) o) -> msg (o, o, COM (destroy), 0);
} /* }}} */
/* {{{ */
void co_del (co o)
{
if (((co_o_small) o) -> destroy) return; // already being destroyed :)
if (((co_o_small) o) -> msg_depth) {
((co_o_small) o) -> destroy = 1;
CO_DEBUG (3, "postponed object deletion: %p", o);
} else {
CO_DEBUG (3, "immediate object deletion: %p", o);
__co_del (o);
}
} /* }}} */
/* {{{ */
void co_del_f (co o)
{
CO_DEBUG (2, "forcing object deletion: %p", o);
__co_del (o);
} /* }}} */
/* {{{ */
co __co_o_bless (co o)
{
CO_DEBUG (3, "blessing object %p", o);
CO_PUSH (o);
CO_M (o, bless);
return o;
}
/* }}} */
/* {{{ */
co __co_o_bless_p (co o)
{
CO_DEBUG (3, "blessing object %p", o);
CO_M (o, bless);
return o;
}
/* }}} */
#endif /* 0 */
Platon Group <platon@platon.org> http://platon.org/
|