X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=lily%2Finclude%2Fsmobs.hh;h=00217866dc07dc92eff400e23050d50b46f67a3b;hb=90e4d7057f3857da049dfda3d130017d4719bd6b;hp=9ccaa61345565a02a4a50d5ac6d402389993b934;hpb=0b25807868f2e1f3372a8fb5e19d9036dec53ecc;p=lilypond.git diff --git a/lily/include/smobs.hh b/lily/include/smobs.hh index 9ccaa61345..00217866dc 100644 --- a/lily/include/smobs.hh +++ b/lily/include/smobs.hh @@ -95,6 +95,30 @@ Complex smobs are created by deriving from Smob. + However, this is not sufficient when classes with their own + protectable elements are derived from the Complex base class. This + is because initialization order is a tricky thing: once a base class + calls smobify_self () in its constructor, further allocations during + construction of base class and derived classes might lead to + mark_smob calls on the object under construction. When those call a + virtual function like derived_mark, the virtual function + corresponding to the incompletely initialized object of derived + class type is likely to be called. + + The order of initialization of an object consists in calling the + constructors of virtual base classes, then of non-virtual base + classes, then initializing all data members. + + As a result, the constructor of a derived class comes too late for + initialization of data members that may be accessed in the + derived_mark kind of functions. + + Such data members are consequently moved into Preinit_* classes + which come before the smobifying base class in derivation order and + construct the contained data members in a state suitable for + derived_mark calls. + + CALLING INTERFACE Common global functions for accessing C++ smob objects: @@ -120,7 +144,7 @@ debugging purposes. If the class does not define this function, the output will be # when printing. - - a static const type_p_name_[] string set to something like + - a static const * const type_p_name_ string set to something like "ly:grob?". When provided, an accordingly named function for checking for the given smob type will be available in Scheme. @@ -177,6 +201,7 @@ private: // Most default functions are do-nothings. void init() will // recognize their address when not overriden and will then refrain // altogether from passing the the respective callbacks to GUILE. + SCM mark_smob (void) const; static SCM mark_trampoline (SCM); // Used for calling mark_smob static size_t free_smob (SCM obj); @@ -185,18 +210,10 @@ private: static int print_trampoline (SCM, SCM, scm_print_state *); static void smob_proc_init (scm_t_bits) { }; - // type_p_name_ can be overriden in the Super class with a static - // const char [] string. This requires both a declaration in the - // class as well as a single instantiation outside. Using a - // template specialization for supplying a different string name - // right in Smob_base itself seems tempting, but the C++ - // rules would then require a specialization declaration at the - // class definition site as well as a specialization instantiation - // in a single compilation unit. That requires just as much source - // code maintenance while being harder to understand and quite - // trickier in its failure symptoms when things go wrong. So we - // just use a static zero as "not here" indication. - static const int type_p_name_ = 0; + // Define type_p_name_ in the Super class as a const char * const. + // Without such definition it defaults to 0, producing no predicate. + + static const char * const type_p_name_; // = 0 // LY_DECLARE_SMOB_PROC is used in the Super class definition for // making a smob callable like a function. Its first argument is a