while (pending_grobs ());
}
-void
-Engraver_group::pre_init ()
+Preinit_Engraver_group::Preinit_Engraver_group ()
{
acknowledge_hash_table_drul_.set (SCM_EOL, SCM_EOL);
}
#include "output-def.hh"
#include "warn.hh"
-void
-Global_context::pre_init ()
+Preinit_Global_context::Preinit_Global_context ()
{
output_def_ = 0;
}
Direction start_end () const { return start_end_; }
};
-class Engraver_group : public Preinit<Engraver_group>, public Translator_group
+struct Preinit_Engraver_group
+{
+ Drul_array<SCM> acknowledge_hash_table_drul_;
+ Preinit_Engraver_group ();
+};
+
+class Engraver_group : Preinit_Engraver_group, public Translator_group
{
protected:
vector<Announce_grob_info> announce_infos_;
- Drul_array<SCM> acknowledge_hash_table_drul_;
void override (SCM);
void revert (SCM);
public:
DECLARE_CLASSNAME (Engraver_group);
- void pre_init ();
Engraver_group ();
virtual void derived_mark () const;
void do_announces ();
#include "context.hh"
#include "pqueue.hh"
-class Global_context : public Preinit<Global_context>, public Context
+struct Preinit_Global_context
{
- PQueue<Moment> extra_mom_pq_;
Output_def *output_def_;
+ Preinit_Global_context ();
+};
+
+class Global_context : Preinit_Global_context, public Context
+{
+ PQueue<Moment> extra_mom_pq_;
virtual void derived_mark () const;
DECLARE_CLASSNAME (Global_context);
friend class Output_def;
public:
- void pre_init ();
Global_context (Output_def *);
int get_moments_left () const;
Moment sneaky_insert_extra_moment (Moment);
#include "font-metric.hh"
+struct Preinit_Modified_font_metric
+{
+ Font_metric *orig_;
+ Preinit_Modified_font_metric ();
+};
+
/* Perhaps junk this, and move this to layout_def as interface? */
-struct Modified_font_metric : public Preinit<Modified_font_metric>,
+class Modified_font_metric : Preinit_Modified_font_metric,
public Font_metric
{
public:
size_t name_to_index (string) const;
size_t index_to_charcode (size_t) const;
Font_metric *original_font () const;
- void pre_init ();
protected:
- Font_metric *orig_;
Real magnification_;
Modified_font_metric (Font_metric *fm, Real magnification);
#define is_mus_type(x) internal_is_music_type (ly_symbol2scm (x))
-class Music : public Preinit<Music>, public Prob
+struct Preinit_Music {
+ SCM length_callback_;
+ SCM start_callback_;
+ Preinit_Music ();
+};
+
+class Music : Preinit_Music, public Prob
{
public:
- void pre_init ();
Music (SCM init);
Music (Music const &m);
VIRTUAL_COPY_CONSTRUCTOR (Music, Music);
virtual void type_check_assignment (SCM, SCM) const;
virtual void derived_mark () const;
protected:
- SCM length_callback_;
- SCM start_callback_;
friend SCM ly_extended_make_music (SCM, SCM);
};
void get_unicode_name (char *s, FT_ULong code);
void get_glyph_index_name (char *s, FT_ULong code);
-class Open_type_font : public Preinit<Open_type_font>, public Font_metric
-{
- /* handle to face object */
- FT_Face face_;
- string postscript_name_;
-
+struct Preinit_Open_type_font {
SCM lily_subfonts_;
SCM lily_character_table_;
SCM lily_global_table_;
SCM lily_index_to_bbox_table_;
+ Preinit_Open_type_font ();
+};
+
+class Open_type_font : Preinit_Open_type_font, public Font_metric
+{
+ /* handle to face object */
+ FT_Face face_;
+ string postscript_name_;
Index_to_charcode_map index_to_charcode_map_;
Open_type_font (FT_Face);
DECLARE_CLASSNAME (Open_type_font);
public:
- void pre_init ();
Real get_units_per_EM () const;
SCM get_subfonts () const;
SCM get_global_table () const;
#include "font-metric.hh"
-class Pango_font : public Preinit<Pango_font>, public Font_metric
+struct Preinit_Pango_font {
+ SCM physical_font_tab_;
+ Preinit_Pango_font ();
+};
+
+class Pango_font : Preinit_Pango_font, public Font_metric
{
PangoContext *context_;
PangoFontDescription *pango_description_;
PangoAttrList *attribute_list_;
Real scale_;
Real output_scale_;
- SCM physical_font_tab_;
Direction text_direction_;
public:
SCM physical_font_tab () const;
- void pre_init ();
Pango_font (PangoFT2FontMap *,
PangoFontDescription const *,
Real);
#include "engraver.hh"
-class Scheme_engraver : public Preinit<Scheme_engraver>, public Engraver
+struct Preinit_Scheme_engraver {
+ SCM initialize_function_;
+ SCM finalize_function_;
+ SCM precomputable_methods_ [TRANSLATOR_METHOD_PRECOMPUTE_COUNT];
+
+ // hashq table of interface-symbol -> scheme-function
+ Drul_array<SCM> interface_acknowledger_hash_;
+
+ // Alist of listened-symbol . scheme-function
+ SCM per_instance_listeners_;
+ Preinit_Scheme_engraver ();
+};
+
+class Scheme_engraver : Preinit_Scheme_engraver, public Engraver
{
public:
TRANSLATOR_FAMILY_DECLARATIONS (Scheme_engraver);
- void pre_init ();
Scheme_engraver (SCM definition);
protected:
SCM translator_description () const { return SCM_EOL; }
bool must_be_last_;
-
- SCM initialize_function_;
- SCM finalize_function_;
- SCM precomputable_methods_ [TRANSLATOR_METHOD_PRECOMPUTE_COUNT];
-
- // hashq table of interface-symbol -> scheme-function
- Drul_array<SCM> interface_acknowledger_hash_;
-
- // Alist of listened-symbol . scheme-function
- SCM per_instance_listeners_;
};
#endif /* SCHEME_ENGRAVER_HH */
Complex smobs are created by deriving from Smob<Classname>.
+ 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:
}
};
-// This 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 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 derived constructor comes too late for
-// initialization. That's where the Preinit template class comes in.
-// Derive from it _before_ deriving from the smobifying base class
-// providing derived_mark, and it will call its Base class' pre_init
-// function (which must not rely on the instantiation being complete).
-
-template <class Base>
-class Preinit {
-protected:
- Preinit ()
- {
- (static_cast <Base *> (this)) -> pre_init ();
- }
-};
-
extern bool parsed_objects_should_be_dead;
class parsed_dead
{
is absolutely necessary for beams, since they have to adjust the
length of stems of notes they encompass.
*/
-class Spanner : public Preinit<Spanner>, public Grob
+
+struct Preinit_Spanner
{
Drul_array<Item *> spanned_drul_;
+ SCM pure_property_cache_;
+ Preinit_Spanner ();
+};
+
+class Spanner : Preinit_Spanner, public Grob
+{
vsize break_index_;
DECLARE_CLASSNAME (Spanner);
void set_bound (Direction d, Grob *);
Item *get_bound (Direction d) const;
- void pre_init ();
Spanner (SCM);
Spanner (Spanner const &);
bool is_broken () const;
void cache_pure_property (SCM sym, int start, int end, SCM value);
protected:
- SCM pure_property_cache_;
-
void set_my_columns ();
virtual Grob *clone () const;
virtual void do_break_processing ();
#include "main.hh"
#include "program-option.hh"
-void Modified_font_metric::pre_init ()
+Preinit_Modified_font_metric::Preinit_Modified_font_metric ()
{
orig_ = 0;
}
return scm_is_true (scm_c_memq (k, ifs));
}
-void
-Music::pre_init ()
+Preinit_Music::Preinit_Music ()
{
length_callback_ = SCM_EOL;
start_callback_ = SCM_EOL;
return otf->self_scm ();
}
-void
-Open_type_font::pre_init ()
+Preinit_Open_type_font::Preinit_Open_type_font ()
{
lily_character_table_ = SCM_EOL;
lily_global_table_ = SCM_EOL;
#if HAVE_PANGO_FT2
#include "stencil.hh"
-void
-Pango_font::pre_init ()
+Preinit_Pango_font::Preinit_Pango_font ()
{
physical_font_tab_ = SCM_EOL;
}
#include "scm-hash.hh"
-void
-Scheme_engraver::pre_init ()
+Preinit_Scheme_engraver::Preinit_Scheme_engraver ()
{
initialize_function_ = SCM_EOL;
finalize_function_ = SCM_EOL;
interface_acknowledger_hash_.set (SCM_EOL, SCM_EOL);
- must_be_last_ = false;
per_instance_listeners_ = SCM_EOL;
for (int i = 0; i < TRANSLATOR_METHOD_PRECOMPUTE_COUNT; i++)
precomputable_methods_[i] = SCM_UNDEFINED;
Pointer_group_interface::add_grob (i, ly_symbol2scm ("bounded-by-me"), this);
}
-void
-Spanner::pre_init ()
+Preinit_Spanner::Preinit_Spanner ()
{
- break_index_ = (vsize)-1;
- // This is stupid, but derived_mark may be run before broken_into_
- // has run its constructor and has a recognizable array size.
- // So we use break_index_ == -1 as a sentinel.
spanned_drul_.set (0, 0);
pure_property_cache_ = SCM_UNDEFINED;
}