Platon Technologies
not logged in Login Registration
EnglishSlovak
open source software development celebrating 10 years of open source development! Saturday, April 20, 2024

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/
Copyright © 2002-2006 Platon Group
Site powered by Metafox CMS
Go to Top