int cache_create(size_t concurrency, size_t capacity, uint64_t duration, void (*destroy_cb)(h2o_iovec_t value), cache_t *cache) { memset(cache, 0, sizeof(*cache)); assert(is_power_of_2(CONCURRENCY_FACTOR)); // Rounding up to a power of 2 simplifies the calculations a little bit, and, as any increase in // the number of caches, potentially reduces thread contention. cache->cache_num = CONCURRENCY_FACTOR * round_up_to_power_of_2(concurrency); cache->cache_num = MAX(cache->cache_num, 1); capacity = (capacity + cache->cache_num - 1) / cache->cache_num; pthread_mutexattr_t attr; if (pthread_mutexattr_init(&attr)) return EXIT_FAILURE; if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ADAPTIVE_NP)) goto error; cache->cache = malloc(cache->cache_num * sizeof(*cache->cache)); if (!cache->cache) goto error; cache->cache_lock = malloc(cache->cache_num * sizeof(*cache->cache_lock)); if (!cache->cache_lock) goto error_malloc; for (size_t i = 0; i < cache->cache_num; i++) { cache->cache[i] = h2o_cache_create(0, capacity, duration, destroy_cb); if (!cache->cache[i] || pthread_mutex_init(cache->cache_lock + i, &attr)) { if (cache->cache[i]) h2o_cache_destroy(cache->cache[i]); cache->cache_num = i; cache_destroy(cache); goto error; } } pthread_mutexattr_destroy(&attr); return EXIT_SUCCESS; error_malloc: free(cache->cache); error: pthread_mutexattr_destroy(&attr); return EXIT_FAILURE; }
void cache_destroy(cache_t *cache) { if (cache->cache) { assert(cache->cache_lock); for (size_t i = 0; i < cache->cache_num; i++) { h2o_cache_destroy(cache->cache[i]); pthread_mutex_destroy(cache->cache_lock + i); } free(cache->cache); free(cache->cache_lock); cache->cache = NULL; cache->cache_lock = NULL; } else assert(!cache->cache_lock); }
static void on_dispose_ssl_ctx_ex_data(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp) { h2o_cache_t *ssl_session_cache = (h2o_cache_t *)ptr; if (ssl_session_cache != NULL) h2o_cache_destroy(ssl_session_cache); }