X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;ds=sidebyside;f=lily%2Finclude%2Flistener.hh;h=a13fdc66e14e141d28917e4ffa46d72494b7e740;hb=HEAD;hp=a5c0c98bdde447717d8fabe4c95f00dd8ee3bf76;hpb=6f16c7184dd33fc91b381bb659e9d2f6001f76c7;p=lilypond.git diff --git a/lily/include/listener.hh b/lily/include/listener.hh index a5c0c98bdd..a13fdc66e1 100644 --- a/lily/include/listener.hh +++ b/lily/include/listener.hh @@ -74,6 +74,7 @@ classes derived from Smob<...>. */ +#include "callback.hh" #include "smobs.hh" // A listener is essentially any procedure accepting a single argument @@ -95,20 +96,19 @@ private: SCM callback_; SCM target_; public: - static const char type_p_name_[]; + static const char * const type_p_name_; Listener (SCM callback, SCM target) : callback_ (callback), target_ (target) { } - void listen (SCM ev) const { scm_call_2 (callback_, target_, ev); } - - LY_DECLARE_SMOB_PROC (1, 0, 0, (SCM self, SCM ev)) + LY_DECLARE_SMOB_PROC (&Listener::listen, 1, 0, 0) + SCM listen (SCM ev) { - Listener::unsmob (self)->listen (ev); + scm_call_2 (callback_, target_, ev); return SCM_UNSPECIFIED; } - SCM mark_smob () + SCM mark_smob () const { scm_gc_mark (callback_); return target_; @@ -122,68 +122,21 @@ public: static SCM equal_p (SCM a, SCM b) { - return *Listener::unsmob (a) == *Listener::unsmob (b) + return *unchecked_unsmob (a) == *unchecked_unsmob (b) ? SCM_BOOL_T : SCM_BOOL_F; } -}; -// A callback wrapper creates a Scheme-callable version of a -// non-static class member function callback which you can call with a -// class instance and an event. -// -// If you have a class member function -// void T::my_listen (SCM ev) -// then Callback_wrapper::make_smob<&T::my_listen> () -// will return an SCM function roughly defined as -// (lambda (target ev) (target->my_listen ev)) -// -// The setup is slightly tricky since the make_smob quasi-constructor -// call is a template function templated on the given callback, and so -// is the trampoline it uses for redirecting the callback. The class -// itself, however, is not templated as that would create a wagonload -// of SCM types. - -class Callback_wrapper : public Simple_smob -{ - // We use an ordinary function pointer pointing to a trampoline - // function (templated on the callback in question) instead of - // storing a member function pointer to a common base class like - // Smob_core. The additional code for the trampolines is negligible - // and the performance implications of using member function - // pointers in connection with inheritance are somewhat opaque as - // this involves an adjustment of the this pointer from Smob_core to - // the scope containing the callback. - void (*trampoline_) (SCM, SCM); template - static void trampoline (SCM target, SCM ev) + static SCM trampoline (SCM target, SCM ev) { - T *t = derived_unsmob (target); - LY_ASSERT_DERIVED_SMOB (T, target, 1); + T *t = unsmob (target); + LY_ASSERT_SMOB (T, target, 1); (t->*callback) (ev); - } - - Callback_wrapper (void (*trampoline) (SCM, SCM)) : trampoline_ (trampoline) - { } // Private constructor, use only in make_smob -public: - LY_DECLARE_SMOB_PROC (2, 0, 0, (SCM self, SCM target, SCM ev)) - { - unsmob (self)->trampoline_ (target, ev); - return SCM_UNSPECIFIED; - } - // Callback wrappers are for an unchanging entity, so we do the Lisp - // creation just once on the first call of make_smob. So we only - // get a single Callback_wrapper instance for each differently - // templated make_smob call. - template - static SCM make_smob () - { - static SCM res = scm_permanent_object - (Callback_wrapper (trampoline).smobbed_copy ()); - return res; + return SCM_UNDEFINED; } }; -#define GET_LISTENER(cl, proc) get_listener (Callback_wrapper::make_smob ()) +#define GET_LISTENER(cl, proc) get_listener (Callback_wrapper::make_smob > ()) #endif /* LISTENER_HH */