} \
} while (0)
+/**
+ * Allocate slot in heap and return pointer to it (zero-initialized)
+ * User fills the slot, then must call rspamd_heap_swim to restore heap property
+ * Returns NULL on allocation failure
+ */
+#define rspamd_heap_push_slot(name, heap) \
+ ({ \
+ typeof(&kv_A(*(heap), 0)) slot = NULL; \
+ kv_push(typeof(kv_A(*(heap), 0)), *(heap), (typeof(kv_A(*(heap), 0))) {0}); \
+ if (kv_size(*(heap)) > 0) { \
+ slot = &kv_A(*(heap), kv_size(*(heap)) - 1); \
+ slot->idx = kv_size(*(heap)) - 1; \
+ } \
+ slot; \
+ })
+
/**
* Push element to heap (safe version with error handling)
* Element is copied into the heap array.
POOL_MTX_LOCK();
- /* Allocate destructor structure */
- dtor = rspamd_mempool_alloc_(pool, sizeof(*dtor),
- RSPAMD_ALIGNOF(struct _pool_destructors), line);
- dtor->func = func;
- dtor->data = data;
- dtor->function = function;
- dtor->loc = line;
- dtor->pri = priority;
-
/* Initialize heap if not yet created */
if (pool->priv->dtors_heap.a == NULL) {
rspamd_heap_init(rspamd_mempool_destruct_heap, &pool->priv->dtors_heap);
}
}
- /* Push to heap - using non-safe version as we're in mempool */
- rspamd_heap_push_safe(rspamd_mempool_destruct_heap, &pool->priv->dtors_heap, dtor, cleanup);
+ /* Allocate slot directly in heap (avoids double allocation) */
+ dtor = rspamd_heap_push_slot(rspamd_mempool_destruct_heap, &pool->priv->dtors_heap);
+ if (dtor == NULL) {
+ goto cleanup;
+ }
+
+ /* Fill destructor structure */
+ dtor->func = func;
+ dtor->data = data;
+ dtor->function = function;
+ dtor->loc = line;
+ dtor->pri = priority;
+
+ /* Restore heap property after filling the slot */
+ rspamd_heap_swim(rspamd_mempool_destruct_heap, &pool->priv->dtors_heap, dtor);
POOL_MTX_UNLOCK();
return;