[lazy] More shuffle
This commit is contained in:
parent
5d9863be6e
commit
5abdf5eeba
|
@ -599,24 +599,22 @@ struct hb_lazy_loader_t
|
||||||
{
|
{
|
||||||
static_assert (WheresData > 0, "");
|
static_assert (WheresData > 0, "");
|
||||||
|
|
||||||
/* https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern */
|
|
||||||
inline const Subclass* thiz (void) const { return static_cast<const Subclass *> (this); }
|
|
||||||
inline Subclass* thiz (void) { return static_cast<Subclass *> (this); }
|
|
||||||
|
|
||||||
inline void init0 (void) {} /* Init, when memory is already set to 0. No-op for us. */
|
inline void init0 (void) {} /* Init, when memory is already set to 0. No-op for us. */
|
||||||
inline void init (void)
|
inline void init (void) { instance.set_relaxed (nullptr); }
|
||||||
|
inline void fini (void) { destroy (instance.get ()); }
|
||||||
|
static inline void destroy (Stored *p)
|
||||||
{
|
{
|
||||||
instance.set_relaxed (nullptr);
|
if (p && p != Subclass::get_null ())
|
||||||
}
|
Subclass::destroy (p);
|
||||||
inline void fini (void)
|
|
||||||
{
|
|
||||||
Stored *p = this->instance.get ();
|
|
||||||
if (p)
|
|
||||||
thiz ()->destroy (p);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const Returned * operator -> (void) const { return thiz ()->get (); }
|
inline const Returned * operator -> (void) const { return get (); }
|
||||||
inline const Returned & operator * (void) const { return *thiz ()->get (); }
|
inline const Returned & operator * (void) const { return *get (); }
|
||||||
|
|
||||||
|
inline Data * get_data (void) const
|
||||||
|
{
|
||||||
|
return *(((Data **) this) - WheresData);
|
||||||
|
}
|
||||||
|
|
||||||
inline Stored * get_stored (void) const
|
inline Stored * get_stored (void) const
|
||||||
{
|
{
|
||||||
|
@ -624,15 +622,15 @@ struct hb_lazy_loader_t
|
||||||
Stored *p = this->instance.get ();
|
Stored *p = this->instance.get ();
|
||||||
if (unlikely (!p))
|
if (unlikely (!p))
|
||||||
{
|
{
|
||||||
Data *data= *(((Data **) this) - WheresData);
|
Data *data = get_data ();
|
||||||
if (likely (!p))
|
if (likely (data))
|
||||||
p = thiz ()->create (data);
|
p = Subclass::create (data);
|
||||||
if (unlikely (!p))
|
if (unlikely (!p))
|
||||||
p = thiz ()->create (nullptr); /* Produce nil object. */
|
p = const_cast<Stored *> (Subclass::get_null ());
|
||||||
assert (p);
|
assert (p);
|
||||||
if (unlikely (!this->instance.cmpexch (nullptr, p)))
|
if (unlikely (!this->instance.cmpexch (nullptr, p)))
|
||||||
{
|
{
|
||||||
thiz ()->destroy (p);
|
destroy (p);
|
||||||
goto retry;
|
goto retry;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -645,23 +643,16 @@ struct hb_lazy_loader_t
|
||||||
* However, to make TSan, etc, happy, we using cmpexch. */
|
* However, to make TSan, etc, happy, we using cmpexch. */
|
||||||
retry:
|
retry:
|
||||||
Stored *p = this->instance.get ();
|
Stored *p = this->instance.get ();
|
||||||
if (p)
|
|
||||||
{
|
|
||||||
if (unlikely (!this->instance.cmpexch (p, instance_)))
|
if (unlikely (!this->instance.cmpexch (p, instance_)))
|
||||||
goto retry;
|
goto retry;
|
||||||
thiz ()->destroy (p);
|
destroy (p);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const Returned * get (void) const
|
inline const Returned * get (void) const { return Subclass::convert (get_stored ()); }
|
||||||
{
|
|
||||||
return thiz ()->convert (get_stored ());
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline const Returned* convert (const Stored *p)
|
/* To be possibly overloaded by subclasses. */
|
||||||
{
|
static inline const Returned* convert (const Stored *p) { return p; }
|
||||||
return p;
|
static inline const Stored* get_null (void) { return &Null(Stored); }
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/* Must only have one pointer. */
|
/* Must only have one pointer. */
|
||||||
|
@ -677,22 +668,19 @@ struct hb_object_lazy_loader_t : hb_lazy_loader_t<hb_object_lazy_loader_t<Wheres
|
||||||
{
|
{
|
||||||
static inline T *create (hb_face_t *face)
|
static inline T *create (hb_face_t *face)
|
||||||
{
|
{
|
||||||
if (unlikely (!face))
|
|
||||||
return const_cast<T *> (&Null(T));
|
|
||||||
T *p = (T *) calloc (1, sizeof (T));
|
T *p = (T *) calloc (1, sizeof (T));
|
||||||
if (unlikely (!p))
|
if (likely (p))
|
||||||
p = const_cast<T *> (&Null(T));
|
|
||||||
else
|
|
||||||
p->init (face);
|
p->init (face);
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
static inline void destroy (T *p)
|
static inline void destroy (T *p)
|
||||||
{
|
{
|
||||||
if (p != &Null(T))
|
p->fini ();
|
||||||
{
|
|
||||||
p->fini();
|
|
||||||
free (p);
|
free (p);
|
||||||
}
|
}
|
||||||
|
static inline const T *get_null (void)
|
||||||
|
{
|
||||||
|
return &Null(T);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -701,18 +689,18 @@ struct hb_table_lazy_loader_t : hb_lazy_loader_t<hb_table_lazy_loader_t<T, Where
|
||||||
hb_face_t, WheresFace,
|
hb_face_t, WheresFace,
|
||||||
T, hb_blob_t>
|
T, hb_blob_t>
|
||||||
{
|
{
|
||||||
static_assert (WheresFace > 0, "");
|
|
||||||
|
|
||||||
static inline hb_blob_t *create (hb_face_t *face)
|
static inline hb_blob_t *create (hb_face_t *face)
|
||||||
{
|
{
|
||||||
if (unlikely (!face))
|
|
||||||
return hb_blob_get_empty ();
|
|
||||||
return hb_sanitize_context_t ().reference_table<T> (face);
|
return hb_sanitize_context_t ().reference_table<T> (face);
|
||||||
}
|
}
|
||||||
static inline void destroy (hb_blob_t *p)
|
static inline void destroy (hb_blob_t *p)
|
||||||
{
|
{
|
||||||
hb_blob_destroy (p);
|
hb_blob_destroy (p);
|
||||||
}
|
}
|
||||||
|
static inline const hb_blob_t *get_null (void)
|
||||||
|
{
|
||||||
|
return hb_blob_get_empty ();
|
||||||
|
}
|
||||||
static inline const T* convert (const hb_blob_t *blob)
|
static inline const T* convert (const hb_blob_t *blob)
|
||||||
{
|
{
|
||||||
return blob->as<T> ();
|
return blob->as<T> ();
|
||||||
|
|
Loading…
Reference in New Issue