Open PerilousApricot opened 8 years ago
In the same vein, module-level initialization/shutdown should take the names/signatures:
// Returns 0 on success, error code otherwise
int tbx_stack_startup();
int tbx_stack_shutdown();
If additional parameters are needed for startup/shutdown, they can be exposed by other functions, but sensible defaults should be exposed by a parameterless function.
Can destructors throw? Should the function signature be void?
// given an already allocated self of the proper size, initialize
// the memory
tbx_stack_t * tbx_stack_init(tbx_stack_t *self);
Perhaps this should be
// given an already allocated self of the proper size, initialize
// the memory
int tbx_stack_init(tbx_stack_t *self);
Strawman. Of course, C doesn't have C++'s idea of perfect forwarding, so additional constructor parameters are kinda annoying. _new()
would need to be split into the allocation half, and then N other halves that forward to each version of _init()
//******************************************************************************
// Boilerplate for tbx_sl_t
//******************************************************************************
tbx_sl_t *tbx_sl_new()
{
tbx_sl_t *sl = (tbx_sl_t *)malloc(sizeof(tbx_sl_t));
if (!sl) // Do we log here?
goto error_1;
apr_status_t ret = apr_pool_create(&(sl->pool), NULL);
if (ret != APR_SUCCESS)
goto error_2;
ret = apr_thread_mutex_create(&(sl->lock), APR_THREAD_MUTEX_DEFAULT, sl->pool);
if (ret != APR_SUCCESS)
goto error_3;
if (tbx_sl_init(sl)) {
goto error_4;
}
return sl;
error_4:
apr_thread_mutex_destroy(sl->lock);
error_3:
apr_pool_destroy(sl->pool);
error_2:
free(sl);
error_1:
return NULL;
}
void tbx_sl_del(tbx_sl_t * self)
{
tbx_sl_fini(sl);
apr_thread_mutex_destroy(self->lock);
apr_pool_destroy(self->pool);
free(self);
}
int tbx_sl_init(self)
{
return tbx_sl_init_full(self, 20, 0.25, 0, &tbx_sl_compare_int, NULL, NULL, NULL);
}
void tbx_sl_fini(tbx_sl_t * self)
{
tbx_sl_empty(self);
destroy_skiplist_node(self, self->head);
}
size_t tbx_sl_size()
{
return sizeof(tbx_sl_t);
}
int tbx_sl_init_full(tbx_sl_t *self,
int maxlevels, double p, int allow_dups,
tbx_sl_compare_t *compare,
tbx_sl_key_t *(*dup)(tbx_sl_key_t *a),
void (*key_free)(tbx_sl_key_t *a),
void (*data_free)(tbx_sl_data_t *a))
{
// Perform initialization
}
For objects intended to be opaque, provide the following consistent API: