From bdd3c11a19d87999eeaff2c82f21c6938d1d9342 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Thu, 2 Aug 2018 00:38:46 -0700 Subject: [PATCH] Internal templatization of lazy-loaders --- src/hb-machinery-private.hh | 74 ++++++++++++++++--------------------- 1 file changed, 32 insertions(+), 42 deletions(-) diff --git a/src/hb-machinery-private.hh b/src/hb-machinery-private.hh index 6328fb007..dbabeaddc 100644 --- a/src/hb-machinery-private.hh +++ b/src/hb-machinery-private.hh @@ -590,38 +590,54 @@ struct BEInt * Lazy struct and blob loaders. */ -/* Logic is shared between hb_lazy_loader_t and hb_table_lazy_loader_t. - * I mean, yeah, only every method is different. */ -template -struct hb_lazy_loader_t +template +struct hb_base_lazy_loader_t { + /* https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern */ + inline const Subclass* thiz (void) const { return static_cast (this); } + inline void init (hb_face_t *face_) { face = face_; instance = nullptr; } + inline const Returned * operator-> (void) const + { + return thiz ()->get (); + } + + protected: + hb_face_t *face; + mutable Stored *instance; +}; + +template +struct hb_lazy_loader_t : hb_base_lazy_loader_t, T> +{ inline void fini (void) { - if (instance && instance != &Null(T)) + if (this->instance && this->instance != &Null(T)) { - instance->fini(); - free (instance); + this->instance->fini(); + free (this->instance); } } inline const T* get (void) const { retry: - T *p = (T *) hb_atomic_ptr_get (&instance); + T *p = (T *) hb_atomic_ptr_get (&this->instance); if (unlikely (!p)) { p = (T *) calloc (1, sizeof (T)); if (unlikely (!p)) p = const_cast (&Null(T)); else - p->init (face); - if (unlikely (!hb_atomic_ptr_cmpexch (const_cast(&instance), nullptr, p))) + p->init (this->face); + if (unlikely (!hb_atomic_ptr_cmpexch (const_cast(&this->instance), nullptr, p))) { if (p != &Null(T)) p->fini (); @@ -630,46 +646,29 @@ struct hb_lazy_loader_t } return p; } - - inline const T* operator-> (void) const - { - return get (); - } - - private: - hb_face_t *face; - mutable T *instance; }; -/* Logic is shared between hb_lazy_loader_t and hb_table_lazy_loader_t. - * I mean, yeah, only every method is different. */ template -struct hb_table_lazy_loader_t +struct hb_table_lazy_loader_t : hb_base_lazy_loader_t, T, hb_blob_t> { - inline void init (hb_face_t *face_) - { - face = face_; - blob = nullptr; - } - inline void fini (void) { - hb_blob_destroy (blob); + hb_blob_destroy (this->instance); } inline hb_blob_t* get_blob (void) const { retry: - hb_blob_t *b = (hb_blob_t *) hb_atomic_ptr_get (&blob); + hb_blob_t *b = (hb_blob_t *) hb_atomic_ptr_get (&this->instance); if (unlikely (!b)) { - b = hb_sanitize_context_t ().reference_table (face); - if (!hb_atomic_ptr_cmpexch (&blob, nullptr, b)) + b = hb_sanitize_context_t ().reference_table (this->face); + if (!hb_atomic_ptr_cmpexch (&this->instance, nullptr, b)) { hb_blob_destroy (b); goto retry; } - blob = b; + this->instance = b; } return b; } @@ -679,15 +678,6 @@ struct hb_table_lazy_loader_t hb_blob_t *b = get_blob (); return b->as (); } - - inline const T* operator-> (void) const - { - return get(); - } - - private: - hb_face_t *face; - mutable hb_blob_t *blob; };