[cache] Notice if a cache query induced the node list change.

Some node comparators (comparing the cache node content and
the properties specified by the query) can flush the cache
node to prevent the cache inflation.  The change may
invalidate the pointers to the node obtained before the node
comparison, so the change should be noticed to the caller.
The problem caused by the cache node changing is reported by
Harsha, see Savannah bug #31923.

* src/cache/ftccache.h (FTC_Node_CompareFunc): Add new
argument `FT_Bool* list_changed' to indicate the change of
the cached nodes to the caller.
(FTC_CACHE_LOOKUP_CMP): Watch the change of the cached nodes
by `_list_changed'.
(FTC_CACHE_TRYLOOP_END): Take new macro argument `_list_changed'
and update it when FTC_Manager_FlushN() flushes any nodes.

* src/cache/ftccback.h (ftc_snode_compare): Updated to fit
with new FTC_Node_CompareFunc type.  (ftc_gnode_compare): Ditto.

* src/cache/ftcbasic.c: Include FT_INTERNAL_OBJECTS_H to
use TRUE/FALSE macros.  (ftc_basic_gnode_compare_faceid):
New argument `FT_Bool* list_changed' to indicate the change
of the cache nodes, anyway, it is always FALSE.

* src/cache/ftccmap.c: Include FT_INTERNAL_OBJECTS_H to
use TRUE/FALSE macros.  (ftc_cmap_node_compare):
New argument `FT_Bool* list_changed' to indicate the change
of the cache nodes, anyway, it is always FALSE.
(ftc_cmap_node_remove_faceid): Ditto.

* src/cache/ftccache.c (FTC_Cache_NewNode): Pass a NULL
pointer to FTC_CACHE_TRYLOOP_END(), because the result is
not needed.  (FTC_Cache_Lookup): Watch the change of the cache
nodes by `list_changed'.  (FTC_Cache_RemoveFaceID): Ditto.

* src/cache/ftcglyph.c: Include FT_INTERNAL_OBJECTS_H to
use TRUE/FALSE macros.  (ftc_gnode_compare): New argument
`FT_Bool* list_changed' to indicate the change of the cache
nodes, anyway, it is always FALSE.  (FTC_GNode_Compare):
New argument `FT_Bool* list_changed' to be passed to
ftc_gnode_compare().
* src/cache/ftcglyph.h (FTC_GNode_Compare): Ditto.

* src/cache/ftcsbits.c (ftc_snode_compare): New argument
`FT_Bool* list_changed' to indicate the change of the cache
nodes, anyway. It is updated by FTC_CACHE_TRYLOOP().
(FTC_SNode_Compare): New argument `FT_Bool* list_changed'
to be passed to ftc_snode_compare().
* src/cache/ftcsbits.h (FTC_SNode_Compare): Ditto.
This commit is contained in:
suzuki toshiya 2011-01-09 22:49:07 +09:00
parent 62d116f8d6
commit 38b272ffbb
10 changed files with 107 additions and 20 deletions

View File

@ -1,3 +1,57 @@
2010-01-09 suzuki toshiya <mpsuzuki@hiroshima-u.ac.jp>
[cache] Notice if a cache query induced the node list change.
Some node comparators (comparing the cache node content and
the properties specified by the query) can flush the cache
node to prevent the cache inflation. The change may
invalidate the pointers to the node obtained before the node
comparison, so the change should be noticed to the caller.
The problem caused by the cache node changing is reported by
Harsha, see Savannah bug #31923.
* src/cache/ftccache.h (FTC_Node_CompareFunc): Add new
argument `FT_Bool* list_changed' to indicate the change of
the cached nodes to the caller.
(FTC_CACHE_LOOKUP_CMP): Watch the change of the cached nodes
by `_list_changed'.
(FTC_CACHE_TRYLOOP_END): Take new macro argument `_list_changed'
and update it when FTC_Manager_FlushN() flushes any nodes.
* src/cache/ftccback.h (ftc_snode_compare): Updated to fit
with new FTC_Node_CompareFunc type. (ftc_gnode_compare): Ditto.
* src/cache/ftcbasic.c: Include FT_INTERNAL_OBJECTS_H to
use TRUE/FALSE macros. (ftc_basic_gnode_compare_faceid):
New argument `FT_Bool* list_changed' to indicate the change
of the cache nodes, anyway, it is always FALSE.
* src/cache/ftccmap.c: Include FT_INTERNAL_OBJECTS_H to
use TRUE/FALSE macros. (ftc_cmap_node_compare):
New argument `FT_Bool* list_changed' to indicate the change
of the cache nodes, anyway, it is always FALSE.
(ftc_cmap_node_remove_faceid): Ditto.
* src/cache/ftccache.c (FTC_Cache_NewNode): Pass a NULL
pointer to FTC_CACHE_TRYLOOP_END(), because the result is
not needed. (FTC_Cache_Lookup): Watch the change of the cache
nodes by `list_changed'. (FTC_Cache_RemoveFaceID): Ditto.
* src/cache/ftcglyph.c: Include FT_INTERNAL_OBJECTS_H to
use TRUE/FALSE macros. (ftc_gnode_compare): New argument
`FT_Bool* list_changed' to indicate the change of the cache
nodes, anyway, it is always FALSE. (FTC_GNode_Compare):
New argument `FT_Bool* list_changed' to be passed to
ftc_gnode_compare().
* src/cache/ftcglyph.h (FTC_GNode_Compare): Ditto.
* src/cache/ftcsbits.c (ftc_snode_compare): New argument
`FT_Bool* list_changed' to indicate the change of the cache
nodes, anyway. It is updated by FTC_CACHE_TRYLOOP().
(FTC_SNode_Compare): New argument `FT_Bool* list_changed'
to be passed to ftc_snode_compare().
* src/cache/ftcsbits.h (FTC_SNode_Compare): Ditto.
2010-01-09 suzuki toshiya <mpsuzuki@hiroshima-u.ac.jp>
[cache] Fit FTC_GNode_Compare() to FTC_Node_CompareFunc.

View File

@ -17,6 +17,7 @@
#include <ft2build.h>
#include FT_INTERNAL_OBJECTS_H
#include FT_INTERNAL_DEBUG_H
#include FT_CACHE_H
#include "ftcglyph.h"
@ -237,7 +238,8 @@
FT_CALLBACK_DEF( FT_Bool )
ftc_basic_gnode_compare_faceid( FTC_Node ftcgnode,
FT_Pointer ftcface_id,
FTC_Cache cache )
FTC_Cache cache,
FT_Bool* list_changed )
{
FTC_GNode gnode = (FTC_GNode)ftcgnode;
FTC_FaceID face_id = (FTC_FaceID)ftcface_id;
@ -245,6 +247,8 @@
FT_Bool result;
if ( list_changed )
*list_changed = FALSE;
result = FT_BOOL( family->attrs.scaler.face_id == face_id );
if ( result )
{

View File

@ -461,7 +461,7 @@
{
error = cache->clazz.node_new( &node, query, cache );
}
FTC_CACHE_TRYLOOP_END();
FTC_CACHE_TRYLOOP_END( NULL );
if ( error )
node = NULL;
@ -490,6 +490,7 @@
FTC_Node* pnode;
FTC_Node node;
FT_Error error = FTC_Err_Ok;
FT_Bool list_changed = FALSE;
FTC_Node_CompareFunc compare = cache->clazz.node_compare;
@ -504,7 +505,8 @@
if ( node == NULL )
goto NewNode;
if ( node->hash == hash && compare( node, query, cache ) )
if ( node->hash == hash &&
compare( node, query, cache, &list_changed ) )
break;
pnode = &node->link;
@ -554,12 +556,13 @@
for ( ;; )
{
FTC_Node node = *pnode;
FT_Bool list_changed = FALSE;
if ( node == NULL )
break;
if ( cache->clazz.node_remove_faceid( node, face_id, cache ) )
if ( cache->clazz.node_remove_faceid( node, face_id, cache, &list_changed ) )
{
*pnode = node->link;
node->link = frees;

12
src/cache/ftccache.h vendored
View File

@ -115,7 +115,8 @@ FT_BEGIN_HEADER
typedef FT_Bool
(*FTC_Node_CompareFunc)( FTC_Node node,
FT_Pointer key,
FTC_Cache cache );
FTC_Cache cache,
FT_Bool* list_changed );
typedef void
@ -218,6 +219,7 @@ FT_BEGIN_HEADER
FTC_Cache _cache = FTC_CACHE(cache); \
FT_PtrDist _hash = (FT_PtrDist)(hash); \
FTC_Node_CompareFunc _nodcomp = (FTC_Node_CompareFunc)(nodecmp); \
FT_Bool _list_changed = FALSE; \
\
\
error = FTC_Err_Ok; \
@ -230,7 +232,8 @@ FT_BEGIN_HEADER
if ( _node == NULL ) \
goto _NewNode; \
\
if ( _node->hash == _hash && _nodcomp( _node, query, _cache ) ) \
if ( _node->hash == _hash && \
_nodcomp( _node, query, _cache, &_list_changed ) ) \
break; \
\
_pnode = &_node->link; \
@ -299,11 +302,14 @@ FT_BEGIN_HEADER
FT_UInt _try_done;
#define FTC_CACHE_TRYLOOP_END() \
#define FTC_CACHE_TRYLOOP_END( list_changed ) \
if ( !error || error != FTC_Err_Out_Of_Memory ) \
break; \
\
_try_done = FTC_Manager_FlushN( _try_manager, _try_count ); \
if ( _try_done > 0 && ( list_changed ) ) \
*(FT_Bool*)( list_changed ) = TRUE; \
\
if ( _try_done == 0 ) \
break; \
\

View File

@ -57,13 +57,15 @@
FT_LOCAL( FT_Bool )
ftc_snode_compare( FTC_Node snode,
FT_Pointer gquery,
FTC_Cache cache );
FTC_Cache cache,
FT_Bool* list_changed );
FT_LOCAL( FT_Bool )
ftc_gnode_compare( FTC_Node gnode,
FT_Pointer gquery,
FTC_Cache cache );
FTC_Cache cache,
FT_Bool* list_changed );
FT_LOCAL( FT_Error )

11
src/cache/ftccmap.c vendored
View File

@ -22,6 +22,7 @@
#include FT_CACHE_H
#include "ftcmanag.h"
#include FT_INTERNAL_MEMORY_H
#include FT_INTERNAL_OBJECTS_H
#include FT_INTERNAL_DEBUG_H
#include "ftccback.h"
@ -190,13 +191,16 @@
FT_CALLBACK_DEF( FT_Bool )
ftc_cmap_node_compare( FTC_Node ftcnode,
FT_Pointer ftcquery,
FTC_Cache cache )
FTC_Cache cache,
FT_Bool* list_changed )
{
FTC_CMapNode node = (FTC_CMapNode)ftcnode;
FTC_CMapQuery query = (FTC_CMapQuery)ftcquery;
FT_UNUSED( cache );
if ( list_changed )
*list_changed = FALSE;
if ( node->face_id == query->face_id &&
node->cmap_index == query->cmap_index )
{
@ -213,12 +217,15 @@
FT_CALLBACK_DEF( FT_Bool )
ftc_cmap_node_remove_faceid( FTC_Node ftcnode,
FT_Pointer ftcface_id,
FTC_Cache cache )
FTC_Cache cache,
FT_Bool* list_changed )
{
FTC_CMapNode node = (FTC_CMapNode)ftcnode;
FTC_FaceID face_id = (FTC_FaceID)ftcface_id;
FT_UNUSED( cache );
if ( list_changed )
*list_changed = FALSE;
return FT_BOOL( node->face_id == face_id );
}

11
src/cache/ftcglyph.c vendored
View File

@ -17,6 +17,7 @@
#include <ft2build.h>
#include FT_INTERNAL_OBJECTS_H
#include FT_CACHE_H
#include "ftcglyph.h"
#include FT_ERRORS_H
@ -64,13 +65,16 @@
FT_LOCAL_DEF( FT_Bool )
ftc_gnode_compare( FTC_Node ftcgnode,
FT_Pointer ftcgquery,
FTC_Cache cache )
FTC_Cache cache,
FT_Bool* list_changed )
{
FTC_GNode gnode = (FTC_GNode)ftcgnode;
FTC_GQuery gquery = (FTC_GQuery)ftcgquery;
FT_UNUSED( cache );
if ( list_changed )
*list_changed = FALSE;
return FT_BOOL( gnode->family == gquery->family &&
gnode->gindex == gquery->gindex );
}
@ -81,9 +85,10 @@
FT_LOCAL_DEF( FT_Bool )
FTC_GNode_Compare( FTC_GNode gnode,
FTC_GQuery gquery,
FTC_Cache cache )
FTC_Cache cache,
FT_Bool* list_changed )
{
return ftc_gnode_compare( FTC_NODE( gnode ), gquery, cache );
return ftc_gnode_compare( FTC_NODE( gnode ), gquery, cache, list_changed );
}
#endif

View File

@ -188,7 +188,8 @@ FT_BEGIN_HEADER
FT_LOCAL( FT_Bool )
FTC_GNode_Compare( FTC_GNode gnode,
FTC_GQuery gquery,
FTC_Cache cache );
FTC_Cache cache,
FT_Bool* list_changed );
#endif

12
src/cache/ftcsbits.c vendored
View File

@ -324,7 +324,8 @@
FT_LOCAL_DEF( FT_Bool )
ftc_snode_compare( FTC_Node ftcsnode,
FT_Pointer ftcgquery,
FTC_Cache cache )
FTC_Cache cache,
FT_Bool* list_changed )
{
FTC_SNode snode = (FTC_SNode)ftcsnode;
FTC_GQuery gquery = (FTC_GQuery)ftcgquery;
@ -333,6 +334,8 @@
FT_Bool result;
if (list_changed)
*list_changed = FALSE;
result = FT_BOOL( gnode->family == gquery->family &&
(FT_UInt)( gindex - gnode->gindex ) < snode->count );
if ( result )
@ -386,7 +389,7 @@
{
error = ftc_snode_load( snode, cache->manager, gindex, &size );
}
FTC_CACHE_TRYLOOP_END();
FTC_CACHE_TRYLOOP_END( list_changed );
ftcsnode->ref_count--; /* unlock the node */
@ -406,9 +409,10 @@
FT_LOCAL_DEF( FT_Bool )
FTC_SNode_Compare( FTC_SNode snode,
FTC_GQuery gquery,
FTC_Cache cache )
FTC_Cache cache,
FT_Bool* list_changed )
{
return ftc_snode_compare( FTC_NODE( snode ), gquery, cache );
return ftc_snode_compare( FTC_NODE( snode ), gquery, cache, list_changed );
}
#endif

View File

@ -88,7 +88,8 @@ FT_BEGIN_HEADER
FT_LOCAL( FT_Bool )
FTC_SNode_Compare( FTC_SNode snode,
FTC_GQuery gquery,
FTC_Cache cache );
FTC_Cache cache,
FT_Bool* list_changed);
#endif