diff --git a/ChangeLog b/ChangeLog index 22ec16f81..3c358b85c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -12,6 +12,15 @@ * include/freetype/cache/ftcmru.h, src/cache/ftcmru.c: implement the new convenience function FTC_MruList_RemoveOldest() + * include/freetype/cache/ftcmanag.h, src/cache/ftcint.h, + src/cache/ftcmanag.h: + + introducing FTC_RETRY_LOOP and FTC_RETRY_END and corresponding + functions. + + moving "ftc_node_destroy" to private headers, it's now a local, + non-public, function + 2005-09-21 David Turner * massive redesign of the cache sub-system internals. diff --git a/include/freetype/cache/ftccache.h b/include/freetype/cache/ftccache.h index e4ecde720..e91467714 100644 --- a/include/freetype/cache/ftccache.h +++ b/include/freetype/cache/ftccache.h @@ -79,12 +79,6 @@ FT_BEGIN_HEADER /* cache sub-system internals. */ /* */ - /* reserved for manager's use */ - FT_EXPORT( void ) - ftc_node_destroy( FTC_Node node, - FTC_Manager manager ); - - /*************************************************************************/ /*************************************************************************/ /***** *****/ diff --git a/include/freetype/cache/ftcmanag.h b/include/freetype/cache/ftcmanag.h index f1704c620..88b8720b6 100644 --- a/include/freetype/cache/ftcmanag.h +++ b/include/freetype/cache/ftcmanag.h @@ -95,6 +95,32 @@ FT_BEGIN_HEADER } FTC_ManagerRec; + /* */ + + /* the following function should never be called directly. It is used + * by FTC_RETRY_LOOP described below + */ + FT_EXPORT( void ) + FTC_Manager_RetryStart( FTC_Manager manager ); + + /* the following function should never be called directly. It is used + * by FTC_RETRY_END described below + */ + FT_EXPORT( FT_Bool ) + FTC_Manager_RetryEnd( FTC_Manager manager, + FT_Error error ); + +#define FTC_RETRY_LOOP(m) \ + FT_BEGIN_STMNT \ + FTC_Manager __retry_mgr = (m); \ + \ + FTC_Manager_RetryStart( __retry_mgr ); \ + do \ + { + +#define FTC_RETRY_END(error) \ + } while ( FTC_Manager_RetryEnd( __retry_mgr, (error) ); \ + FT_END_STMNT /*************************************************************************/ /* */ diff --git a/src/cache/ftccache.c b/src/cache/ftccache.c index 793bfefb0..e5969c05d 100644 --- a/src/cache/ftccache.c +++ b/src/cache/ftccache.c @@ -244,7 +244,7 @@ /* remove a node from the cache manager */ - FT_EXPORT_DEF( void ) + FT_LOCAL_DEF( void ) ftc_node_destroy( FTC_Node node, FTC_Manager manager ) { diff --git a/src/cache/ftcmanag.c b/src/cache/ftcmanag.c index 70b0b3519..186e69aa2 100644 --- a/src/cache/ftcmanag.c +++ b/src/cache/ftcmanag.c @@ -23,15 +23,6 @@ #include "ftcerror.h" - FT_EXPORT_DEF( void ) - _ftc_manager_get_debug_info( FTC_Manager manager, - FT_UInt *p_num_caches, - FT_UInt *p_num_nodes, - FT_ULong *p_cur_weight ) - { - } - - #undef FT_COMPONENT #define FT_COMPONENT trace_cache @@ -581,6 +572,23 @@ FT_Memory memory = manager->memory; + /* look for pre-existing cache with same class */ + { + FT_Int nn; + + for ( nn = 0; nn < manager->num_caches; nn++ ) + { + cache = manager->caches[nn]; + + if ( cache->clazz == clazz ) + { + error = 0; + goto Exit; + } + } + cache = NULL; + } + if ( manager->num_caches >= FTC_MAX_CACHES ) { error = FTC_Err_Too_Many_Caches; @@ -663,9 +671,9 @@ { FT_UInt nn; - /* this will remove all FTC_SizeNode that correspond to - * the face_id as well - */ + /* this will remove all FTC_SizeNode that correspond to + * the face_id as well + */ FTC_MruList_RemoveSelection( &manager->faces, NULL, face_id ); for ( nn = 0; nn < manager->num_caches; nn++ ) @@ -684,4 +692,87 @@ } + /* see documentation for FTC_RETRY_LOOP in ftcmanag.h */ + + FT_EXPORT_DEF( void ) + FTC_Manager_RetryStart( FTC_Manager manager ) + { + manager->retry_depth = 1; + manager->retry_num_nodes = 8; + manager->retry_num_faces = 1; + manager->retry_overflow = 0; + } + + /* see documentation for FTC_RETRY_END in ftcmanag.h */ + + FT_EXPORT_DEF( FT_Bool ) + FTC_Manager_RetryEnd( FTC_Manager manager, + FT_Error error ) + { + FT_Bool retry = 0; + FT_UInt count; + + if ( manager->retry_depth > 1 ) + { + manager->retry_depth--; + goto Exit; + } + + if ( error != FTC_Err_Out_Of_Memory || + manager->retry_overflow != 0 ) + goto Exit; + + count = manager->retry_num_nodes; + if ( count > 0 ) + { + if ( FTC_Manager_FlushN( manager, count ) > 0 ) + { + /* FlushN returns > 0 if we could clear some nodes from + * the cache. we compute the size of the next cleanup + * and respond with retry=1 + */ + FT_UInt count2 = count*2; + + if ( count2 < count || count2 > manager->num_nodes ) + count2 = manager->num_nodes; + + manager->retry_num_nodes = count2; + retry = 1; + goto Exit; + } + + /* if FlushN returns 0, there is no more unlocked nodes + * in the cache. se retry_num_nodes to 0, then start + * clearing managed faces. + */ + manager->retry_num_nodes = 0; + } + else + { + /* we try to completely flush the cache, just in case + * client code between RETRY_LOOP and RETRY_END created + * some spurious unlocked nodes. + */ + FTC_Manager_FlushN( manager, manager->num_nodes ); + } + + count = manager->retry_num_faces; + + if ( count >= manager->faces.num_nodes ) + manager->retry_overflow = 1; + + manager->retry_num_faces = count + (count >> 1) + 1; + + for ( ; count > 0; count-- ) + FTC_MruList_RemoveOldest( &manager->faces ); + + retry = 1; + + Exit: + return retry; + } + + + + /* END */