+static inline http_persistent_handle_list *http_persistent_handle_list_init(http_persistent_handle_list *list)
+{
+ int free_list;
+
+ if ((free_list = !list)) {
+ list = pemalloc(sizeof(http_persistent_handle_list), 1);
+ }
+
+ list->used = 0;
+
+ if (SUCCESS != zend_hash_init(&list->free, 0, NULL, NULL, 1)) {
+ if (free_list) {
+ pefree(list, 1);
+ }
+ list = NULL;
+ }
+
+ return list;
+}
+
+static inline void http_persistent_handle_list_dtor(http_persistent_handle_list *list, http_persistent_handle_dtor dtor)
+{
+ HashPosition pos;
+ void **handle;
+
+#if HTTP_DEBUG_PHANDLES
+ fprintf(stderr, "LSTDTOR: %p\n", list);
+#endif
+ FOREACH_HASH_VAL(pos, &list->free, handle) {
+#if HTTP_DEBUG_PHANDLES
+ fprintf(stderr, "DESTROY: %p\n", *handle);
+#endif
+
+ dtor(*handle);
+ }
+ zend_hash_destroy(&list->free);
+}
+
+static inline void http_persistent_handle_list_free(http_persistent_handle_list **list, http_persistent_handle_dtor dtor)
+{
+ http_persistent_handle_list_dtor(*list, dtor);
+#if HTTP_DEBUG_PHANDLES
+ fprintf(stderr, "LSTFREE: %p\n", *list);
+#endif
+ pefree(*list, 1);
+ *list = NULL;
+}
+
+static inline http_persistent_handle_list *http_persistent_handle_list_find(http_persistent_handle_provider *provider TSRMLS_DC)
+{
+ http_persistent_handle_list **list, *new_list;
+
+ if (SUCCESS == zend_hash_quick_find(&provider->list.free, HTTP_G->persistent.handles.ident.s, HTTP_G->persistent.handles.ident.l, HTTP_G->persistent.handles.ident.h, (void *) &list)) {
+#if HTTP_DEBUG_PHANDLES
+ fprintf(stderr, "LSTFIND: %p\n", *list);
+#endif
+ return *list;
+ }
+
+ if ((new_list = http_persistent_handle_list_init(NULL))) {
+ if (SUCCESS == zend_hash_quick_add(&provider->list.free, HTTP_G->persistent.handles.ident.s, HTTP_G->persistent.handles.ident.l, HTTP_G->persistent.handles.ident.h, (void *) &new_list, sizeof(http_persistent_handle_list *), (void *) &list)) {
+#if HTTP_DEBUG_PHANDLES
+ fprintf(stderr, "LSTFIND: %p (new)\n", *list);
+#endif
+ return *list;
+ }
+ http_persistent_handle_list_free(&new_list, provider->dtor);
+ }
+
+ return NULL;
+}
+
+static inline STATUS http_persistent_handle_do_acquire(http_persistent_handle_provider *provider, void **handle TSRMLS_DC)
+{
+ ulong index;
+ void **handle_ptr;
+ http_persistent_handle_list *list;
+
+ if ((list = http_persistent_handle_list_find(provider TSRMLS_CC))) {
+ zend_hash_internal_pointer_end(&list->free);
+ if (HASH_KEY_NON_EXISTANT != zend_hash_get_current_key(&list->free, NULL, &index, 0) && SUCCESS == zend_hash_get_current_data(&list->free, (void *) &handle_ptr)) {
+ *handle = *handle_ptr;
+ zend_hash_index_del(&list->free, index);
+ } else {
+ *handle = provider->ctor();
+ }
+
+ if (*handle) {
+ ++provider->list.used;
+ ++list->used;
+ return SUCCESS;
+ }
+ } else {
+ *handle = NULL;
+ }
+
+ return FAILURE;
+}
+
+static inline STATUS http_persistent_handle_do_release(http_persistent_handle_provider *provider, void **handle TSRMLS_DC)