--- deliantra/server/include/cfperl.h 2006/12/19 04:58:04 1.40 +++ deliantra/server/include/cfperl.h 2006/12/25 11:25:49 1.41 @@ -43,6 +43,7 @@ { KLASS_NONE, KLASS_GLOBAL, + KLASS_ATTACHABLE, KLASS_CLIENT, KLASS_PLAYER, KLASS_OBJECT, @@ -58,94 +59,114 @@ NUM_EVENT_TYPES }; -#define ARG_AV(o) DT_AV , static_cast (o) -#define ARG_INT(v) DT_INT , static_cast (v) -#define ARG_INT64(v) DT_INT64 , static_cast (v) -#define ARG_DOUBLE(v) DT_DOUBLE, static_cast (v) -#define ARG_STRING(v) DT_STRING, static_cast (v) -#define ARG_DATA(s,l) DT_DATA , static_cast (s), int (l) -#define ARG_OBJECT(o) DT_OBJECT, (void *)static_cast (o) -#define ARG_MAP(o) DT_MAP , (void *)static_cast (o) -#define ARG_PLAYER(o) DT_PLAYER, (void *)static_cast (o) -#define ARG_ARCH(o) DT_ARCH , (void *)static_cast (o) -#define ARG_PARTY(o) DT_PARTY , (void *)static_cast (o) -#define ARG_REGION(o) DT_REGION, (void *)static_cast (o) -#define ARG_CLIENT(o) DT_CLIENT, (void *)static_cast (o) +#define ARG_AV(o) DT_AV , static_cast (o) +#define ARG_INT(v) DT_INT , static_cast (v) +#define ARG_INT64(v) DT_INT64 , static_cast (v) +#define ARG_DOUBLE(v) DT_DOUBLE, static_cast (v) +#define ARG_STRING(v) DT_STRING, static_cast (v) +#define ARG_DATA(s,l) DT_DATA , static_cast (s), int (l) +#define ARG_OBJECT(o) DT_OBJECT, (void *)(static_cast (o)) +#define ARG_MAP(o) DT_MAP , (void *)(static_cast (o)) +#define ARG_PLAYER(o) DT_PLAYER, (void *)(static_cast (o)) +#define ARG_ARCH(o) DT_ARCH , (void *)(static_cast (o)) +#define ARG_CLIENT(o) DT_CLIENT, (void *)(static_cast (o)) +#define ARG_PARTY(o) DT_PARTY , (void *)(static_cast (o)) +#define ARG_REGION(o) DT_REGION, (void *)(static_cast (o)) // the ", ## __VA_ARGS" is, unfortunately, a gnu-cpp extension // all these return true when the normal event processing should be skipped (if any) -#define INVOKE_(event, ...) cfperl_invoke (event, ## __VA_ARGS__, DT_END) - -#define INVOKE(klass, event, ...) INVOKE_(EVENT_ ## klass ## _ ## event, ## __VA_ARGS__) -#define INVOKE_GLOBAL(event, ...) INVOKE_(EVENT_ ## GLOBAL ## _ ## event, ## __VA_ARGS__) -#define INVOKE_OBJECT(event, op, ...) INVOKE_(EVENT_ ## OBJECT ## _ ## event, ARG_OBJECT (op), ## __VA_ARGS__) -#define INVOKE_CLIENT(event, ns, ...) INVOKE_(EVENT_ ## CLIENT ## _ ## event, ARG_CLIENT (ns), ## __VA_ARGS__) -#define INVOKE_PLAYER(event, pl, ...) INVOKE_(EVENT_ ## PLAYER ## _ ## event, ARG_PLAYER (pl), ## __VA_ARGS__) -#define INVOKE_MAP(event, map, ...) INVOKE_(EVENT_ ## MAP ## _ ## event, ARG_MAP (map) , ## __VA_ARGS__) +#define INVOKE_GLOBAL(event, ...) gbl_ev.invoke (EVENT_ ## GLOBAL ## _ ## event, ## __VA_ARGS__, DT_END) +#define INVOKE_ATTACHABLE(event, obj, ...) (obj)->invoke (EVENT_ ## ATTACHABLE ## _ ## event, ## __VA_ARGS__, DT_END) +#define INVOKE_OBJECT(event, obj, ...) (obj)->invoke (EVENT_ ## OBJECT ## _ ## event, ## __VA_ARGS__, DT_END) +#define INVOKE_CLIENT(event, obj, ...) (obj)->invoke (EVENT_ ## CLIENT ## _ ## event, ## __VA_ARGS__, DT_END) +#define INVOKE_PLAYER(event, obj, ...) (obj)->invoke (EVENT_ ## PLAYER ## _ ## event, ## __VA_ARGS__, DT_END) +#define INVOKE_MAP(event, obj, ...) (obj)->invoke (EVENT_ ## MAP ## _ ## event, ## __VA_ARGS__, DT_END) //TODO should index into @result #define RESULT(idx,type) cfperl_result_ ## type (idx) #define RESULT_DOUBLE(idx) RESULT(idx, DOUBLE) #define RESULT_INT(idx) RESULT(idx, INT) -bool cfperl_invoke (event_type event, ...); double cfperl_result_DOUBLE (int idx); int cfperl_result_INT (int idx); -struct attachable_base +struct attachable { - SV *self; // CF+ perl self + static unordered_vector mortals; + static void check_mortals (); + + enum { + F_DESTROYED = 0x01, + F_BORROWED = 0x02, + }; + + // object is delete'd after the refcount reaches 0 + mutable int refcnt; + int flags; + + void refcnt_inc () const { ++refcnt; } + void refcnt_dec () const { --refcnt; } + + // check wether the object has died and destroy + void refcnt_chk () { if (refcnt <= 0) do_check (); } + + // destroy the object unless it was already destroyed + // this politely asks everybody interested the reduce + // the refcount to 0 as soon as possible. + void destroy (); + + // return wether an object was destroyed already + bool destroyed () const { return flags & F_DESTROYED; } + + virtual void gather_callbacks (AV *&callbacks, event_type event) const; + +#if 0 +private: + static refcounted *rc_first; + refcounted *rc_next; +#endif + + HV *self; // CF+ perl self AV *cb; // CF+ callbacks shstr attach; // generic extension attachment information - void clear (); // called when free'ing objects void optimise (); // possibly save some memory by destroying unneeded data - void instantiate (data_type type, void *obj); - void attachable_clear () + attachable () + : flags (0), refcnt (0), self (0), cb (0), attach (0) { - self = 0; - cb = 0; - attach = 0; } - attachable_base () + attachable (const attachable &src) + : flags (0), refcnt (0), self (0), cb (0), attach (src.attach) { - attachable_clear (); } - ~attachable_base () - { - clear (); - } + virtual ~attachable (); - attachable_base (const attachable_base &src) - : self (0), cb (0), attach (src.attach) - { - } + attachable &operator =(const attachable &src); - attachable_base &operator =(const attachable_base &src) - { - clear (); - attach = src.attach; - return *this; - } + bool invoke (event_type event, ...); + void instantiate (); + void reattach (); + +protected: + // do the real refcount checking work + void do_check (); + + // the method that does the real destroy work + virtual void do_destroy (); }; -// objects attachable from perl (or any other extension) should include or -// derive using the curiously recurring template pattern, to avoid -// virtual method calls etc. -template -struct attachable : attachable_base +// the global object is a pseudo object that cares for the global events +struct global : attachable { - void instantiate () - { - if (attach) - attachable_base::instantiate ((data_type) cftype::dt, static_cast(this)); - } + void gather_callbacks (AV *&callbacks, event_type event) const; }; +extern struct global gbl_ev; + struct object_freezer : dynbuf { AV *av; @@ -153,13 +174,7 @@ object_freezer (); ~object_freezer (); - void put (attachable_base *ext); - - template - void put (attachable *obj) - { - put ((attachable_base *)obj); - } + void put (attachable *ext); // used only for user-defined key-value pairs void put (const shstr &k, const shstr &v) @@ -298,14 +313,7 @@ object_thawer (const char *data, AV *perlav); ~object_thawer (); - void get (data_type type, void *obj, attachable_base *ext, int oid); - - template - void get (attachable *obj, int oid) - { - if (av) - get ((data_type) cftype::dt, (subclass *)obj, obj, oid); - } + void get (attachable *obj, int oid); keyword get_kv (); // also parse value for later use