Internal templatization of lazy-loaders
This commit is contained in:
parent
ed7b2e58fc
commit
bdd3c11a19
|
@ -590,38 +590,54 @@ struct BEInt<Type, 4>
|
||||||
* Lazy struct and blob loaders.
|
* Lazy struct and blob loaders.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Logic is shared between hb_lazy_loader_t and hb_table_lazy_loader_t.
|
template <typename Subclass,
|
||||||
* I mean, yeah, only every method is different. */
|
typename Returned,
|
||||||
template <typename T>
|
typename Stored = Returned>
|
||||||
struct hb_lazy_loader_t
|
struct hb_base_lazy_loader_t
|
||||||
{
|
{
|
||||||
|
/* https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern */
|
||||||
|
inline const Subclass* thiz (void) const { return static_cast<const Subclass *> (this); }
|
||||||
|
|
||||||
inline void init (hb_face_t *face_)
|
inline void init (hb_face_t *face_)
|
||||||
{
|
{
|
||||||
face = face_;
|
face = face_;
|
||||||
instance = nullptr;
|
instance = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline const Returned * operator-> (void) const
|
||||||
|
{
|
||||||
|
return thiz ()->get ();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
hb_face_t *face;
|
||||||
|
mutable Stored *instance;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct hb_lazy_loader_t : hb_base_lazy_loader_t<hb_lazy_loader_t<T>, T>
|
||||||
|
{
|
||||||
inline void fini (void)
|
inline void fini (void)
|
||||||
{
|
{
|
||||||
if (instance && instance != &Null(T))
|
if (this->instance && this->instance != &Null(T))
|
||||||
{
|
{
|
||||||
instance->fini();
|
this->instance->fini();
|
||||||
free (instance);
|
free (this->instance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const T* get (void) const
|
inline const T* get (void) const
|
||||||
{
|
{
|
||||||
retry:
|
retry:
|
||||||
T *p = (T *) hb_atomic_ptr_get (&instance);
|
T *p = (T *) hb_atomic_ptr_get (&this->instance);
|
||||||
if (unlikely (!p))
|
if (unlikely (!p))
|
||||||
{
|
{
|
||||||
p = (T *) calloc (1, sizeof (T));
|
p = (T *) calloc (1, sizeof (T));
|
||||||
if (unlikely (!p))
|
if (unlikely (!p))
|
||||||
p = const_cast<T *> (&Null(T));
|
p = const_cast<T *> (&Null(T));
|
||||||
else
|
else
|
||||||
p->init (face);
|
p->init (this->face);
|
||||||
if (unlikely (!hb_atomic_ptr_cmpexch (const_cast<T **>(&instance), nullptr, p)))
|
if (unlikely (!hb_atomic_ptr_cmpexch (const_cast<T **>(&this->instance), nullptr, p)))
|
||||||
{
|
{
|
||||||
if (p != &Null(T))
|
if (p != &Null(T))
|
||||||
p->fini ();
|
p->fini ();
|
||||||
|
@ -630,46 +646,29 @@ struct hb_lazy_loader_t
|
||||||
}
|
}
|
||||||
return p;
|
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 <typename T>
|
template <typename T>
|
||||||
struct hb_table_lazy_loader_t
|
struct hb_table_lazy_loader_t : hb_base_lazy_loader_t<hb_table_lazy_loader_t<T>, T, hb_blob_t>
|
||||||
{
|
{
|
||||||
inline void init (hb_face_t *face_)
|
|
||||||
{
|
|
||||||
face = face_;
|
|
||||||
blob = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void fini (void)
|
inline void fini (void)
|
||||||
{
|
{
|
||||||
hb_blob_destroy (blob);
|
hb_blob_destroy (this->instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline hb_blob_t* get_blob (void) const
|
inline hb_blob_t* get_blob (void) const
|
||||||
{
|
{
|
||||||
retry:
|
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))
|
if (unlikely (!b))
|
||||||
{
|
{
|
||||||
b = hb_sanitize_context_t ().reference_table<T> (face);
|
b = hb_sanitize_context_t ().reference_table<T> (this->face);
|
||||||
if (!hb_atomic_ptr_cmpexch (&blob, nullptr, b))
|
if (!hb_atomic_ptr_cmpexch (&this->instance, nullptr, b))
|
||||||
{
|
{
|
||||||
hb_blob_destroy (b);
|
hb_blob_destroy (b);
|
||||||
goto retry;
|
goto retry;
|
||||||
}
|
}
|
||||||
blob = b;
|
this->instance = b;
|
||||||
}
|
}
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
@ -679,15 +678,6 @@ struct hb_table_lazy_loader_t
|
||||||
hb_blob_t *b = get_blob ();
|
hb_blob_t *b = get_blob ();
|
||||||
return b->as<T> ();
|
return b->as<T> ();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const T* operator-> (void) const
|
|
||||||
{
|
|
||||||
return get();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
hb_face_t *face;
|
|
||||||
mutable hb_blob_t *blob;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue