Skip to content

Commit

Permalink
remove boost from GUIFontCache
Browse files Browse the repository at this point in the history
  • Loading branch information
FernetMenta committed Jan 31, 2016
1 parent 166f3e9 commit 77ff892
Show file tree
Hide file tree
Showing 2 changed files with 100 additions and 108 deletions.
173 changes: 96 additions & 77 deletions xbmc/guilib/GUIFontCache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,46 +23,66 @@
#include "GUIFontTTF.h"
#include "GraphicContext.h"

#if defined(TARGET_DARWIN )
// apple clang with c++11 doesn't like
// the forwards declarations of boost
// disable them ...
#define BOOST_DETAIL_NO_CONTAINER_FWD 1
#endif

#include "boost/multi_index_container.hpp"
#include "boost/multi_index/sequenced_index.hpp"
#include "boost/multi_index/hashed_index.hpp"
#include "boost/multi_index/member.hpp"

using namespace boost::multi_index;

template<class Position, class Value>
class CGUIFontCacheImpl
{
/* Empty structs used as tags to identify indexes */
struct Age {};
struct Hash {};

typedef multi_index_container <
CGUIFontCacheEntry<Position, Value>,
indexed_by<
sequenced<tag<Age> >,
hashed_unique<tag<Hash>,
member<CGUIFontCacheEntry<Position, Value>,
CGUIFontCacheKey<Position>, &CGUIFontCacheEntry<Position, Value>::m_key
>,
CGUIFontCacheHash<Position>, CGUIFontCacheKeysMatch < Position >
>
>
> EntryList;

typedef typename EntryList::template index<Age>::type::iterator EntryAgeIterator;
typedef typename EntryList::template index<Hash>::type::iterator EntryHashIterator;
struct EntryList
{
typedef std::multimap<size_t, CGUIFontCacheEntry<Position, Value>*> HashMap;
typedef std::multimap<size_t, typename HashMap::iterator> AgeMap;

typename HashMap::iterator Insert(size_t hash, CGUIFontCacheEntry<Position, Value> *v)
{
auto r (hashMap.insert(typename HashMap::value_type(hash, v)));
if (r->second)
ageMap.insert(typename AgeMap::value_type(r->second->m_lastUsedMillis, r));
return r;
}
void Flush()
{
ageMap.clear();
for (auto it = hashMap.begin(); it != hashMap.end(); ++it)
delete(it->second);
hashMap.clear();
}
typename HashMap::iterator FindKey(CGUIFontCacheKey<Position> key)
{
CGUIFontCacheHash<Position> hashGen;
CGUIFontCacheKeysMatch<Position> keyMatch;
typename HashMap::iterator ret;
auto range = hashMap.equal_range(hashGen(key));
for (ret = range.first; ret != range.second; ++ret)
{
if (keyMatch(ret->second->m_key, key))
{
return ret;
}
}
return hashMap.end();
}
void UpdateAge(typename HashMap::iterator it, size_t millis)
{
auto range = ageMap.equal_range(millis);
typename AgeMap::iterator ageit;
for (ageit = range.first; ageit != range.second; ++ageit)
{
if (ageit->second == it)
{
ageMap.erase(ageit);
ageMap.insert(typename AgeMap::value_type(millis, it));
it->second->m_lastUsedMillis = millis;
return;
}
}
}

HashMap hashMap;
AgeMap ageMap;
};

EntryList m_list;
CGUIFontCache<Position, Value> *m_parent;

public:

CGUIFontCacheImpl(CGUIFontCache<Position, Value>* parent) : m_parent(parent) {}
Expand All @@ -75,27 +95,26 @@ class CGUIFontCacheImpl
};

template<class Position, class Value>
void CGUIFontCacheEntry<Position, Value>::Reassign::operator()(CGUIFontCacheEntry<Position, Value> &entry)
CGUIFontCacheEntry<Position, Value>::~CGUIFontCacheEntry()
{
entry.m_key.m_pos = m_key.m_pos;
entry.m_key.m_colors.assign(m_key.m_colors.begin(), m_key.m_colors.end());
entry.m_key.m_text.assign(m_key.m_text.begin(), m_key.m_text.end());
entry.m_key.m_alignment = m_key.m_alignment;
entry.m_key.m_maxPixelWidth = m_key.m_maxPixelWidth;
entry.m_key.m_scrolling = m_key.m_scrolling;
entry.m_matrix = m_key.m_matrix;
entry.m_key.m_scaleX = m_key.m_scaleX;
entry.m_key.m_scaleY = m_key.m_scaleY;

entry.m_lastUsedMillis = m_nowMillis;
entry.m_value.clear();
delete &m_key.m_colors;
delete &m_key.m_text;
m_value.clear();
}

template<class Position, class Value>
CGUIFontCacheEntry<Position, Value>::~CGUIFontCacheEntry()
void CGUIFontCacheEntry<Position, Value>::Assign(const CGUIFontCacheKey<Position> &key, unsigned int nowMillis)
{
delete &m_key.m_colors;
delete &m_key.m_text;
m_key.m_pos = key.m_pos;
m_key.m_colors.assign(key.m_colors.begin(), key.m_colors.end());
m_key.m_text.assign(key.m_text.begin(), key.m_text.end());
m_key.m_alignment = key.m_alignment;
m_key.m_maxPixelWidth = key.m_maxPixelWidth;
m_key.m_scrolling = key.m_scrolling;
m_matrix = key.m_matrix;
m_key.m_scaleX = key.m_scaleX;
m_key.m_scaleY = key.m_scaleY;
m_lastUsedMillis = nowMillis;
m_value.clear();
}

Expand Down Expand Up @@ -137,38 +156,40 @@ Value &CGUIFontCacheImpl<Position, Value>::Lookup(Position &pos,
alignment, maxPixelWidth,
scrolling, g_graphicsContext.GetGUIMatrix(),
g_graphicsContext.GetGUIScaleX(), g_graphicsContext.GetGUIScaleY());
auto i = m_list.template get<Hash>().find(key);
if (i == m_list.template get<Hash>().end())

auto i = m_list.FindKey(key);
if (i == m_list.hashMap.end())
{
/* Cache miss */
EntryAgeIterator oldest = m_list.template get<Age>().begin();
if (!m_list.template get<Age>().empty() && nowMillis - oldest->m_lastUsedMillis > FONT_CACHE_TIME_LIMIT)
// Cache miss
dirtyCache = true;
CGUIFontCacheEntry<Position, Value> *entry = nullptr;
if (!m_list.ageMap.empty() && (nowMillis - m_list.ageMap.begin()->first) > FONT_CACHE_TIME_LIMIT)
{
/* The oldest existing entry is old enough to expire and reuse */
m_list.template get<Hash>().modify(m_list.template project<Hash>(oldest), typename CGUIFontCacheEntry<Position, Value>::Reassign(key, nowMillis));
m_list.template get<Age>().relocate(m_list.template get<Age>().end(), oldest);
entry = m_list.ageMap.begin()->second->second;
m_list.hashMap.erase(m_list.ageMap.begin()->second);
m_list.ageMap.erase(m_list.ageMap.begin()->first);
}

// add new entry
CGUIFontCacheHash<Position> hashgen;
if (!entry)
entry = new CGUIFontCacheEntry<Position, Value>(*m_parent, key, nowMillis);
else
{
/* We need a new entry instead */
/* Yes, this causes the creation an destruction of a temporary entry, but
* this code ought to only be used infrequently, when the cache needs to grow */
m_list.template get<Age>().push_back(CGUIFontCacheEntry<Position, Value>(*m_parent, key, nowMillis));
}
dirtyCache = true;
return (--m_list.template get<Age>().end())->m_value;
entry->Assign(key, nowMillis);
return m_list.Insert(hashgen(key), entry)->second->m_value;
}
else
{
/* Cache hit */
/* Update the translation arguments so that they hold the offset to apply
* to the cached values (but only in the dynamic case) */
pos.UpdateWithOffsets(i->m_key.m_pos, scrolling);
/* Update time in entry and move to the back of the list */
i->m_lastUsedMillis = nowMillis;
m_list.template get<Age>().relocate(m_list.template get<Age>().end(), m_list.template project<Age>(i));
// Cache hit
// Update the translation arguments so that they hold the offset to apply
// to the cached values (but only in the dynamic case)
pos.UpdateWithOffsets(i->second->m_key.m_pos, scrolling);

// Update time in entry and move to the back of the list
m_list.UpdateAge(i, nowMillis);

dirtyCache = false;
return i->m_value;
return i->second->m_value;
}
}

Expand All @@ -181,19 +202,17 @@ void CGUIFontCache<Position, Value>::Flush()
template<class Position, class Value>
void CGUIFontCacheImpl<Position, Value>::Flush()
{
m_list.template get<Age>().clear();
m_list.Flush();
}

template CGUIFontCache<CGUIFontCacheStaticPosition, CGUIFontCacheStaticValue>::CGUIFontCache(CGUIFontTTFBase &font);
template CGUIFontCache<CGUIFontCacheStaticPosition, CGUIFontCacheStaticValue>::~CGUIFontCache();
template void CGUIFontCacheEntry<CGUIFontCacheStaticPosition, CGUIFontCacheStaticValue>::Reassign::operator()(CGUIFontCacheEntry<CGUIFontCacheStaticPosition, CGUIFontCacheStaticValue> &entry);
template CGUIFontCacheEntry<CGUIFontCacheStaticPosition, CGUIFontCacheStaticValue>::~CGUIFontCacheEntry();
template CGUIFontCacheStaticValue &CGUIFontCache<CGUIFontCacheStaticPosition, CGUIFontCacheStaticValue>::Lookup(CGUIFontCacheStaticPosition &, const vecColors &, const vecText &, uint32_t, float, bool, unsigned int, bool &);
template void CGUIFontCache<CGUIFontCacheStaticPosition, CGUIFontCacheStaticValue>::Flush();

template CGUIFontCache<CGUIFontCacheDynamicPosition, CGUIFontCacheDynamicValue>::CGUIFontCache(CGUIFontTTFBase &font);
template CGUIFontCache<CGUIFontCacheDynamicPosition, CGUIFontCacheDynamicValue>::~CGUIFontCache();
template void CGUIFontCacheEntry<CGUIFontCacheDynamicPosition, CGUIFontCacheDynamicValue>::Reassign::operator()(CGUIFontCacheEntry<CGUIFontCacheDynamicPosition, CGUIFontCacheDynamicValue> &entry);
template CGUIFontCacheEntry<CGUIFontCacheDynamicPosition, CGUIFontCacheDynamicValue>::~CGUIFontCacheEntry();
template CGUIFontCacheDynamicValue &CGUIFontCache<CGUIFontCacheDynamicPosition, CGUIFontCacheDynamicValue>::Lookup(CGUIFontCacheDynamicPosition &, const vecColors &, const vecText &, uint32_t, float, bool, unsigned int, bool &);
template void CGUIFontCache<CGUIFontCacheDynamicPosition, CGUIFontCacheDynamicValue>::Flush();
Expand Down
35 changes: 4 additions & 31 deletions xbmc/guilib/GUIFontCache.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,12 +80,8 @@ struct CGUIFontCacheEntry
const CGUIFontCache<Position, Value> &m_cache;
CGUIFontCacheKey<Position> m_key;
TransformMatrix m_matrix;

/* These need to be declared as mutable to get round the fact that only
* const iterators are available. These fields do not affect comparison or
* hash functors, so from the container's point of view, they are mutable. */
mutable unsigned int m_lastUsedMillis;
mutable Value m_value;
unsigned int m_lastUsedMillis;
Value m_value;

CGUIFontCacheEntry(const CGUIFontCache<Position, Value> &cache, const CGUIFontCacheKey<Position> &key, unsigned int nowMillis) :
m_cache(cache),
Expand All @@ -101,31 +97,9 @@ struct CGUIFontCacheEntry
m_matrix = key.m_matrix;
}

CGUIFontCacheEntry(const CGUIFontCacheEntry &other) :
m_cache(other.m_cache),
m_key(other.m_key.m_pos,
*new vecColors, *new vecText,
other.m_key.m_alignment, other.m_key.m_maxPixelWidth,
other.m_key.m_scrolling, m_matrix,
other.m_key.m_scaleX, other.m_key.m_scaleY),
m_lastUsedMillis(other.m_lastUsedMillis),
m_value(other.m_value)
{
m_key.m_colors.assign(other.m_key.m_colors.begin(), other.m_key.m_colors.end());
m_key.m_text.assign(other.m_key.m_text.begin(), other.m_key.m_text.end());
m_matrix = other.m_key.m_matrix;
}

struct Reassign
{
Reassign(const CGUIFontCacheKey<Position> &key, unsigned int nowMillis) : m_key(key), m_nowMillis(nowMillis) {}
void operator()(CGUIFontCacheEntry &entry);
private:
const CGUIFontCacheKey<Position> &m_key;
unsigned int m_nowMillis;
};

~CGUIFontCacheEntry();

void Assign(const CGUIFontCacheKey<Position> &key, unsigned int nowMillis);
};

template<class Position>
Expand Down Expand Up @@ -161,7 +135,6 @@ struct CGUIFontCacheKeysMatch
};



template<class Position, class Value>
class CGUIFontCache
{
Expand Down

0 comments on commit 77ff892

Please sign in to comment.