cache.h

Go to the documentation of this file.
00001 /*
00002 Copyright (C) 2001-2006, William Joseph.
00003 All Rights Reserved.
00004 
00005 This file is part of GtkRadiant.
00006 
00007 GtkRadiant is free software; you can redistribute it and/or modify
00008 it under the terms of the GNU General Public License as published by
00009 the Free Software Foundation; either version 2 of the License, or
00010 (at your option) any later version.
00011 
00012 GtkRadiant is distributed in the hope that it will be useful,
00013 but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 GNU General Public License for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with GtkRadiant; if not, write to the Free Software
00019 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00020 */
00021 
00022 #if !defined(INCLUDED_CONTAINER_CACHE_H)
00023 #define INCLUDED_CONTAINER_CACHE_H
00024 
00025 #include <cstddef>
00026 #include "container/hashtable.h"
00027 #include "memory/allocator.h"
00028 
00029 template<typename Type, typename Parameter>
00030 class DefaultCreationPolicy {
00031 public:
00032     Type* construct(const Parameter& parameter) {
00033         return New<Type>().scalar(parameter);
00034     }
00035     void destroy(Type* p) {
00036         Delete<Type>().scalar(p);
00037     }
00038 };
00039 
00040 template<typename Type>
00041 class SharedValue {
00042     typedef Type value_type;
00043     typedef value_type* pointer;
00044     typedef value_type& reference;
00045 
00046     std::size_t m_count;
00047     pointer m_value;
00048 
00049 public:
00050     SharedValue()
00051             : m_count(0), m_value(0) {
00052     }
00053     ~SharedValue() {
00054         ASSERT_MESSAGE(m_count == 0 , "destroying a referenced object\n");
00055     }
00056     void set(pointer value) {
00057         m_value = value;
00058     }
00059     pointer get() {
00060         return m_value;
00061     }
00062     std::size_t increment() {
00063         return ++m_count;
00064     }
00065     std::size_t decrement() {
00066         ASSERT_MESSAGE(!empty(), "destroying a non-existent object\n");
00067         return --m_count;
00068     }
00069     std::size_t count() {
00070         return m_count;
00071     }
00072     bool empty() {
00073         return m_count == 0;
00074     }
00075     reference operator*() const {
00076         ASSERT_NOTNULL(m_value);
00077         return *m_value;
00078     }
00079     pointer operator->() const {
00080         return &(operator*());
00081     }
00082 };
00083 
00084 
00085 
00093 template < typename Key, typename Cached, typename Hasher, typename KeyEqual = std::equal_to<Key>, typename CreationPolicy = DefaultCreationPolicy<Cached, Key> >
00094 class HashedCache : public CreationPolicy {
00095     typedef SharedValue<Cached> Element;
00096     typedef HashTable<Key, Element, Hasher, KeyEqual> map_type;
00097 
00098     map_type m_map;
00099 
00100 public:
00101     explicit HashedCache(const CreationPolicy& creation = CreationPolicy())
00102             : CreationPolicy(creation), m_map(256) {
00103     }
00104     ~HashedCache() {
00105         ASSERT_MESSAGE(empty(), "HashedCache::~HashedCache: not empty");
00106     }
00107 
00108     typedef typename map_type::iterator iterator;
00109     typedef typename map_type::value_type value_type;
00110 
00111     iterator begin() {
00112         return m_map.begin();
00113     }
00114     iterator end() {
00115         return m_map.end();
00116     }
00117 
00118     bool empty() const {
00119         return m_map.empty();
00120     }
00121 
00122     iterator find(const Key& key) {
00123         return m_map.find(key);
00124     }
00125 
00126     void capture(iterator i) {
00127         (*i).value.increment();
00128     }
00129     void release(iterator i) {
00130         if ((*i).value.decrement() == 0) {
00131             CreationPolicy::destroy((*i).value.get());
00132             m_map.erase(i);
00133         }
00134     }
00135 
00136     Element& capture(const Key& key) {
00137         iterator i = m_map.insert(key, Element());
00138         if ((*i).value.increment() == 1) {
00139             (*i).value.set(CreationPolicy::construct((*i).key));
00140         }
00141         return (*i).value;
00142     }
00143     void release(const Key& key) {
00144         iterator i = m_map.find(key);
00145         ASSERT_MESSAGE(i != m_map.end(), "releasing a non-existent object\n");
00146         release(i);
00147     }
00148 
00149     void clear() {
00150         m_map.clear();
00151     }
00152 };
00153 
00154 
00155 #endif

Generated by  doxygen 1.6.2