]> git.donarmstrong.com Git - lilypond.git/commitdiff
Issue 5024: Rework the Preinit framework into something simpler
authorDavid Kastrup <dak@gnu.org>
Sun, 1 Jan 2017 09:14:14 +0000 (10:14 +0100)
committerDavid Kastrup <dak@gnu.org>
Sun, 8 Jan 2017 15:17:59 +0000 (16:17 +0100)
The previous introduction of the Preinit class had to work with
uninitialized data members in a state before construction.

Particularly for data structures like vector classes, this
was quite awkward.  Moving such structures into a separate
class initialized before the smobifying base class fixes
this deficiency and makes the behavior much more reliable,
at the cost of making the class hierarchy a bit more nested.

17 files changed:
lily/engraver-group.cc
lily/global-context.cc
lily/include/engraver-group.hh
lily/include/global-context.hh
lily/include/modified-font-metric.hh
lily/include/music.hh
lily/include/open-type-font.hh
lily/include/pango-font.hh
lily/include/scheme-engraver.hh
lily/include/smobs.hh
lily/include/spanner.hh
lily/modified-font-metric.cc
lily/music.cc
lily/open-type-font.cc
lily/pango-font.cc
lily/scheme-engraver.cc
lily/spanner.cc

index 51af2d4afaac2f665bc29279d6c65601dc29d687..c431d10ae13cd35e83e6130e1e8bf09a4ac6a405 100644 (file)
@@ -204,8 +204,7 @@ Engraver_group::do_announces ()
   while (pending_grobs ());
 }
 
-void
-Engraver_group::pre_init ()
+Preinit_Engraver_group::Preinit_Engraver_group ()
 {
   acknowledge_hash_table_drul_.set (SCM_EOL, SCM_EOL);
 }
index 47e76718db2bd13e6e1c9236bf27df5ab10ef173..be523665b921911b0ffdffeef28cb675d2343c8d 100644 (file)
@@ -30,8 +30,7 @@ using namespace std;
 #include "output-def.hh"
 #include "warn.hh"
 
-void
-Global_context::pre_init ()
+Preinit_Global_context::Preinit_Global_context ()
 {
   output_def_ = 0;
 }
index 367b6a8f4cd244772c691d4d6e9dc762356a2474..6bdb9143140781683eee398792a0f33aeaf3b06e 100644 (file)
@@ -33,16 +33,20 @@ public:
   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 ();
index fd6f1f92c010c578c03286da4f30e8e3b7951234..e0aca0a7d6cc35aeea203bb3c524e985eedd80ba 100644 (file)
 #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);
index 66996eaf06c226ded5522198767987813055efe0..0f4223d4ba90779d781a1720f886c55b273bd326 100644 (file)
 
 #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:
@@ -37,10 +43,8 @@ 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);
index 32ca55babcdfaa9deff2d17706728d0f8e529961..af672a38d161915190f57cb97f15c476b9cd7184 100644 (file)
 
 #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);
@@ -62,8 +67,6 @@ protected:
   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);
 };
 
index bf66d669813c7917baf23c204034b6c0014bd8f1..76d015325591ab602900aa356146fb0cf4d8431c 100644 (file)
@@ -26,23 +26,25 @@ Index_to_charcode_map make_index_to_charcode_map (FT_Face face);
 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;
index 2a3367705b8ee2c4f51008d16b7752e99ac61d56..aaae077b769d01bd257e1e96414581a6ea147dd4 100644 (file)
 
 #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);
index 2eb2f30379d9b339833a65608b1b351f4311c250..11caf9f9c283861eff90d4a93c2eddaf6257f9ba 100644 (file)
 
 #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:
@@ -53,16 +65,6 @@ private:
   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 */
index 0d446102e19b0b042b5fac463f206427777898ea..00217866dc07dc92eff400e23050d50b46f67a3b 100644 (file)
 
   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:
@@ -320,32 +344,6 @@ public:
   }
 };
 
-// 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
 {
index bc41ec6e639155fdc08ce05a9ed443551e0182c5..a5ecd3dae92c451a259a45b2fa92f2702d63c651 100644 (file)
     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);
@@ -66,7 +73,6 @@ public:
   void set_bound (Direction d, Grob *);
   Item *get_bound (Direction d) const;
 
-  void pre_init ();
   Spanner (SCM);
   Spanner (Spanner const &);
   bool is_broken () const;
@@ -83,8 +89,6 @@ public:
   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 ();
index a93b3f4d97a4a415acc8a469453c1b7baefc9d73..d68db92c4b897b6728ee0d37fec25410360a2f6e 100644 (file)
@@ -26,7 +26,7 @@ using namespace std;
 #include "main.hh"
 #include "program-option.hh"
 
-void Modified_font_metric::pre_init ()
+Preinit_Modified_font_metric::Preinit_Modified_font_metric ()
 {
   orig_ = 0;
 }
index 994d685ed2582e921bdd4519a0cf027b4d1c4099..8b9da5596d02d5d217c397bd2b47b9b1be5c346d 100644 (file)
@@ -45,8 +45,7 @@ Music::internal_is_music_type (SCM k) const
   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;
index 73ef069c4fea6816bbbd236cefff664ae9523af0..730d6cef3580cef522f924b503b4ee9c51f85d55 100644 (file)
@@ -251,8 +251,7 @@ Open_type_font::make_otf (const string &str)
   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;
index 798d258338787a6497fb180f9c0bf4ea3243eb30..9fe6b78cb00a54a78273b5820c5bfe672ea10136 100644 (file)
@@ -46,8 +46,7 @@
 #if HAVE_PANGO_FT2
 #include "stencil.hh"
 
-void
-Pango_font::pre_init ()
+Preinit_Pango_font::Preinit_Pango_font ()
 {
   physical_font_tab_ = SCM_EOL;
 }
index 54d96208229152c03ce29fc3616dd4f4fe109eea..d0abfb1bd062f73a7330147b406e5d0cc2fed12a 100644 (file)
 
 #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;
index 1b6798086a3244558555a7cd1fa98059e15e834d..f3593cbbf534d8774a57abdd1158960384c63aad 100644 (file)
@@ -224,13 +224,8 @@ Spanner::set_bound (Direction d, Grob *s)
     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;
 }