src/Lib/shttl/setassoc_table.h

説明を見る。
00001 // 
00002 // Copyright (c) 2005-2008 Kenichi Watanabe.
00003 // Copyright (c) 2005-2008 Yasuhiro Watari.
00004 // Copyright (c) 2005-2008 Hironori Ichibayashi.
00005 // Copyright (c) 2008-2009 Kazuo Horio.
00006 // Copyright (c) 2009-2013 Naruki Kurata.
00007 // Copyright (c) 2005-2013 Ryota Shioya.
00008 // Copyright (c) 2005-2013 Masahiro Goshima.
00009 // 
00010 // This software is provided 'as-is', without any express or implied
00011 // warranty. In no event will the authors be held liable for any damages
00012 // arising from the use of this software.
00013 // 
00014 // Permission is granted to anyone to use this software for any purpose,
00015 // including commercial applications, and to alter it and redistribute it
00016 // freely, subject to the following restrictions:
00017 // 
00018 // 1. The origin of this software must not be misrepresented; you must not
00019 // claim that you wrote the original software. If you use this software
00020 // in a product, an acknowledgment in the product documentation would be
00021 // appreciated but is not required.
00022 // 
00023 // 2. Altered source versions must be plainly marked as such, and must not be
00024 // misrepresented as being the original software.
00025 // 
00026 // 3. This notice may not be removed or altered from any source
00027 // distribution.
00028 // 
00029 // 
00030 
00031 
00032 //
00033 // Generic set-associative table class.
00034 //
00035 // Usage:
00036 //  shttl::setassoc_table<
00037 //      std::pair< AddrType, LineType >, 
00038 //      shttl::hasher,
00039 //      shttl::lru_list< Addr, u8 >
00040 //  > table_with_small_associativity.
00041 //
00042 //  shttl::setassoc_table<
00043 //      CachePair, 
00044 //      CacheHasher,
00045 //      shttl::lru_list< Addr, u32 >,
00046 //      shttl::setassoc_table_strage_map<       // For large associative table.
00047 //          shttl::setassoc_table_line_base< CachePair >
00048 //      >
00049 //  > table_with_large_associativity.
00050 //
00051 
00052 #ifndef SETASSOC_TABLE_H
00053 #define SETASSOC_TABLE_H
00054 
00055 #include <stdexcept>
00056 #include <algorithm>
00057 #include <functional>
00058 #include <cassert>
00059 #include <vector>
00060 #include <map>
00061 
00062 
00063 #include "shttl_types.h"
00064 #include "std_hasher.h"
00065 #include "lru.h"
00066 #include "nlu.h"
00067 
00068 
00069 namespace shttl
00070 {
00071 
00072     // ID of each value, which stores the index and the way number of a line.
00073     template < typename BodyType, typename BodyPtrType, typename LineType >
00074     class setassoc_table_iterator_base
00075     {
00076     public:
00077 
00078         typedef BodyType    body_type;
00079         typedef BodyPtrType body_ptr_type;
00080         typedef LineType    line_type;
00081         typedef typename body_type::size_type size_type;
00082 
00083         static const size_type invalid_index = body_type::invalid_index;
00084         static const size_type invalid_way   = body_type::invalid_way;
00085 
00086         setassoc_table_iterator_base( 
00087             body_ptr_type body  = NULL,
00088             size_type     index = invalid_index, 
00089             size_type     way   = invalid_way
00090         ) : 
00091             m_body ( body ),
00092             m_index( index ),
00093             m_way  ( way   )
00094         {
00095         }
00096 
00097         size_type way() const
00098         {
00099             return m_way;
00100         }
00101 
00102         size_type index() const 
00103         {
00104             return m_index;
00105         }
00106 
00107         // Returns the pointer of a table body.
00108         const body_type* body() const
00109         {
00110             return m_body;
00111         }
00112 
00113         bool operator != ( const setassoc_table_iterator_base& rhs ) const
00114         {
00115             return !((*this) == rhs);
00116         }
00117 
00118         bool operator == ( const setassoc_table_iterator_base& rhs ) const
00119         {
00120             return 
00121                 ( m_body  == rhs.m_body  ) &&
00122                 ( m_index == rhs.m_index ) &&
00123                 ( m_way   == rhs.m_way   );
00124         }
00125 
00126         // Pre increment
00127         setassoc_table_iterator_base& operator++()
00128         {   
00129             SHTTL_ASSERT( m_index < m_body->set_num() );
00130             SHTTL_ASSERT( m_way   < m_body->way_num() );
00131             m_way++;
00132             if( m_way == m_body->way_num() ){
00133                 m_way = 0;
00134                 m_index++;
00135             }
00136             return *this;
00137         }
00138 
00139         // Post increment
00140         setassoc_table_iterator_base operator++(int)
00141         {   
00142             setassoc_table_iterator_base tmp = *this;
00143             ++*this;
00144             return tmp;
00145         }
00146 
00147         line_type* operator->() 
00148         {
00149             return &m_body->at( *this );
00150         }
00151 
00152         line_type& operator*()
00153         {
00154             return m_body->at( *this );
00155         }
00156 
00157     protected:
00158 
00159         body_ptr_type m_body;   // The pointer of a table body.
00160         size_type     m_index;
00161         size_type     m_way;
00162 
00163     };
00164 
00165     // A const version of an iterator.
00166     template < 
00167         typename BodyType, 
00168         typename BodyPtrType, 
00169         typename LineType,
00170         typename IteratorType 
00171     >
00172     class setassoc_table_const_iterator_base : 
00173         public setassoc_table_iterator_base< BodyType, BodyPtrType, LineType >
00174     {
00175         
00176     public:
00177 
00178         typedef
00179             setassoc_table_iterator_base< 
00180                 BodyType, 
00181                 BodyPtrType, 
00182                 LineType 
00183             > 
00184             base_type;
00185 
00186         typedef
00187             setassoc_table_const_iterator_base<
00188                 BodyType, 
00189                 BodyPtrType,
00190                 LineType, 
00191                 IteratorType
00192             >
00193             this_type;
00194 
00195         typedef IteratorType iterator;
00196         typedef typename base_type::body_ptr_type body_ptr_type;
00197         typedef typename base_type::size_type size_type;
00198         typedef typename base_type::line_type line_type;
00199 
00200 
00201         setassoc_table_const_iterator_base(
00202             body_ptr_type body  = NULL,
00203             size_type     index = base_type::invalid_index, 
00204             size_type     way   = base_type::invalid_way
00205         ) : base_type( body, index, way )
00206         {
00207         }
00208 
00209         setassoc_table_const_iterator_base(
00210             const iterator &ref
00211         ) : 
00212             base_type( ref.body(), ref.index(), ref.way() )
00213         {
00214         }
00215 
00216         bool operator != ( const this_type& rhs ) const
00217         {
00218             return *static_cast<const base_type*>(this) != rhs;
00219         }
00220 
00221         bool operator == ( const this_type& rhs ) const
00222         {
00223             return *static_cast<const base_type*>(this) == rhs;
00224         }
00225 
00226         line_type* operator->() 
00227         {
00228             return &m_body->at( *this );
00229         }
00230 
00231         line_type& operator*() 
00232         {
00233             return m_body->at( *this );
00234         }
00235 
00236     protected:
00237         using base_type::m_body;
00238 
00239     };
00240 
00241 
00242     //
00243     // Cache sets in setassoc_table.
00244     // 'setassoc_table_set_vector' and 'setassoc_table_strage_vector' 
00245     // work cooperatively.
00246     // This class is a version using 'std::vector'.
00247     // 'find()' is implemented by linear search thus
00248     // this class is fast in a table with small associativity
00249     //
00250     template <
00251         typename line_type, 
00252         typename strage_type 
00253     >
00254     class setassoc_table_set_vector
00255     {
00256 
00257     public:
00258 
00259         typedef typename strage_type::size_type size_type;
00260         typedef typename line_type::tag_type    tag_type;
00261         typedef typename line_type::value_type  value_type;
00262 
00263         static const size_type invalid_index = strage_type::invalid_index;
00264         static const size_type invalid_way   = strage_type::invalid_way;
00265 
00266         setassoc_table_set_vector( 
00267             strage_type* lines, 
00268             size_type way_num, 
00269             size_type offset 
00270         ) :
00271             m_strage ( lines ),
00272             m_way_num( way_num ),
00273             m_offset ( offset )
00274         {
00275         }
00276 
00277         // tagway
00278         inline size_type find( const tag_type tag ) const
00279         {
00280             for( size_type w = 0; w < m_way_num; w++ ){
00281                 const line_type& line = at( w );
00282                 if( line.tag == tag && line.valid ){
00283                     return w;
00284                 }
00285             }
00286             return invalid_way;
00287         }
00288 
00289         // way
00290         size_type find_free_way() const
00291         {
00292             for( size_type w = 0; w < m_way_num; w++ ){
00293                 if( !at( w ).valid )
00294                     return w;
00295             }
00296             return invalid_way;
00297         }
00298 
00299         // wayway
00300         void invalidate( const size_type way )
00301         {
00302             if( way == invalid_way )
00303                 return;
00304 
00305             assert_valid_way( way );
00306             at( way ).valid = false;
00307         }
00308 
00309 
00310         bool read( size_type way, line_type* line ) const
00311         {
00312             if( way == invalid_way )
00313                 return false;
00314 
00315             assert_valid_way( way );
00316             if( line ){
00317                 *line = at( way );
00318             }
00319             return at( way ).valid;
00320         }
00321 
00322         void write(
00323             const size_type way,
00324             const tag_type  tag, 
00325             const value_type &val = value_type()
00326         ){
00327             if(way == invalid_way)
00328                 return;
00329 
00330             assert_valid_way(way);
00331 
00332             // keydH
00333             SHTTL_ASSERT( find(tag) == invalid_way || find( tag ) == way );
00334 
00335             // 
00336             at( way ) = line_type( tag, val, true );
00337         }
00338 
00339         // Invalidate all lines in this set.
00340         void clear()
00341         {
00342             for( size_type w = 0; w < m_way_num; w++ ){
00343                 at( w ).valid = false;
00344             }
00345         }
00346 
00347         line_type& at( size_type way )
00348         {
00349             return m_strage->at( way + m_offset );
00350         }
00351 
00352         const line_type& at( size_type way ) const 
00353         {
00354             return m_strage->at( way + m_offset );
00355         }
00356 
00357     protected:
00358 
00359         strage_type* m_strage;
00360         size_type m_way_num;
00361         size_type m_offset;
00362 
00363         void assert_valid_way( size_type way ) const
00364         {
00365             SHTTL_ASSERT( 0 <= way && way < m_way_num );
00366         }
00367 
00368     };
00369 
00370     template < typename line_type >
00371     class setassoc_table_strage_vector
00372     {
00373     public:
00374 
00375         typedef setassoc_table_strage_vector< line_type > this_type;
00376         typedef size_t size_type;
00377         typedef std::vector<line_type> strage_type;
00378 
00379         typedef setassoc_table_set_vector<
00380             line_type,
00381             this_type
00382         > set_type;
00383         
00384         typedef setassoc_table_set_vector< 
00385             const line_type, 
00386             const this_type 
00387         > const_set_type;
00388 
00389         static const size_type invalid_index = ~((size_type)0);
00390         static const size_type invalid_way   = ~((size_type)0);
00391 
00392         line_type& at( size_type index )
00393         {
00394             return m_body.at( index );
00395         }
00396 
00397         const line_type& at( size_type index ) const 
00398         {
00399             return m_body.at( index );
00400         }
00401 
00402         set_type get_set( size_type index )
00403         {
00404             size_type offset = index*m_way_num;
00405             return set_type( 
00406                 this,
00407                 m_way_num,
00408                 offset
00409             );
00410         }
00411 
00412         const_set_type get_set( size_type index ) const
00413         {
00414             size_type offset = index*m_way_num;
00415             return const_set_type( 
00416                 this,
00417                 m_way_num,
00418                 offset
00419             );
00420         }
00421 
00422         void resize( size_type set_num, size_type way_num )
00423         {
00424             m_set_num = set_num;
00425             m_way_num = way_num;
00426             m_body.resize( set_num*way_num, line_type() );
00427         }
00428 
00429     protected:
00430 
00431         size_type   m_set_num;
00432         size_type   m_way_num;
00433         strage_type m_body;
00434 
00435     };
00436 
00437 
00438     //
00439     // Cache sets in setassoc_table.
00440     // 'setassoc_table_set_map' and 'setassoc_table_strage_map' 
00441     // work cooperatively.
00442     // This class is a version using 'std::map'.
00443     // 'find()' is implemented by 'std::map' thus
00444     // this class is fast in a table with large associativity
00445     //
00446     template <
00447         typename line_type, 
00448         typename strage_type 
00449     >
00450     class setassoc_table_set_map
00451     {
00452 
00453     public:
00454 
00455         typedef typename strage_type::size_type size_type;
00456         typedef typename line_type::key_type    tag_type;
00457         typedef typename line_type::value_type  value_type;
00458 
00459         typedef typename strage_type::line_map_type    line_map_type;
00460         typedef typename strage_type::invalid_map_type invalid_map_type;
00461 
00462         static const size_type invalid_index = strage_type::invalid_index;
00463         static const size_type invalid_way   = strage_type::invalid_way;
00464 
00465         setassoc_table_set_map( 
00466             strage_type* lines, 
00467             size_type way_num, 
00468             size_type index, 
00469             size_type offset 
00470         ) :
00471             m_strage ( lines ),
00472             m_way_num( way_num ),
00473             m_index  ( index ),
00474             m_offset ( offset )
00475         {
00476         }
00477 
00478         // tagway
00479         size_type find( const tag_type tag ) const
00480         {
00481             line_map_type& strage_set = m_strage->get_line_map( m_index );
00482             typename line_map_type::iterator strage_line = strage_set.find( tag );
00483             
00484             size_type found = invalid_way;
00485             if( strage_line != strage_set.end() && strage_line->second->valid ){
00486                 found = 
00487                     strage_line->second - m_strage->get_set_strage_iterator( m_index );
00488             }
00489 
00490         #ifdef SHTTL_SET_ASSOC_TABLE_VALIDATE_STRAGE_MAP
00491             size_type linear_found = invalid_way;
00492             for( size_type w = 0; w < m_way_num; w++ ){
00493                 const line_type& line = at( w );
00494                 if( line.key == tag && line.valid ){
00495                     linear_found = w;
00496                     break;
00497                 }
00498             }
00499             SHTTL_ASSERT( linear_found == found );
00500         #endif
00501 
00502             return found;
00503         }
00504 
00505         // way
00506         size_type find_free_way() const
00507         {
00508 
00509             invalid_map_type& invalid_set = m_strage->get_invalid_map( m_index );
00510             typename invalid_map_type::iterator invalid_line = invalid_set.begin();
00511             size_type found = invalid_way;
00512             if( invalid_line != invalid_set.end() ){
00513                 found = invalid_line->second;
00514             }
00515 
00516         #ifdef SHTTL_SET_ASSOC_TABLE_VALIDATE_STRAGE_MAP
00517             size_type linear_found = invalid_way;
00518             for( size_type w = 0; w < m_way_num; w++ ){
00519                 if( !at( w ).valid ){
00520                     linear_found = w;
00521                     break;
00522                 }
00523             }
00524             SHTTL_ASSERT( linear_found == found );
00525         #endif
00526 
00527             return found;
00528         }
00529 
00530         // wayway
00531         void invalidate( const size_type way )
00532         {
00533             if( way == invalid_way )
00534                 return;
00535 
00536             assert_valid_way( way );
00537             at( way ).valid = false;
00538 
00539             m_strage->get_invalid_map( m_index )[ way ] = way;
00540         }
00541         
00542         bool read( size_type way, line_type* line ) const
00543         {
00544             if( way == invalid_way )
00545                 return false;
00546 
00547             assert_valid_way( way );
00548             if( line ){
00549                 *line = at( way );
00550             }
00551             return at( way ).valid;
00552         }
00553 
00554         void write(
00555             const size_type way,
00556             const tag_type  tag, 
00557             const value_type &val = value_type()
00558         ){
00559             if(way == invalid_way)
00560                 return;
00561 
00562             assert_valid_way(way);
00563 
00564             // keydH
00565             SHTTL_ASSERT( find(tag) == invalid_way || find( tag ) == way );
00566 
00567             // 
00568             typename strage_type::strage_type::iterator line =
00569                 m_strage->get_set_strage_iterator( m_index ) + way;
00570 
00571             line_map_type& strage_set = m_strage->get_line_map( m_index );
00572             typename line_map_type::iterator old_line = strage_set.find( at( way ).key );
00573             if( old_line->second == line ){
00574                 strage_set.erase( old_line );
00575             }
00576 
00577             at( way ) = line_type( tag, val, true );
00578 
00579             strage_set[ tag ] = line;
00580             m_strage->get_invalid_map( m_index ).erase( way );
00581         }
00582 
00583         // Invalidate all lines in this set.
00584         void clear()
00585         {
00586             for( size_type way = 0; way < m_way_num; way++ ){
00587                 at( way ).valid = false;
00588 
00589                 m_strage->get_invalid_map( m_index )[ way ] = way;
00590             }
00591         }
00592 
00593         line_type& at( size_type way )
00594         {
00595             return m_strage->at( way + m_offset );
00596         }
00597 
00598         const line_type& at( size_type way ) const 
00599         {
00600             return m_strage->at( way + m_offset );
00601         }
00602 
00603     protected:
00604 
00605         strage_type* m_strage;
00606         size_type m_way_num;
00607         size_type m_index;
00608         size_type m_offset;
00609 
00610         void assert_valid_way( size_type way ) const
00611         {
00612             SHTTL_ASSERT( 0 <= way && way < m_way_num );
00613         }
00614 
00615     };
00616 
00617     template < typename line_type >
00618     class setassoc_table_strage_map
00619     {
00620     public:
00621 
00622         typedef setassoc_table_strage_map< line_type > this_type;
00623         typedef size_t size_type;
00624         typedef std::vector<line_type> strage_type;
00625         
00626         typedef typename line_type::key_type   key_type;
00627         typedef typename line_type::value_type value_type;
00628 
00629         typedef 
00630             setassoc_table_set_map<
00631                 line_type,
00632                 this_type
00633             > 
00634             set_type;
00635         
00636         typedef 
00637             setassoc_table_set_map< 
00638                 const line_type, 
00639                 const this_type 
00640             > 
00641             const_set_type;
00642 
00643         typedef 
00644             std::map<
00645                 key_type, 
00646                 typename strage_type::iterator
00647             >
00648             line_map_type;
00649 
00650         typedef 
00651             std::map<
00652                 size_type, 
00653                 size_type
00654             >
00655             invalid_map_type;
00656 
00657         static const size_type invalid_index = ~((size_type)0);
00658         static const size_type invalid_way   = ~((size_type)0);
00659 
00660         line_type& at( size_type index )
00661         {
00662             return m_body.at( index );
00663         }
00664 
00665         const line_type& at( size_type index ) const 
00666         {
00667             return m_body.at( index );
00668         }
00669 
00670         set_type get_set( size_type index )
00671         {
00672             size_type offset = index*m_way_num;
00673             return set_type( 
00674                 this,
00675                 m_way_num,
00676                 index,
00677                 offset
00678             );
00679         }
00680 
00681         const_set_type get_set( size_type index ) const
00682         {
00683             size_type offset = index*m_way_num;
00684             return const_set_type( 
00685                 this,
00686                 m_way_num,
00687                 index,
00688                 offset
00689             );
00690         }
00691 
00692         line_map_type& get_line_map( size_type index ){
00693             return m_line_map[ index ];
00694         }
00695         
00696         invalid_map_type& get_invalid_map( size_type index ){
00697             return m_invalid_map[ index ];
00698         }
00699 
00700         typename strage_type::iterator get_set_strage_iterator( size_type index )
00701         {
00702             return m_body.begin() + index * m_way_num; 
00703         }
00704 
00705         void resize( size_type set_num, size_type way_num )
00706         {
00707             m_set_num = set_num;
00708             m_way_num = way_num;
00709             
00710             m_body.clear();
00711             m_body.resize( set_num*way_num, line_type() );
00712 
00713             m_line_map.clear();
00714             m_line_map.resize( set_num );
00715 
00716             m_invalid_map.clear();
00717             m_invalid_map.resize( set_num );
00718 
00719             for( size_type index = 0; index < set_num; index++ ){
00720                 
00721                 set_type  set    = get_set( index );
00722                 line_map_type&    set_line_map    = m_line_map[ index ];
00723                 invalid_map_type& set_invalid_map = m_invalid_map[ index ];
00724                 typename strage_type::iterator set_iterator = get_set_strage_iterator( index );
00725 
00726                 // Update map and invalid line information.
00727                 for( size_type way = 0; way < way_num; way++ ){
00728                     line_type& line = set.at( way );
00729                     if( line.valid ){
00730                         set_line_map[ line.key ] = set_iterator + way;
00731                     }
00732                     else{
00733                         set_invalid_map[ way ] = way;
00734                     }
00735                 }
00736 
00737             }
00738         }
00739 
00740     protected:
00741 
00742         size_type   m_set_num;
00743         size_type   m_way_num;
00744 
00745         strage_type m_body;
00746         
00747         // Visual Studio 2010 cannot treat types with names whose 
00748         // length is larger than 4096. These struct are hack to 
00749         // reduce the length of type name..
00750         struct line_map_allocator : public std::allocator<line_map_type>
00751         {
00752         };
00753         struct invalid_map_allocator : public std::allocator<invalid_map_type>
00754         {
00755         };
00756         std::vector< line_map_type,    line_map_allocator >    m_line_map;
00757         std::vector< invalid_map_type, invalid_map_allocator > m_invalid_map;
00758 
00759     };
00760 
00761     // Line data stored in a table.
00762     template < typename PairType >
00763     struct setassoc_table_line_base
00764     {
00765         typedef typename PairType::first_type  tag_type;
00766         typedef typename PairType::second_type value_type;
00767 
00768         tag_type   tag;
00769         value_type value;
00770         bool       valid;
00771 
00772         setassoc_table_line_base(
00773             const tag_type&   tag_arg   = tag_type(),
00774             const value_type& value_arg = value_type(),
00775             const bool&       valid_arg = false
00776         ) :
00777             tag  ( tag_arg   ),
00778             value( value_arg ),
00779             valid( valid_arg )
00780         {
00781         }
00782     };
00783 
00784 
00785     //
00786     // Set-associative table.
00787     //
00788     template<
00789         typename PairType,          // The pair of an address and a value.
00790         typename Hasher = std_hasher< typename PairType::first_type >,
00791         typename Replacer = lru< typename PairType::first_type >,
00792         typename Strage =           
00793             setassoc_table_strage_vector< 
00794                 setassoc_table_line_base< PairType >
00795             >
00796     >
00797     class setassoc_table
00798     {
00799     public:
00800 
00801         // Types
00802 
00803         typedef
00804             setassoc_table< PairType, Hasher, Replacer, Strage > 
00805             this_type;
00806 
00807         typedef PairType pair_type;
00808         typedef Hasher   hasher_type;
00809         typedef Replacer replacer_type;
00810         typedef Strage   strage_type;
00811         
00812         typedef typename pair_type::first_type   key_type;
00813         typedef typename pair_type::second_type  value_type;
00814         typedef typename hasher_type::size_type  hasher_size_type;
00815 
00816         typedef typename strage_type::set_type       set_type;
00817         typedef typename strage_type::const_set_type const_set_type;
00818         typedef typename strage_type::size_type      size_type;
00819 
00820         static const size_type invalid_index = strage_type::invalid_index;
00821         static const size_type invalid_way   = strage_type::invalid_way;
00822 
00823         typedef 
00824             setassoc_table_line_base< pair_type > 
00825             line_type;
00826 
00827         // iterator and const iterator.
00828         typedef 
00829             setassoc_table_iterator_base<
00830                 this_type, 
00831                 this_type*,
00832                 line_type
00833             > 
00834             iterator;
00835 
00836         typedef 
00837             setassoc_table_const_iterator_base<
00838                 this_type,
00839                 const this_type*, 
00840                 const line_type, 
00841                 iterator
00842             > 
00843             const_iterator;
00844 
00845 
00846 
00847         // Accessors
00848         size_type set_num() const
00849         {
00850             return (size_type)m_hasher.size();
00851         }
00852 
00853         size_type way_num() const
00854         { 
00855             return m_way_num; 
00856         }
00857 
00858         // size in lines
00859         size_type size() const
00860         {
00861             return set_num() * way_num();
00862         }
00863 
00864 
00865         // Constructors
00866         setassoc_table(
00867             const hasher_type &hasher,
00868             const size_type way_num
00869         ) :
00870             m_replacer(),
00871             m_hasher  ( hasher  ),
00872             m_way_num ( way_num )
00873         {
00874             m_replacer.construct( hasher.size(), way_num ); 
00875             m_strage.resize( hasher.size(), way_num );
00876         }
00877 
00878         ~setassoc_table()
00879         {
00880         }
00881         
00882         // Returns an iterator of a value that corresponds the key.
00883         iterator find( const key_type key )
00884         {
00885             hasher_size_type index = m_hasher.index( key );
00886             key_type tag = m_hasher.tag( key );
00887 
00888             const set_type& set = m_strage.get_set( (size_type)index );
00889             size_type way = set.find( tag );
00890             if( way != invalid_way )
00891                 return iterator( this, index, way );
00892             else
00893                 return end();
00894         }
00895 
00896         // Returns an iterator of a value that corresponds the key.
00897         iterator read( const key_type key, value_type* val = NULL )
00898         {
00899             iterator id = find( key );
00900 
00901             // hit
00902             if( id != end() ){
00903                 if( val ){
00904                     *val = at( id ).value;
00905                 }
00906                 touch( id, key );
00907             }
00908 
00909             return id;
00910         }
00911 
00912         // Returns an iterator of a value that corresponds the key.
00913         iterator write(
00914             const key_type   key, 
00915             const value_type &val    = value_type(),
00916             bool*      ref_replaced      = NULL,
00917             key_type*  ref_replaced_key = NULL,
00918             line_type* ref_replaced_line = NULL
00919         ){
00920             hasher_size_type key_index = index( key );
00921             set_type set = m_strage.get_set( key_index );
00922             bool replaced = false;
00923 
00924             // miss
00925             iterator id = find( key );
00926             if( id == end() ){
00927 
00928                 // Find an invalid way.
00929                 size_type way = set.find_free_way();
00930 
00931                 // Could not find a free way and now replace a valid way.
00932                 if( way == invalid_way ){
00933                     way = m_replacer.target( key_index );
00934                     replaced = true;
00935                 }
00936 
00937                 id = iterator( this, key_index, way );
00938             }
00939 
00940             if( ref_replaced ){
00941                 *ref_replaced = replaced;
00942             }
00943 
00944             if( replaced && ref_replaced_line ){
00945                 *ref_replaced_line = set.at( id.way() );
00946             }
00947 
00948             if( replaced && ref_replaced_key ){
00949                 *ref_replaced_key = m_hasher.rebuild( ref_replaced_line->tag, id.index() );
00950             }
00951 
00952             key_type tag = m_hasher.tag( key );
00953             set.write( id.way(), tag, val );
00954 
00955             touch( id, key );
00956             return id;
00957         }
00958 
00959         // true if hit
00960         iterator invalidate( const key_type key )
00961         {
00962             iterator id = find( key );
00963             if( id != end() && at(id).valid ){
00964                 m_strage.get_set( id.index() ).invalidate( id.way() );
00965             }
00966             return id;
00967         }
00968 
00969         void touch( iterator id, const key_type key )
00970         {
00971             m_replacer.touch( id.index(), id.way(), key );
00972         }
00973 
00974         void clear()
00975         {
00976             for( size_type i = 0; i < set_num(); i++ ){
00977                 m_strage.get_set( i ).clear();
00978             }
00979         }
00980 
00981         hasher_size_type index( const key_type key ) const
00982         {
00983             return m_hasher.index( key );
00984         }
00985 
00986         //
00987         // Access interfaces
00988         //
00989         line_type& at( iterator id )
00990         {
00991             return m_strage.get_set( id.index() ).at( id.way() );
00992         };
00993 
00994         const line_type& at( const_iterator id ) const
00995         {
00996             return m_strage.get_set( id.index() ).at( id.way() );
00997         };
00998 
00999         iterator begin()
01000         {
01001             return iterator( this, 0, 0 );
01002         }
01003 
01004         iterator end()
01005         {
01006             return iterator( this, set_num(), 0 );
01007         }
01008 
01009         const_iterator begin() const
01010         {
01011             return const_iterator( this, 0, 0 );
01012         }
01013 
01014         const_iterator end() const
01015         {
01016             return const_iterator( this, set_num(), 0 );
01017         }
01018 
01019         iterator begin_set( hasher_size_type index )
01020         {
01021             return iterator( this, index, 0 );
01022         }
01023 
01024         iterator end_set( hasher_size_type index )
01025         {
01026             return iterator( this, index+1, 0 );
01027         }
01028 
01029         const_iterator begin_set( hasher_size_type index ) const
01030         {
01031             return const_iterator( this, index, 0 );
01032         }
01033 
01034         const_iterator end_set( hasher_size_type index ) const
01035         {
01036             return const_iterator( this, index+1, 0 );
01037         }
01038 
01039 
01040         //
01041         // setassoc. table only
01042         //
01043         replacer_type& get_replacer()
01044         {
01045             return m_replacer;
01046         };
01047 
01048         hasher_type& get_hasher()
01049         {
01050             return m_hasher;
01051         }
01052 
01053 
01054     protected:
01055 
01056         replacer_type m_replacer;       // replacer object
01057         hasher_type   m_hasher;     // key hasher
01058         size_type     m_way_num;
01059 
01060         strage_type m_strage;       // tag & value & valid
01061 
01062         // Copying setassoc_table is not allowed.
01063         setassoc_table(
01064             const setassoc_table& ref
01065         )
01066         {
01067         }
01068 
01069 
01070     }; // class setassoc_table
01071 
01072 } // namespace shttl
01073 
01074 #endif // SETASSOC_TABLE_H

Onikiri2に対してTue Jun 18 14:34:21 2013に生成されました。  doxygen 1.4.7