Kaydet (Commit) 08bb8fca authored tarafından Herbert Dürr's avatar Herbert Dürr Kaydeden (comit) Tor Lillqvist

#i122208# replace the binaryurp cache for improved C++ compatibility

Failing to instantiatie incomplete types like the Map::iterator in
binaryurp Cache's Entry members is allowed by the C++ standard.
The rewrite makes it more compliant with other C++ compilers/STLs.
And interesting alternative would be to use boost's multi_index_container.

git-svn-id: http://svn.apache.org/repos/asf/openoffice/branches/rejuvenate01@1480367 13f79535-47bb-0310-9956-ffa450edef68
üst da1dea9a
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include <cassert> #include <cassert>
#include <cstddef> #include <cstddef>
#include <map> #include <map>
#include <list>
#include "boost/noncopyable.hpp" #include "boost/noncopyable.hpp"
#include "sal/types.h" #include "sal/types.h"
...@@ -37,88 +38,57 @@ enum { size = 256, ignore = 0xFFFF }; ...@@ -37,88 +38,57 @@ enum { size = 256, ignore = 0xFFFF };
} }
template< typename T > class Cache: private boost::noncopyable { template< typename T > class Cache : private boost::noncopyable {
public: public:
typedef sal_uInt16 IdxType;
explicit Cache(std::size_t size): explicit Cache(std::size_t size):
size_(size), first_(map_.end()), last_(map_.end()) size_(size)
{ {
assert(size < cache::ignore); assert(size < cache::ignore);
} }
sal_uInt16 add(T const & content, bool * found) { IdxType add( const T& rContent, bool* pbFound) {
assert(found != 0); assert( pbFound != NULL);
typename Map::iterator i(map_.find(content)); if( !size_) {
*found = i != map_.end(); *pbFound = false;
if (i == map_.end()) {
typename Map::size_type n = map_.size();
if (n < size_) {
i =
(map_.insert(
typename Map::value_type(
content,
Entry(
static_cast< sal_uInt16 >(n), map_.end(),
first_)))).
first;
if (first_ == map_.end()) {
last_ = i;
} else {
first_->second.prev = i;
}
first_ = i;
} else if (last_ != map_.end()) {
i =
(map_.insert(
typename Map::value_type(
content,
Entry(last_->second.index, map_.end(), first_)))).
first;
first_->second.prev = i;
first_ = i;
typename Map::iterator j(last_);
last_ = last_->second.prev;
last_->second.next = map_.end();
map_.erase(j);
} else {
// Reached iff size_ == 0:
return cache::ignore; return cache::ignore;
} }
} else if (i != first_) { // try to insert into the map
// Move to front (reached only if size_ > 1): list_.push_front( rContent); // create a temp entry
i->second.prev->second.next = i->second.next; typedef std::pair<typename LruList::iterator, IdxType> MappedType;
if (i->second.next == map_.end()) { typedef std::pair<typename LruItMap::iterator,bool> MapPair;
last_ = i->second.prev; MapPair aMP = map_.insert( MappedType( list_.begin(), 0));
} else { *pbFound = !aMP.second;
i->second.next->second.prev = i->second.prev;
if( !aMP.second) { // insertion not needed => found the entry
list_.pop_front(); // remove the temp entry
list_.splice( list_.begin(), list_, aMP.first->first); // the found entry is moved to front
return aMP.first->second;
} }
i->second.prev = map_.end();
i->second.next = first_; // test insertion successful => it was new so we keep it
first_->second.prev = i; IdxType n = static_cast<IdxType>( map_.size() - 1);
first_ = i; if( n >= size_) { // cache full => replace the LRU entry
// find the least recently used element in the map
typename LruItMap::iterator it = map_.find( --list_.end());
n = it->second;
map_.erase( it); // remove it from the map
list_.pop_back(); // remove from the list
} }
return i->second.index; aMP.first->second = n;
return n;
} }
private: private:
struct Entry; typedef std::list<T> LruList; // last recently used list
typedef typename LruList::iterator LruListIt;
typedef std::map< T, Entry > Map; struct CmpT{ bool operator()( const LruListIt& rA, const LruListIt& rB) const { return (*rA<*rB);}};
typedef ::std::map< LruListIt, IdxType, CmpT > LruItMap; // a map into a LruList
struct Entry {
sal_uInt16 index;
typename Map::iterator prev;
typename Map::iterator next;
Entry(
sal_uInt16 theIndex, typename Map::iterator thePrev,
typename Map::iterator theNext):
index(theIndex), prev(thePrev), next(theNext) {}
};
std::size_t size_; std::size_t size_;
Map map_; LruItMap map_;
typename Map::iterator first_; LruList list_;
typename Map::iterator last_;
}; };
} }
......
...@@ -32,14 +32,38 @@ ...@@ -32,14 +32,38 @@
namespace com { namespace sun { namespace star { namespace uno { namespace com { namespace sun { namespace star { namespace uno {
bool operator <(TypeDescription const & left, TypeDescription const & right) { bool operator<( const TypeDescription& rLeft, const TypeDescription& rRight) {
assert(left.is() && right.is()); assert( rLeft.is() && rRight.is());
typelib_TypeClass tc1 = left.get()->eTypeClass; const typelib_TypeDescription& rA = *rLeft.get();
typelib_TypeClass tc2 = right.get()->eTypeClass; const typelib_TypeDescription& rB = *rRight.get();
return tc1 < tc2 || if( rA.eTypeClass != rA.eTypeClass)
(tc1 == tc2 && return (rA.eTypeClass < rB.eTypeClass);
(OUString(left.get()->pTypeName) < const sal_Int32 nCmp = rtl_ustr_compare_WithLength(
OUString(right.get()->pTypeName))); rA.pTypeName->buffer, rA.pTypeName->length,
rB.pTypeName->buffer, rB.pTypeName->length);
return (nCmp < 0);
}
bool TypeDescEqual::operator()( const TypeDescription& rLeft, const TypeDescription& rRight) const
{
assert( rLeft.is() && rRight.is());
const typelib_TypeDescription& rA = *rLeft.get();
const typelib_TypeDescription& rB = *rRight.get();
if( rA.eTypeClass != rB.eTypeClass)
return false;
const sal_Int32 nCmp = rtl_ustr_compare_WithLength(
rA.pTypeName->buffer, rA.pTypeName->length,
rB.pTypeName->buffer, rB.pTypeName->length);
return (nCmp == 0);
}
sal_Int32 TypeDescHash::operator()( const TypeDescription& rTD) const
{
assert( rTD.is());
const typelib_TypeDescription& rA = *rTD.get();
sal_Int32 h = rtl_ustr_hashCode_WithLength( rA.pTypeName->buffer, rA.pTypeName->length);
h ^= static_cast<sal_Int32>(rA.eTypeClass);
return h;
} }
} } } } } } } }
...@@ -47,8 +71,8 @@ bool operator <(TypeDescription const & left, TypeDescription const & right) { ...@@ -47,8 +71,8 @@ bool operator <(TypeDescription const & left, TypeDescription const & right) {
namespace rtl { namespace rtl {
bool operator <(ByteSequence const & left, ByteSequence const & right) { bool operator <(ByteSequence const & left, ByteSequence const & right) {
for (sal_Int32 i = 0; i != std::min(left.getLength(), right.getLength()); const sal_Int32 nLen = std::min( left.getLength(), right.getLength());
++i) for( sal_Int32 i = 0; i < nLen; ++i )
{ {
if (left[i] < right[i]) { if (left[i] < right[i]) {
return true; return true;
......
...@@ -31,6 +31,10 @@ namespace com { namespace sun { namespace star { namespace uno { ...@@ -31,6 +31,10 @@ namespace com { namespace sun { namespace star { namespace uno {
bool operator <(TypeDescription const & left, TypeDescription const & right); bool operator <(TypeDescription const & left, TypeDescription const & right);
struct TypeDescHash { sal_Int32 operator()( const TypeDescription&) const; };
struct TypeDescEqual { bool operator()( const TypeDescription&, const TypeDescription&) const; };
} } } } } } } }
namespace rtl { namespace rtl {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment