From 90d3233da87b372e02690978f89b2add3863fba6 Mon Sep 17 00:00:00 2001 From: David Kastrup Date: Thu, 30 Apr 2015 20:48:09 +0200 Subject: [PATCH] Issue 4360: Reorganize smob initialization to make it more reliable This change is a nuisance in that it requires an explicit call to ADD_SMOB_INIT for each Scheme-related class. However, this setup guarantees that at the point Scheme execution commences, all predicates of the likes of "ly:grob?" will be present. It also guarantees that if a particular type should seem required during _other_ initializations that happen to depend on the type and get executed earlier, it will be provided early. --- lily/book.cc | 1 + lily/box.cc | 2 ++ lily/context-def.cc | 2 ++ lily/context-mod.cc | 2 ++ lily/context-property.cc | 2 ++ lily/context.cc | 2 ++ lily/dispatcher.cc | 2 ++ lily/duration.cc | 2 ++ lily/font-metric.cc | 1 + lily/grob-array.cc | 1 + lily/grob.cc | 1 + lily/include/smobs.hh | 42 ++++++++++++++++---------------- lily/include/smobs.tcc | 22 ++++++----------- lily/input-smob.cc | 2 ++ lily/lily-lexer.cc | 2 ++ lily/lily-parser.cc | 1 + lily/listener.cc | 2 ++ lily/moment.cc | 2 ++ lily/music-function.cc | 2 ++ lily/music-iterator.cc | 1 + lily/music-output.cc | 1 + lily/output-def.cc | 2 ++ lily/page-marker.cc | 2 ++ lily/paper-book.cc | 1 + lily/paper-outputter.cc | 1 + lily/pitch.cc | 2 ++ lily/prob.cc | 1 + lily/scale.cc | 1 + lily/scheme-listener.cc | 2 ++ lily/scm-hash.cc | 2 ++ lily/score.cc | 2 ++ lily/simple-closure.cc | 2 ++ lily/simple-spacer.cc | 2 ++ lily/skyline-pair.cc | 2 ++ lily/skyline.cc | 2 ++ lily/source-file.cc | 2 ++ lily/spring.cc | 2 ++ lily/stencil.cc | 1 + lily/translator-dispatch-list.cc | 1 + lily/translator-group.cc | 2 ++ lily/translator.cc | 2 ++ lily/undead.cc | 2 ++ 42 files changed, 96 insertions(+), 35 deletions(-) diff --git a/lily/book.cc b/lily/book.cc index 8e63d889e0..e76963eaf3 100644 --- a/lily/book.cc +++ b/lily/book.cc @@ -33,6 +33,7 @@ using namespace std; #include "paper-score.hh" #include "page-marker.hh" +ADD_SMOB_INIT (Book); Book::Book () { diff --git a/lily/box.cc b/lily/box.cc index 629b8010fa..050824a25a 100644 --- a/lily/box.cc +++ b/lily/box.cc @@ -19,6 +19,8 @@ #include "box.hh" +ADD_SMOB_INIT (Box); + void Box::translate (Offset o) { diff --git a/lily/context-def.cc b/lily/context-def.cc index 10f31ae830..b2aaedf44a 100644 --- a/lily/context-def.cc +++ b/lily/context-def.cc @@ -29,6 +29,8 @@ #include "translator.hh" #include "warn.hh" +ADD_SMOB_INIT (Context_def); + Context_def::Context_def () { context_aliases_ = SCM_EOL; diff --git a/lily/context-mod.cc b/lily/context-mod.cc index fd2a25d2fe..b9c43fe76a 100644 --- a/lily/context-mod.cc +++ b/lily/context-mod.cc @@ -19,6 +19,8 @@ #include "context-mod.hh" +ADD_SMOB_INIT (Context_mod); + Context_mod::Context_mod () { mods_ = SCM_EOL; diff --git a/lily/context-property.cc b/lily/context-property.cc index 59bcf9afc6..7a605352fd 100644 --- a/lily/context-property.cc +++ b/lily/context-property.cc @@ -94,6 +94,8 @@ private: cooked_ (alist), cooked_from_ (alist), nested_ (0) { } }; +ADD_SMOB_INIT (Grob_properties); + const char Grob_properties::type_p_name_[] = "ly:grob-properties?"; SCM diff --git a/lily/context.cc b/lily/context.cc index 9dad38f269..1d8efed630 100644 --- a/lily/context.cc +++ b/lily/context.cc @@ -31,6 +31,8 @@ #include "translator-group.hh" #include "warn.hh" +ADD_SMOB_INIT (Context); + bool Context::is_removable () const { diff --git a/lily/dispatcher.cc b/lily/dispatcher.cc index efb3ca506c..b76e76c35c 100644 --- a/lily/dispatcher.cc +++ b/lily/dispatcher.cc @@ -22,6 +22,8 @@ #include "international.hh" #include "warn.hh" +ADD_SMOB_INIT (Dispatcher); + const char Dispatcher::type_p_name_[] = "ly:dispatcher?"; Dispatcher::~Dispatcher () diff --git a/lily/duration.cc b/lily/duration.cc index 4768f015b5..78ae045a88 100644 --- a/lily/duration.cc +++ b/lily/duration.cc @@ -20,6 +20,8 @@ #include "duration.hh" +ADD_SMOB_INIT (Duration); + #include "misc.hh" #include "lily-proto.hh" diff --git a/lily/font-metric.cc b/lily/font-metric.cc index f18b2d7256..be071fe912 100644 --- a/lily/font-metric.cc +++ b/lily/font-metric.cc @@ -29,6 +29,7 @@ using namespace std; #include "stencil.hh" #include "warn.hh" +ADD_SMOB_INIT (Font_metric); Real Font_metric::design_size () const diff --git a/lily/grob-array.cc b/lily/grob-array.cc index 2747e0d77f..f267ce5a44 100644 --- a/lily/grob-array.cc +++ b/lily/grob-array.cc @@ -21,6 +21,7 @@ #include "item.hh" #include "spanner.hh" +ADD_SMOB_INIT (Grob_array); Item * Grob_array::item (vsize i) diff --git a/lily/grob.cc b/lily/grob.cc index 435a6faff3..8cfb14d539 100644 --- a/lily/grob.cc +++ b/lily/grob.cc @@ -39,6 +39,7 @@ #include "unpure-pure-container.hh" #include "warn.hh" +ADD_SMOB_INIT (Grob); Grob * Grob::clone () const diff --git a/lily/include/smobs.hh b/lily/include/smobs.hh index 3ee2ef80ab..eeb385e1a2 100644 --- a/lily/include/smobs.hh +++ b/lily/include/smobs.hh @@ -127,37 +127,26 @@ */ -// Initialization class. Create a variable or static data member of -// this type at global scope (or creation will happen too late for -// Scheme initialization), initialising with a function to be called. -// Reference somewhere (like in the constructor of the containing -// class) to make sure the variable is actually instantiated. - -class Scm_init { -public: - Scm_init () { } - Scm_init (void (*fun) (void)) - { - add_scm_init_func (fun); - } -}; - template class Smob_base { static scm_t_bits smob_tag_; - static Scm_init scm_init_; - static void init (void); + static scm_t_bits init_id (void); static string smob_name_; static Super *unchecked_unsmob (SCM s) { return reinterpret_cast (SCM_SMOB_DATA (s)); } protected: - // reference scm_init_ in smob_tag which is sure to be called. The - // constructor, in contrast, may not be called at all in classes - // like Smob1. - static scm_t_bits smob_tag () { (void) scm_init_; return smob_tag_; } + // This is an initialization with side effect. It is called once, + // the first time smob_tag is actually getting called. This + // allocates and initializes the type before it is first used for + // anything. + static scm_t_bits smob_tag () + { + static scm_t_bits tag = init_id (); + return tag; + } Smob_base () { } static SCM register_ptr (Super *p); static Super *unregister_ptr (SCM obj); @@ -217,6 +206,17 @@ private: static const int smob_proc_signature_ = -1; public: + static void init (void) + { + // This is stupid, but without forcing initialization at the + // Scheme startup hook stage, stuff like ly:undead? will not be + // defined when the first Scheme files are loaded. + // + // So we provide an explicit initialization routine that can be + // used with ADD_SCM_INIT_FUNC + (void) smob_tag (); + } +#define ADD_SMOB_INIT(type) ADD_SCM_INIT_FUNC (Smob_init_ ## type, Smob_base::init) static bool is_smob (SCM s) { return SCM_SMOB_PREDICATE (smob_tag (), s); diff --git a/lily/include/smobs.tcc b/lily/include/smobs.tcc index b4dacacaa3..097047e32b 100644 --- a/lily/include/smobs.tcc +++ b/lily/include/smobs.tcc @@ -106,17 +106,11 @@ Smob_base::unregister_ptr (SCM obj) return p; } -template -scm_t_bits Smob_base::smob_tag_ = 0; - -template -Scm_init Smob_base::scm_init_ = init; - template string Smob_base::smob_name_; template -void Smob_base::init () +scm_t_bits Smob_base::init_id () { smob_name_ = typeid (Super).name (); // Primitive demangling, suitable for GCC, should be harmless @@ -124,8 +118,7 @@ void Smob_base::init () // unsuitable for Texinfo documentation. If that proves to be an // issue, we need some smarter strategy. smob_name_ = smob_name_.substr (smob_name_.find_first_not_of ("0123456789")); - assert(!smob_tag_); - smob_tag_ = scm_make_smob_type (smob_name_.c_str (), 0); + scm_t_bits smob_tag = scm_make_smob_type (smob_name_.c_str (), 0); // The following have trivial private default definitions not // referring to any aspect of the Super class apart from its name. // They should be overridden (or rather masked) at Super level: that @@ -134,7 +127,7 @@ void Smob_base::init () // doing it like the rest. if (&Super::free_smob != &Smob_base::free_smob) - scm_set_smob_free (smob_tag_, Super::free_smob); + scm_set_smob_free (smob_tag, Super::free_smob); // Old GCC versions get their type lattice for pointers-to-members // tangled up to a degree where we need to typecast _both_ covariant // types in order to be able to compare them. The other comparisons @@ -142,10 +135,10 @@ void Smob_base::init () // pointers which work without those contortions. if (static_cast(&Super::mark_smob) != static_cast(&Smob_base::mark_smob)) - scm_set_smob_mark (smob_tag_, Super::mark_trampoline); - scm_set_smob_print (smob_tag_, Super::print_trampoline); + scm_set_smob_mark (smob_tag, Super::mark_trampoline); + scm_set_smob_print (smob_tag, Super::print_trampoline); if (&Super::equal_p != &Smob_base::equal_p) - scm_set_smob_equalp (smob_tag_, Super::equal_p); + scm_set_smob_equalp (smob_tag, Super::equal_p); if (Super::type_p_name_ != 0) { SCM subr = scm_c_define_gsubr (Super::type_p_name_, 1, 0, 0, @@ -158,10 +151,11 @@ void Smob_base::init () } ly_add_type_predicate ((void *) is_smob, smob_name_.c_str ()); if (Super::smob_proc_signature_ >= 0) - scm_set_smob_apply (smob_tag_, + scm_set_smob_apply (smob_tag, (scm_t_subr)Super::smob_proc, Super::smob_proc_signature_ >> 8, (Super::smob_proc_signature_ >> 4)&0xf, Super::smob_proc_signature_ & 0xf); + return smob_tag; } #endif diff --git a/lily/input-smob.cc b/lily/input-smob.cc index 0a33bd6a59..f6a3b7a773 100644 --- a/lily/input-smob.cc +++ b/lily/input-smob.cc @@ -21,6 +21,8 @@ #include "source-file.hh" #include "std-string.hh" +ADD_SMOB_INIT (Input); + /* Dummy input location for use if real one is missing. */ Input dummy_input_global; diff --git a/lily/lily-lexer.cc b/lily/lily-lexer.cc index 3bb7921b2b..7785ede296 100644 --- a/lily/lily-lexer.cc +++ b/lily/lily-lexer.cc @@ -36,6 +36,8 @@ using namespace std; #include "program-option.hh" #include "lily-parser.hh" +ADD_SMOB_INIT (Lily_lexer); + static Keyword_ent the_key_tab[] = { diff --git a/lily/lily-parser.cc b/lily/lily-parser.cc index 2d006f8d78..4bba3e445b 100644 --- a/lily/lily-parser.cc +++ b/lily/lily-parser.cc @@ -37,6 +37,7 @@ #include "warn.hh" #include "program-option.hh" +ADD_SMOB_INIT (Lily_parser); Lily_parser::Lily_parser (Sources *sources) { diff --git a/lily/listener.cc b/lily/listener.cc index 50f1969ecb..4194c83618 100644 --- a/lily/listener.cc +++ b/lily/listener.cc @@ -20,6 +20,8 @@ #include "listener.hh" #include "warn.hh" +ADD_SMOB_INIT (Listener); + Listener::Listener () { target_ = 0; diff --git a/lily/moment.cc b/lily/moment.cc index 9f3e8ed383..cd82c8a597 100644 --- a/lily/moment.cc +++ b/lily/moment.cc @@ -21,6 +21,8 @@ #include "warn.hh" +ADD_SMOB_INIT (Moment); + Moment::Moment () { } diff --git a/lily/music-function.cc b/lily/music-function.cc index 35341e3c6d..a20af4d0a2 100644 --- a/lily/music-function.cc +++ b/lily/music-function.cc @@ -19,6 +19,8 @@ #include "music-function.hh" +ADD_SMOB_INIT (Music_function); + const char Music_function::type_p_name_[] = "ly:music-function?"; /* Print a textual represenation of the smob to a given port. */ diff --git a/lily/music-iterator.cc b/lily/music-iterator.cc index 8eb238c295..ed778323b9 100644 --- a/lily/music-iterator.cc +++ b/lily/music-iterator.cc @@ -30,6 +30,7 @@ using namespace std; #include "music-wrapper-iterator.hh" #include "simple-music-iterator.hh" +ADD_SMOB_INIT (Music_iterator); Music_iterator::Music_iterator () { diff --git a/lily/music-output.cc b/lily/music-output.cc index 0907bf38f4..8e03177bf4 100644 --- a/lily/music-output.cc +++ b/lily/music-output.cc @@ -19,6 +19,7 @@ #include "music-output.hh" +ADD_SMOB_INIT (Music_output); Music_output::Music_output () { diff --git a/lily/output-def.cc b/lily/output-def.cc index af407fb70a..525ccd975e 100644 --- a/lily/output-def.cc +++ b/lily/output-def.cc @@ -34,6 +34,8 @@ #include "string-convert.hh" +ADD_SMOB_INIT (Output_def); + Output_def::Output_def () { scope_ = SCM_EOL; diff --git a/lily/page-marker.cc b/lily/page-marker.cc index 1e393862e6..88eb975304 100644 --- a/lily/page-marker.cc +++ b/lily/page-marker.cc @@ -19,6 +19,8 @@ #include "page-marker.hh" +ADD_SMOB_INIT (Page_marker); + Page_marker::Page_marker () { symbol_ = SCM_EOL; diff --git a/lily/paper-book.cc b/lily/paper-book.cc index 7dce3a9507..00917966e5 100644 --- a/lily/paper-book.cc +++ b/lily/paper-book.cc @@ -31,6 +31,7 @@ #include "program-option.hh" #include "page-marker.hh" +ADD_SMOB_INIT (Paper_book); Paper_book::Paper_book () { diff --git a/lily/paper-outputter.cc b/lily/paper-outputter.cc index 269e1e294c..e8f1d821aa 100644 --- a/lily/paper-outputter.cc +++ b/lily/paper-outputter.cc @@ -38,6 +38,7 @@ using namespace std; #include "string-convert.hh" #include "warn.hh" +ADD_SMOB_INIT (Paper_outputter); Paper_outputter::Paper_outputter (SCM port, const string &format) { diff --git a/lily/pitch.cc b/lily/pitch.cc index 0fd7512947..4c5cb79e37 100644 --- a/lily/pitch.cc +++ b/lily/pitch.cc @@ -26,6 +26,8 @@ #include +ADD_SMOB_INIT (Pitch); + Pitch::Pitch (int o, int n, Rational a) { notename_ = n; diff --git a/lily/prob.cc b/lily/prob.cc index 37dad6246b..57f6b2f4d5 100644 --- a/lily/prob.cc +++ b/lily/prob.cc @@ -23,6 +23,7 @@ #include "input.hh" #include "profile.hh" +ADD_SMOB_INIT (Prob); const char Prob::type_p_name_[] = "ly:prob?"; diff --git a/lily/scale.cc b/lily/scale.cc index a5afd41dae..57406f0af0 100644 --- a/lily/scale.cc +++ b/lily/scale.cc @@ -21,6 +21,7 @@ #include "scale.hh" +ADD_SMOB_INIT (Scale); /* todo: put string <-> pitch here too. diff --git a/lily/scheme-listener.cc b/lily/scheme-listener.cc index 9df6960bdf..8a9e175f5c 100644 --- a/lily/scheme-listener.cc +++ b/lily/scheme-listener.cc @@ -19,6 +19,8 @@ #include "scheme-listener.hh" +ADD_SMOB_INIT (Scheme_listener); + IMPLEMENT_LISTENER (Scheme_listener, call) void Scheme_listener::call (SCM ev) diff --git a/lily/scm-hash.cc b/lily/scm-hash.cc index 5eb048f6d1..c5a8959548 100644 --- a/lily/scm-hash.cc +++ b/lily/scm-hash.cc @@ -23,6 +23,8 @@ #include using namespace std; +ADD_SMOB_INIT (Scheme_hash_table); + /* Return: number of objects. diff --git a/lily/score.cc b/lily/score.cc index 5ce7e3ba95..9210766c77 100644 --- a/lily/score.cc +++ b/lily/score.cc @@ -19,6 +19,8 @@ #include "score.hh" +ADD_SMOB_INIT (Score); + #include using namespace std; diff --git a/lily/simple-closure.cc b/lily/simple-closure.cc index b62649f06d..0ef57ded6e 100644 --- a/lily/simple-closure.cc +++ b/lily/simple-closure.cc @@ -22,6 +22,8 @@ #include "grob.hh" +ADD_SMOB_INIT (Simple_closure); + SCM evaluate_args (SCM delayed_argument, SCM args, bool pure, int start, int end) { diff --git a/lily/simple-spacer.cc b/lily/simple-spacer.cc index ada16593aa..ce587c5fdd 100644 --- a/lily/simple-spacer.cc +++ b/lily/simple-spacer.cc @@ -32,6 +32,8 @@ #include "spring.hh" #include "warn.hh" +ADD_SMOB_INIT (Simple_spacer); + /* A simple spacing constraint solver. The approach: diff --git a/lily/skyline-pair.cc b/lily/skyline-pair.cc index 92ae97a342..005b9b77cf 100644 --- a/lily/skyline-pair.cc +++ b/lily/skyline-pair.cc @@ -22,6 +22,8 @@ #include "international.hh" +ADD_SMOB_INIT (Skyline_pair); + Skyline_pair::Skyline_pair () : skylines_ (Skyline (DOWN), Skyline (UP)) { diff --git a/lily/skyline.cc b/lily/skyline.cc index 42a028fe0a..ef284e7131 100644 --- a/lily/skyline.cc +++ b/lily/skyline.cc @@ -65,6 +65,8 @@ Alert to these considerations, we now accept buildings of zero-width. */ +ADD_SMOB_INIT (Skyline); + static void print_buildings (list const &b) { diff --git a/lily/source-file.cc b/lily/source-file.cc index 1118b9d286..67690289b9 100644 --- a/lily/source-file.cc +++ b/lily/source-file.cc @@ -42,6 +42,8 @@ using namespace std; #include "misc.hh" #include "warn.hh" +ADD_SMOB_INIT (Source_file); + void Source_file::load_stdin () { diff --git a/lily/spring.cc b/lily/spring.cc index d1640e72b9..3d3dfff5fb 100644 --- a/lily/spring.cc +++ b/lily/spring.cc @@ -36,6 +36,8 @@ #include "spring.hh" +ADD_SMOB_INIT (Spring); + Spring::Spring () { distance_ = 1.0; diff --git a/lily/stencil.cc b/lily/stencil.cc index 980618ceaa..b162280829 100644 --- a/lily/stencil.cc +++ b/lily/stencil.cc @@ -25,6 +25,7 @@ #include "string-convert.hh" #include "warn.hh" +ADD_SMOB_INIT (Stencil); Stencil::Stencil () { diff --git a/lily/translator-dispatch-list.cc b/lily/translator-dispatch-list.cc index ed968c571a..02de105da9 100644 --- a/lily/translator-dispatch-list.cc +++ b/lily/translator-dispatch-list.cc @@ -20,6 +20,7 @@ #include "translator-dispatch-list.hh" #include "engraver.hh" +ADD_SMOB_INIT (Engraver_dispatch_list); void Engraver_dispatch_list::apply (Grob_info gi) diff --git a/lily/translator-group.cc b/lily/translator-group.cc index 2e6039a9af..f8818462c6 100644 --- a/lily/translator-group.cc +++ b/lily/translator-group.cc @@ -35,6 +35,8 @@ #include "scm-hash.hh" #include "warn.hh" +ADD_SMOB_INIT (Translator_group); + void translator_each (SCM list, Translator_method method) { diff --git a/lily/translator.cc b/lily/translator.cc index d6874ef78c..a1053c5725 100644 --- a/lily/translator.cc +++ b/lily/translator.cc @@ -28,6 +28,8 @@ #include "translator.icc" +ADD_SMOB_INIT (Translator); + Translator::~Translator () { } diff --git a/lily/undead.cc b/lily/undead.cc index d6e3d550d1..9adc5e6fd0 100644 --- a/lily/undead.cc +++ b/lily/undead.cc @@ -32,6 +32,8 @@ public: Undead (SCM object = SCM_UNDEFINED) : object_ (object) { }; }; +ADD_SMOB_INIT (Undead); + SCM Undead::mark_smob () { -- 2.39.2