X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=lily%2Finclude%2Fsmobs.hh;h=00217866dc07dc92eff400e23050d50b46f67a3b;hb=bf14e3a7d89454c17f65b291d192d05752afad27;hp=c5edc4b01f63a0cad022360a25006f96e8ba9e99;hpb=1b5f1825a6655583a6209fedd51b98f4865bb2cd;p=lilypond.git diff --git a/lily/include/smobs.hh b/lily/include/smobs.hh index c5edc4b01f..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,26 +201,19 @@ 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); static SCM equal_p (SCM, SCM); - int print_smob (SCM, scm_print_state *); + int print_smob (SCM, scm_print_state *) const; 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