]> git.donarmstrong.com Git - lilypond.git/blob - lily/include/smobs.hh
Issue 4360: Reorganize smob initialization to make it more reliable
[lilypond.git] / lily / include / smobs.hh
1 /*
2   This file is part of LilyPond, the GNU music typesetter.
3
4   Copyright (C) 1999--2015 Han-Wen Nienhuys <hanwen@xs4all.nl>
5
6   LilyPond is free software: you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation, either version 3 of the License, or
9   (at your option) any later version.
10
11   LilyPond is distributed in the hope that it will be useful,
12   but WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   GNU General Public License for more details.
15
16   You should have received a copy of the GNU General Public License
17   along with LilyPond.  If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #ifndef SMOBS_HH
21 #define SMOBS_HH
22
23 #include "lily-guile.hh"
24 #include "warn.hh"
25 #include <string>
26
27 /*
28   Smobs are GUILEs mechanism of exporting C(++) objects to the Scheme
29   world.  They are documented in the GUILE manual.
30
31
32   In LilyPond, C++ objects can be placed under the control of GUILE's
33   type system and garbage collection mechanism by inheriting from one
34   of several Smob base classes.
35
36   There are two types of smob objects.
37
38   1. Simple smobs are intended for simple objects like numbers:
39   immutable objects that can be copied without change of meaning.
40
41   To obtain an SCM version of a simple smob, use the member function
42   SCM smobbed_copy ().
43
44   Simple smobs are created by deriving from Simple_smob<Classname>.
45
46   A simple smob is only optionally under the reign of the GUILE
47   garbage collector: its usual life time is that of a normal C++
48   object.  While a smobbed_copy () is fully under control of the
49   garbage collector and will have its mark_smob function called during
50   garbage collection, an automatic variable of this type will not have
51   mark_smob called, but rather have its memory image in the call stack
52   scanned for contained non-immediate SCM values.  Anything requiring
53   more complex mark_smob behavior is not suitable for a simple smob.
54
55   When you create a smobbed_copy, the _copy_ is fully managed by the
56   GUILE memory system.  As a corollary, multiple smobbed_copy calls
57   yield multiple GUILE objects generally not eq? to each other.
58
59   2. Complex smobs are objects that have an identity. These objects
60   carry this identity in the form of a self_scm () method, which is a
61   SCM pointer to the object itself.  Complex smobs are always under
62   control of the GUILE memory system.
63
64   The constructor for a complex smob should have 3 steps:
65
66   * initialize all SCM members to an immediate value (like SCM_EOL)
67
68   * call smobify_self ()
69
70   * initialize SCM members
71
72   For example,
73
74   Complex_smob::Complex_smob : public Smob<Complex_smob> () {
75   scm_member_ = SCM_EOL;
76   smobify_self ();
77   scm_member_ = <..what you want to store..>
78   }
79
80   after construction, the self_scm () field of a complex smob is
81   protected from Garbage Collection.  This protection should be
82   removed once the object is put into another (reachable) Scheme data
83   structure, i.e.
84
85   Complex_smob *p = new Complex_smob;
86   list = scm_cons (p->self_scm (), list);
87   p->unprotect ();
88
89   Since unprotect returns the SCM object itself, this particular case
90   can be written as
91
92   Complex_smob *p = new Complex_smob;
93   list = scm_cons (p->unprotect (), list);
94
95   Complex smobs are created by deriving from Smob<Classname>.
96
97   CALLING INTERFACE
98
99   Common public methods to C++ smob objects:
100
101   - unsmob (SCM x) - unpacks X and returns pointer to the C++ object,
102     or 0 if it has the wrong type.  This can be used as a boolean
103     condition at C++ level.
104   - smob_p (SCM x) returns #t or #f at Scheme level.
105
106   IMPLEMENTATION
107
108   For implementating a class, the following public members can be
109   provided in the top class itself:
110
111   - SCM equal_p (SCM a, SCM b) - compare A and B. Returns a Scheme
112     boolean.  If the class does not define this function, equal? will
113     be equivalent to eq?.  The function will only be called when both
114     objects are of the respective type and not eq? to each other.
115
116   - mark_smob () function, that calls scm_gc_mark () on all Scheme
117     objects in the class.  If the class does not define this function,
118     it must not contain non-immediate Scheme values.
119
120   - a print_smob () function, that displays a representation for
121     debugging purposes.  If the class does not define this function,
122     the output will be #<Classname> when printing.
123
124   - a static const type_p_name_[] string set to something like
125     "ly:grob?".  When provided, an accordingly named function for
126     checking for the given smob type will be available in Scheme.
127
128 */
129
130 template <class Super>
131 class Smob_base
132 {
133   static scm_t_bits smob_tag_;
134   static scm_t_bits init_id (void);
135   static string smob_name_;
136   static Super *unchecked_unsmob (SCM s)
137   {
138     return reinterpret_cast<Super *> (SCM_SMOB_DATA (s));
139   }
140 protected:
141   // This is an initialization with side effect.  It is called once,
142   // the first time smob_tag is actually getting called.  This
143   // allocates and initializes the type before it is first used for
144   // anything.
145   static scm_t_bits smob_tag ()
146   {
147     static scm_t_bits tag = init_id ();
148     return tag;
149   }
150   Smob_base () { }
151   static SCM register_ptr (Super *p);
152   static Super *unregister_ptr (SCM obj);
153 private:
154   // Those fallbacks are _only_ for internal use by Smob_base.  They
155   // are characterized by no knowledge about the implemented type
156   // apart from the type's name.  Overriding them as a template
157   // specialization is _not_ intended since a type-dependent
158   // implementation will in general need access to possibly private
159   // parts of the Super class.  So any class-dependent override should
160   // be done by redefining the respective function in the Super class
161   // (where it will mask the private template member) rather than
162   // specializing a different template function/pointer.
163   //
164   // Most default functions are do-nothings.  void init() will
165   // recognize their address when not overriden and will then refrain
166   // altogether from passing the the respective callbacks to GUILE.
167   SCM mark_smob (void);
168   static SCM mark_trampoline (SCM); // Used for calling mark_smob
169   static size_t free_smob (SCM obj);
170   static SCM equal_p (SCM, SCM);
171   int print_smob (SCM, scm_print_state *);
172   static int print_trampoline (SCM, SCM, scm_print_state *);
173
174   // type_p_name_ can be overriden in the Super class with a static
175   // const char [] string.  This requires both a declaration in the
176   // class as well as a single instantiation outside.  Using a
177   // template specialization for supplying a different string name
178   // right in Smob_base<Super> itself seems tempting, but the C++
179   // rules would then require a specialization declaration at the
180   // class definition site as well as a specialization instantiation
181   // in a single compilation unit.  That requires just as much source
182   // code maintenance while being harder to understand and quite
183   // trickier in its failure symptoms when things go wrong.  So we
184   // just use a static zero as "not here" indication.
185   static const int type_p_name_ = 0;
186
187   // LY_DECLARE_SMOB_PROC is used in the Super class definition for
188   // making a smob callable like a function.  Declaration has to be
189   // public.  It may be either be completed with a semicolon in which
190   // case a definition of the member function smob_proc has to be done
191   // outside of the class body, or the semicolon is left off and an
192   // inline function body is added immediately below.  It would be
193   // nice if this were a non-static member function but it would seem
194   // tricky to do the required trampolining for unsmobbing the first
195   // argument of the callback and using it as a this pointer.
196 #define LY_DECLARE_SMOB_PROC(REQ, OPT, VAR, ARGLIST)                    \
197   static const int smob_proc_signature_ = ((REQ)<<8)|((OPT)<<4)|(VAR);  \
198   static SCM smob_proc ARGLIST
199
200   // a separate LY_DEFINE_SMOB_PROC seems sort of pointless as it
201   // would just result in SCM CLASS::smob_proc ARGLIST
202   //
203   // The default case without function functionality is recognized by
204   // smob_proc_signature being -1.
205   static const int smob_proc = 0;
206   static const int smob_proc_signature_ = -1;
207
208 public:
209   static void init (void)
210   {
211     // This is stupid, but without forcing initialization at the
212     // Scheme startup hook stage, stuff like ly:undead? will not be
213     // defined when the first Scheme files are loaded.
214     //
215     // So we provide an explicit initialization routine that can be
216     // used with ADD_SCM_INIT_FUNC
217     (void) smob_tag ();
218   }
219 #define ADD_SMOB_INIT(type) ADD_SCM_INIT_FUNC (Smob_init_ ## type, Smob_base<type>::init)
220   static bool is_smob (SCM s)
221   {
222     return SCM_SMOB_PREDICATE (smob_tag (), s);
223   }
224   static SCM smob_p (SCM s)
225   {
226     return is_smob (s) ? SCM_BOOL_T : SCM_BOOL_F;
227   }
228   static Super *unsmob (SCM s)
229   {
230     return is_smob (s) ? Super::unchecked_unsmob (s) : 0;
231   }
232 };
233
234 // Simple smobs
235 template <class Super>
236 class Simple_smob : public Smob_base<Super> {
237 public:
238   static size_t free_smob (SCM obj)
239   {
240     delete Smob_base<Super>::unregister_ptr (obj);
241     return 0;
242   }
243   SCM smobbed_copy () const
244   {
245     Super *p = new Super(*static_cast<const Super *> (this));
246     return Smob_base<Super>::register_ptr (p);
247   }
248 };
249
250 void protect_smob (SCM smob, SCM *prot_cons);
251 void unprotect_smob (SCM smob, SCM *prot_cons);
252
253 template <class Super>
254 class Smob : public Smob_base<Super> {
255 private:
256   SCM self_scm_;
257   SCM protection_cons_;
258   Smob (const Smob<Super> &); // Do not define!  Not copyable!
259 protected:
260   Smob () : self_scm_ (SCM_UNDEFINED), protection_cons_ (SCM_EOL) { };
261 public:
262   static size_t free_smob (SCM obj)
263   {
264     delete Smob_base<Super>::unregister_ptr (obj);
265     return 0;
266   }
267   SCM unprotected_smobify_self ()
268   {
269     SCM s = Smob_base<Super>::register_ptr (static_cast<Super *> (this));
270     self_scm_ = s;
271     return s;
272   }
273   void protect ()
274   {
275     protect_smob (self_scm_, &protection_cons_);
276   }
277   void smobify_self () {
278     protect_smob (unprotected_smobify_self (), &protection_cons_);
279   }
280   SCM unprotect ()
281   {
282     SCM s = self_scm_;
283     unprotect_smob (s, &protection_cons_);
284     return s;
285   }
286   SCM self_scm () const { return self_scm_; }
287 };
288
289 extern bool parsed_objects_should_be_dead;
290 class parsed_dead
291 {
292   static vector<parsed_dead *> elements;
293   SCM data;
294   SCM readout_one ()
295   {
296     SCM res = data;
297     data = SCM_UNDEFINED;
298     return res;
299   }
300 public:
301   parsed_dead () : data (SCM_UNDEFINED)
302   {
303     elements.push_back (this);
304   }
305   void checkin (SCM arg) { data = arg; }
306   static SCM readout ();
307 };
308
309 // This does not appear to work with GUILEv2's garbage collector:
310 // Objects are found in the GC phase but printing them will crash at
311 // least some, so they are apparently not protected in spite of being
312 // included in the GC scans.  So it would appear that scanning smobs
313 // is not equivalent to marking them.  Ugh.
314 #if !defined(NDEBUG) && !GUILEV2
315 #define ASSERT_LIVE_IS_ALLOWED(arg)                                     \
316   do {                                                                  \
317     static parsed_dead pass_here;                                       \
318     if (parsed_objects_should_be_dead)                                  \
319       pass_here.checkin (arg);                                          \
320   } while (0)
321 #else
322 #define ASSERT_LIVE_IS_ALLOWED(arg) do { (void)(arg); }  \
323   while (0)
324 #endif
325
326 #include "smobs.tcc"
327 #endif /* SMOBS_HH */