void mlt_cache_purge( mlt_cache cache, void *object ) { if (!cache) return; pthread_mutex_lock( &cache->mutex ); if ( cache && object ) { int i, j; void **alt = cache->current == cache->A ? cache->B : cache->A; for ( i = 0, j = 0; i < cache->count; i++ ) { void *o = cache->current[ i ]; if ( o == object ) { cache_object_close( cache, o, NULL ); } else { alt[ j++ ] = o; } } cache->count = j; cache->current = alt; } pthread_mutex_unlock( &cache->mutex ); }
void mlt_cache_item_close( mlt_cache_item item ) { if ( item ) { pthread_mutex_lock( &item->cache->mutex ); cache_object_close( item->cache, item->object, item->data ); pthread_mutex_unlock( &item->cache->mutex ); } }
void mlt_cache_purge( mlt_cache cache, void *object ) { pthread_mutex_lock( &cache->mutex ); if ( cache && object ) { int i, j; void **alt = cache->current == cache->A ? cache->B : cache->A; for ( i = 0, j = 0; i < cache->count; i++ ) { void *o = cache->current[ i ]; if ( o == object ) { pthread_mutex_unlock( &cache->mutex ); cache_object_close( cache, o, NULL ); pthread_mutex_lock( &cache->mutex ); } else { alt[ j++ ] = o; } } cache->count = j; cache->current = alt; // Remove the object's data from the active list regardless of refcount char key[19]; sprintf( key, "%p", object ); mlt_cache_item item = mlt_properties_get_data( cache->active, key, NULL ); if ( item && item->destructor ) { item->destructor( item->data ); item->data = NULL; item->destructor = NULL; mlt_properties_set_data( cache->active, key, NULL, 0, NULL, NULL ); } // Remove the object's items from the garbage collection regardless of refcount i = mlt_properties_count( cache->garbage ); while ( i-- ) { item = mlt_properties_get_data_at( cache->garbage, i, NULL ); if ( object == item->object && item->destructor ) { sprintf( key, "%p", item->data ); item->destructor( item->data ); item->data = NULL; item->destructor = NULL; mlt_properties_set_data( cache->garbage, key, NULL, 0, NULL, NULL ); } } } pthread_mutex_unlock( &cache->mutex ); }
void mlt_cache_close( mlt_cache cache ) { if ( cache ) { while ( cache->count-- ) { void *object = cache->current[ cache->count ]; mlt_log( NULL, MLT_LOG_DEBUG, "%s: %d = %p\n", __FUNCTION__, cache->count, object ); cache_object_close( cache, object, NULL ); } mlt_properties_close( cache->active ); mlt_properties_close( cache->garbage ); pthread_mutex_destroy( &cache->mutex ); free( cache ); } }
void mlt_cache_put( mlt_cache cache, void *object, void* data, int size, mlt_destructor destructor ) { pthread_mutex_lock( &cache->mutex ); void **hit = shuffle_get_hit( cache, object ); void **alt = cache->current == cache->A ? cache->B : cache->A; // add the object to the cache if ( hit ) { // release the old data pthread_mutex_unlock( &cache->mutex ); cache_object_close( cache, *hit, NULL ); pthread_mutex_lock( &cache->mutex ); // the MRU end gets the updated data hit = &alt[ cache->count - 1 ]; } else if ( cache->count < CACHE_SIZE ) { // more room in cache, add it to MRU end hit = &alt[ cache->count++ ]; } else { // release the entry at the LRU end pthread_mutex_unlock( &cache->mutex ); cache_object_close( cache, cache->current[0], NULL ); pthread_mutex_lock( &cache->mutex ); // The MRU end gets the new item hit = &alt[ cache->count - 1 ]; } *hit = object; mlt_log( NULL, MLT_LOG_DEBUG, "%s: put %d = %p, %p\n", __FUNCTION__, cache->count - 1, object, data ); // Fetch the cache item char key[19]; sprintf( key, "%p", object ); mlt_cache_item item = mlt_properties_get_data( cache->active, key, NULL ); if ( !item ) { item = calloc( 1, sizeof( mlt_cache_item_s ) ); if ( item ) mlt_properties_set_data( cache->active, key, item, 0, free, NULL ); } if ( item ) { // If updating the cache item but not all references are released // copy the item to the garbage collection. if ( item->refcount > 0 && item->data ) { mlt_cache_item orphan = calloc( 1, sizeof( mlt_cache_item_s ) ); if ( orphan ) { mlt_log( NULL, MLT_LOG_DEBUG, "adding to garbage collection object %p data %p\n", item->object, item->data ); *orphan = *item; sprintf( key, "%p", orphan->data ); // We store in the garbage collection by data address, not the owner's! mlt_properties_set_data( cache->garbage, key, orphan, 0, free, NULL ); } } // Set/update the cache item item->cache = cache; item->object = object; item->data = data; item->size = size; item->destructor = destructor; item->refcount = 1; } // swap the current array cache->current = alt; pthread_mutex_unlock( &cache->mutex ); }
void mlt_cache_item_close( mlt_cache_item item ) { if ( item ) cache_object_close( item->cache, item->object, item->data ); }