⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ftccache.c

📁 下载来的一个看图软件的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
  FT_EXPORT_DEF( void )  ftc_family_done( FTC_Family  family )  {    if ( family && family->cache )    {      FTC_Manager  manager = family->cache->manager;      /* remove from manager's family table */      ftc_family_table_free( &manager->families, family->fam_index );    }  }  /*************************************************************************/  /*************************************************************************/  /*****                                                               *****/  /*****                    ABSTRACT CACHE CLASS                       *****/  /*****                                                               *****/  /*************************************************************************/  /*************************************************************************/  FT_EXPORT_DEF( FT_Error )  ftc_cache_init( FTC_Cache  cache )  {    FT_Memory        memory = cache->memory;    FTC_Cache_Class  clazz  = cache->clazz;    FT_Error         error;    cache->p     = 0;    cache->mask  = FTC_HASH_INITIAL_SIZE - 1;    cache->slack = FTC_HASH_INITIAL_SIZE * FTC_HASH_MAX_LOAD;    if ( FT_NEW_ARRAY( cache->buckets, FTC_HASH_INITIAL_SIZE * 2 ) )      goto Exit;    /* now, initialize the lru list of families for this cache */    if ( clazz->family_size > 0 )    {      FT_LruList_ClassRec*  lru_class = &cache->family_class;      lru_class->list_size = sizeof( FT_LruListRec );      lru_class->list_init = NULL;      lru_class->list_done = NULL;      lru_class->node_size    = clazz->family_size;      lru_class->node_init    = (FT_LruNode_InitFunc)   clazz->family_init;      lru_class->node_done    = (FT_LruNode_DoneFunc)   clazz->family_done;      lru_class->node_flush   = (FT_LruNode_FlushFunc)  NULL;      lru_class->node_compare = (FT_LruNode_CompareFunc)clazz->family_compare;      error = FT_LruList_New( (FT_LruList_Class) lru_class,                              0,    /* max items == 0 => unbounded list */                              cache,                              memory,                              &cache->families );      if ( error )        FT_FREE( cache->buckets );    }  Exit:    return error;  }  FT_EXPORT_DEF( void )  ftc_cache_clear( FTC_Cache  cache )  {    if ( cache )    {      FT_Memory        memory  = cache->memory;      FTC_Cache_Class  clazz   = cache->clazz;      FTC_Manager      manager = cache->manager;      FT_UFast         i;      FT_UInt          count;      count = cache->p + cache->mask + 1;      for ( i = 0; i < count; i++ )      {        FTC_Node  *pnode = cache->buckets + i, next, node = *pnode;        while ( node )        {          next        = node->link;          node->link  = NULL;          /* remove node from mru list */          ftc_node_mru_unlink( node, manager );          /* now finalize it */          manager->cur_weight -= clazz->node_weight( node, cache );          if ( clazz->node_done )            clazz->node_done( node, cache );          FT_FREE( node );          node = next;        }        cache->buckets[i] = NULL;      }      cache->p = 0;      /* destroy the families */      if ( cache->families )        FT_LruList_Reset( cache->families );    }  }  FT_EXPORT_DEF( void )  ftc_cache_done( FTC_Cache  cache )  {    if ( cache )    {      FT_Memory  memory = cache->memory;      ftc_cache_clear( cache );      FT_FREE( cache->buckets );      cache->mask  = 0;      cache->slack = 0;      if ( cache->families )      {        FT_LruList_Destroy( cache->families );        cache->families = NULL;      }    }  }  /* Look up a node in "top" of its cache's hash table. */  /* If not found, create a new node.                   */  /*                                                    */  FT_EXPORT_DEF( FT_Error )  ftc_cache_lookup( FTC_Cache   cache,                    FTC_Query   query,                    FTC_Node   *anode )  {    FT_Error     error = FTC_Err_Ok;    FTC_Manager  manager;    FT_LruNode   lru;    FT_UInt      free_count = 0;    if ( !cache || !query || !anode )      return FTC_Err_Invalid_Argument;    *anode = NULL;    query->hash   = 0;    query->family = NULL;    manager = cache->manager;   /*  here's a small note explaining what's happening in the code below.    *    *  We need to deal intelligently with out-of-memory (OOM) conditions    *  when trying to create a new family or cache node during the lookup.    *    *  When an OOM is detected, we try to free one or more "old" nodes    *  from the cache, then try again.  It may be necessary to do that    *  several times, so a loop is needed.    *    *  The local variable "free_count" holds the number of "old" nodes to    *  discard on each attempt.  It starts at 1 and doubles on each    *  iteration.  The loop stops when:    *    *   - a non-OOM error is detected    *   - a succesful lookup is performed    *   - there are no more unused nodes in the cache    *    *  For the record, remember that all used nodes appear _before_    *  unused ones in the manager's MRU node list.    */    for (;;)    {      {        /* first of all, find the relevant family */        FT_LruList              list    = cache->families;        FT_LruNode              fam, *pfam;        FT_LruNode_CompareFunc  compare = list->clazz->node_compare;        pfam = &list->nodes;        for (;;)        {          fam = *pfam;          if ( fam == NULL )          {            error = FT_LruList_Lookup( list, query, &lru );            if ( error )              goto Fail;            goto Skip;          }          if ( compare( fam, query, list->data ) )            break;          pfam = &fam->next;        }        FT_ASSERT( fam != NULL );        /* move to top of list when needed */        if ( fam != list->nodes )        {          *pfam       = fam->next;          fam->next   = list->nodes;          list->nodes = fam;        }        lru = fam;      Skip:        ;      }      {        FTC_Family   family  = (FTC_Family) lru;        FT_UFast     hash    = query->hash;        FTC_Node*    bucket;        FT_UInt      idx;        idx = hash & cache->mask;        if ( idx < cache->p )          idx = hash & ( cache->mask * 2 + 1 );        bucket  = cache->buckets + idx;        if ( query->family     != family                 ||             family->fam_index >= manager->families.size )        {          FT_ERROR((            "ftc_cache_lookup: invalid query (bad 'family' field)\n" ));          error = FTC_Err_Invalid_Argument;          goto Exit;        }        if ( *bucket )        {          FTC_Node*             pnode   = bucket;          FTC_Node_CompareFunc  compare = cache->clazz->node_compare;          for ( ;; )          {            FTC_Node  node;            node = *pnode;            if ( node == NULL )              break;            if ( node->hash == hash                            &&                 (FT_UInt)node->fam_index == family->fam_index &&                 compare( node, query, cache ) )            {              /* move to head of bucket list */              if ( pnode != bucket )              {                *pnode     = node->link;                node->link = *bucket;                *bucket    = node;              }              /* move to head of MRU list */              if ( node != manager->nodes_list )                ftc_node_mru_up( node, manager );              *anode = node;              goto Exit;            }            pnode = &node->link;          }        }        /* didn't find a node, create a new one */        {          FTC_Cache_Class  clazz   = cache->clazz;          FT_Memory        memory  = cache->memory;          FTC_Node         node;          if ( FT_ALLOC( node, clazz->node_size ) )            goto Fail;          node->fam_index = (FT_UShort) family->fam_index;          node->hash      = query->hash;          node->ref_count = 0;          error = clazz->node_init( node, query, cache );          if ( error )          {            FT_FREE( node );            goto Fail;          }          error = ftc_node_hash_link( node, cache );          if ( error )          {            clazz->node_done( node, cache );            FT_FREE( node );            goto Fail;          }          ftc_node_mru_link( node, cache->manager );          cache->manager->cur_weight += clazz->node_weight( node, cache );          /* now try to compress the node pool when necessary */          if ( manager->cur_weight >= manager->max_weight )          {            node->ref_count++;            FTC_Manager_Compress( manager );            node->ref_count--;          }          *anode = node;        }       /* all is well, exit now        */        goto Exit;      }    Fail:      if ( error != FTC_Err_Out_Of_Memory )        goto Exit;     /* There is not enough memory; try to release some unused nodes      * from the cache to make room for a new one.      */      {        FT_UInt  new_count;        new_count = 1 + free_count * 2;        /* check overflow and bounds */        if ( new_count < free_count || free_count > manager->num_nodes )          goto Exit;        free_count = new_count;        /* try to remove "new_count" nodes from the list */        {          FTC_Node  first = manager->nodes_list;          FTC_Node  node;          if ( first == NULL )  /* empty list! */            goto Exit;          /* go to last node - it's a circular list */          node = first->mru_prev;          for ( ; node && new_count > 0; new_count-- )          {            FTC_Node  prev = node->mru_prev;            /* Used nodes always appear before unused one in the MRU             * list.  If we find one here, we'd better stop right now             * our iteration.             */            if ( node->ref_count > 0 )            {              /* if there are no unused nodes in the list, we'd better exit */              if ( new_count == free_count )                goto Exit;              break;            }            ftc_node_destroy( node, manager );            if ( node == first )              break;            node = prev;          }        }      }    }  Exit:    return error;  }/* END */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -