00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #ifndef __FTCCACHE_H__
00020 #define __FTCCACHE_H__
00021
00022
00023 #include "ftcmru.h"
00024
00025 FT_BEGIN_HEADER
00026
00027
00028 typedef struct FTC_CacheRec_* FTC_Cache;
00029
00030
00031 typedef const struct FTC_CacheClassRec_* FTC_CacheClass;
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055 typedef struct FTC_NodeRec_
00056 {
00057 FTC_MruNodeRec mru;
00058 FTC_Node link;
00059 FT_UInt32 hash;
00060 FT_UShort cache_index;
00061 FT_Short ref_count;
00062
00063 } FTC_NodeRec;
00064
00065
00066 #define FTC_NODE( x ) ( (FTC_Node)(x) )
00067 #define FTC_NODE_P( x ) ( (FTC_Node*)(x) )
00068
00069 #define FTC_NODE__NEXT( x ) FTC_NODE( (x)->mru.next )
00070 #define FTC_NODE__PREV( x ) FTC_NODE( (x)->mru.prev )
00071
00072
00073 #ifdef FT_CONFIG_OPTION_OLD_INTERNALS
00074 FT_BASE( void )
00075 ftc_node_destroy( FTC_Node node,
00076 FTC_Manager manager );
00077 #endif
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089 typedef FT_Error
00090 (*FTC_Node_NewFunc)( FTC_Node *pnode,
00091 FT_Pointer query,
00092 FTC_Cache cache );
00093
00094 typedef FT_Offset
00095 (*FTC_Node_WeightFunc)( FTC_Node node,
00096 FTC_Cache cache );
00097
00098
00099 typedef FT_Bool
00100 (*FTC_Node_CompareFunc)( FTC_Node node,
00101 FT_Pointer key,
00102 FTC_Cache cache );
00103
00104
00105 typedef void
00106 (*FTC_Node_FreeFunc)( FTC_Node node,
00107 FTC_Cache cache );
00108
00109 typedef FT_Error
00110 (*FTC_Cache_InitFunc)( FTC_Cache cache );
00111
00112 typedef void
00113 (*FTC_Cache_DoneFunc)( FTC_Cache cache );
00114
00115
00116 typedef struct FTC_CacheClassRec_
00117 {
00118 FTC_Node_NewFunc node_new;
00119 FTC_Node_WeightFunc node_weight;
00120 FTC_Node_CompareFunc node_compare;
00121 FTC_Node_CompareFunc node_remove_faceid;
00122 FTC_Node_FreeFunc node_free;
00123
00124 FT_Offset cache_size;
00125 FTC_Cache_InitFunc cache_init;
00126 FTC_Cache_DoneFunc cache_done;
00127
00128 } FTC_CacheClassRec;
00129
00130
00131
00132 typedef struct FTC_CacheRec_
00133 {
00134 FT_UFast p;
00135 FT_UFast mask;
00136 FT_Long slack;
00137 FTC_Node* buckets;
00138
00139 FTC_CacheClassRec clazz;
00140
00141 FTC_Manager manager;
00142 FT_Memory memory;
00143 FT_UInt index;
00144
00145 FTC_CacheClass org_class;
00146
00147 } FTC_CacheRec;
00148
00149
00150 #define FTC_CACHE( x ) ( (FTC_Cache)(x) )
00151 #define FTC_CACHE_P( x ) ( (FTC_Cache*)(x) )
00152
00153
00154
00155 FT_LOCAL( FT_Error )
00156 FTC_Cache_Init( FTC_Cache cache );
00157
00158
00159 FT_LOCAL( void )
00160 FTC_Cache_Done( FTC_Cache cache );
00161
00162
00163
00164
00165
00166
00167
00168 #ifndef FTC_INLINE
00169 FT_LOCAL( FT_Error )
00170 FTC_Cache_Lookup( FTC_Cache cache,
00171 FT_UInt32 hash,
00172 FT_Pointer query,
00173 FTC_Node *anode );
00174 #endif
00175
00176 FT_LOCAL( FT_Error )
00177 FTC_Cache_NewNode( FTC_Cache cache,
00178 FT_UInt32 hash,
00179 FT_Pointer query,
00180 FTC_Node *anode );
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192 FT_LOCAL( void )
00193 FTC_Cache_RemoveFaceID( FTC_Cache cache,
00194 FTC_FaceID face_id );
00195
00196
00197 #ifdef FTC_INLINE
00198
00199 #define FTC_CACHE_LOOKUP_CMP( cache, nodecmp, hash, query, node, error ) \
00200 FT_BEGIN_STMNT \
00201 FTC_Node *_bucket, *_pnode, _node; \
00202 FTC_Cache _cache = FTC_CACHE(cache); \
00203 FT_UInt32 _hash = (FT_UInt32)(hash); \
00204 FTC_Node_CompareFunc _nodcomp = (FTC_Node_CompareFunc)(nodecmp); \
00205 FT_UFast _idx; \
00206 \
00207 \
00208 error = 0; \
00209 node = NULL; \
00210 _idx = _hash & _cache->mask; \
00211 if ( _idx < _cache->p ) \
00212 _idx = _hash & ( _cache->mask*2 + 1 ); \
00213 \
00214 _bucket = _pnode = _cache->buckets + _idx; \
00215 for (;;) \
00216 { \
00217 _node = *_pnode; \
00218 if ( _node == NULL ) \
00219 goto _NewNode; \
00220 \
00221 if ( _node->hash == _hash && _nodcomp( _node, query, _cache ) ) \
00222 break; \
00223 \
00224 _pnode = &_node->link; \
00225 } \
00226 \
00227 if ( _node != *_bucket ) \
00228 { \
00229 *_pnode = _node->link; \
00230 _node->link = *_bucket; \
00231 *_bucket = _node; \
00232 } \
00233 \
00234 { \
00235 FTC_Manager _manager = _cache->manager; \
00236 void* _nl = &_manager->nodes_list; \
00237 \
00238 \
00239 if ( _node != _manager->nodes_list ) \
00240 FTC_MruNode_Up( (FTC_MruNode*)_nl, \
00241 (FTC_MruNode)_node ); \
00242 } \
00243 goto _Ok; \
00244 \
00245 _NewNode: \
00246 error = FTC_Cache_NewNode( _cache, _hash, query, &_node ); \
00247 \
00248 _Ok: \
00249 node = _node; \
00250 FT_END_STMNT
00251
00252 #else
00253
00254 #define FTC_CACHE_LOOKUP_CMP( cache, nodecmp, hash, query, node, error ) \
00255 FT_BEGIN_STMNT \
00256 error = FTC_Cache_Lookup( FTC_CACHE( cache ), hash, query, \
00257 (FTC_Node*)&(node) ); \
00258 FT_END_STMNT
00259
00260 #endif
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279 #define FTC_CACHE_TRYLOOP( cache ) \
00280 { \
00281 FTC_Manager _try_manager = FTC_CACHE( cache )->manager; \
00282 FT_UInt _try_count = 4; \
00283 \
00284 \
00285 for (;;) \
00286 { \
00287 FT_UInt _try_done;
00288
00289
00290 #define FTC_CACHE_TRYLOOP_END() \
00291 if ( !error || error != FT_Err_Out_Of_Memory ) \
00292 break; \
00293 \
00294 _try_done = FTC_Manager_FlushN( _try_manager, _try_count ); \
00295 if ( _try_done == 0 ) \
00296 break; \
00297 \
00298 if ( _try_done == _try_count ) \
00299 { \
00300 _try_count *= 2; \
00301 if ( _try_count < _try_done || \
00302 _try_count > _try_manager->num_nodes ) \
00303 _try_count = _try_manager->num_nodes; \
00304 } \
00305 } \
00306 }
00307
00308
00309
00310 FT_END_HEADER
00311
00312
00313 #endif
00314
00315
00316