Commit 3b347644 authored by Simon Morlat's avatar Simon Morlat
Browse files

robustize garbage collection in multi-threaded environments

parent 6b058ba8
......@@ -314,6 +314,8 @@ typedef struct belle_sip_object_pool belle_sip_object_pool_t;
belle_sip_object_pool_t * belle_sip_object_pool_push(void);
void belle_sip_object_pool_pop(void);
belle_sip_object_pool_t * belle_sip_object_pool_get_current();
int belle_sip_object_pool_cleanable(belle_sip_object_pool_t *pool);
void belle_sip_object_pool_clean(belle_sip_object_pool_t *obj);
#endif
......
......@@ -115,7 +115,6 @@ typedef struct weak_ref{
void *belle_sip_object_get_interface_methods(belle_sip_object_t *obj, belle_sip_interface_id_t ifid);
/*used internally by unref()*/
void belle_sip_object_delete(void *obj);
belle_sip_object_pool_t *belle_sip_object_pool_get_current(void);
void belle_sip_object_pool_add(belle_sip_object_pool_t *pool, belle_sip_object_t *obj);
void belle_sip_object_pool_remove(belle_sip_object_pool_t *pool, belle_sip_object_t *obj);
......
......@@ -343,6 +343,12 @@ void belle_sip_main_loop_iterate(belle_sip_main_loop_t *ml){
int ret;
uint64_t cur;
belle_sip_list_t *copy;
int can_clean=belle_sip_object_pool_cleanable(ml->pool); /*iterate might not be called by the thread that created the main loop*/
if (!can_clean){
/*Push a temporary pool for the time of the iterate loop*/
belle_sip_object_pool_push();
}
/*prepare the pollfd table */
memset(pfd, 0, pfd_size);
......@@ -413,7 +419,8 @@ void belle_sip_main_loop_iterate(belle_sip_main_loop_t *ml){
}else belle_sip_main_loop_remove_source(ml,s);
}
belle_sip_list_free_with_data(copy,belle_sip_object_unref);
belle_sip_object_pool_clean(ml->pool);
if (belle_sip_object_pool_cleanable(ml->pool)) belle_sip_object_pool_clean(ml->pool);
else belle_sip_object_pool_pop();
}
void belle_sip_main_loop_run(belle_sip_main_loop_t *ml){
......
......@@ -391,8 +391,19 @@ void belle_sip_object_pool_remove(belle_sip_object_pool_t *pool, belle_sip_objec
obj->pool=NULL;
}
int belle_sip_object_pool_cleanable(belle_sip_object_pool_t *pool){
return belle_sip_thread_self()==pool->thread_id;
}
void belle_sip_object_pool_clean(belle_sip_object_pool_t *pool){
belle_sip_list_t *elem,*next;
if (!belle_sip_object_pool_cleanable(pool)){
belle_sip_warning("Thread pool [%p] cannot be cleaned from thread [%u] because it was created for thread [%u]",
pool,(unsigned)belle_sip_thread_self(),(unsigned)pool->thread_id);
return;
}
for(elem=pool->objects;elem!=NULL;elem=next){
belle_sip_object_t *obj=(belle_sip_object_t*)elem->data;
if (obj->ref==0){
......@@ -417,11 +428,13 @@ static void cleanup_pool_stack(void *data){
belle_sip_free(pool_stack);
}
static belle_sip_list_t** get_current_pool_stack(void){
static belle_sip_list_t** get_current_pool_stack(int *first_time){
static belle_sip_thread_key_t pools_key;
static int pools_key_created=0;
belle_sip_list_t **pool_stack;
if (first_time) *first_time=0;
if (!pools_key_created){
pools_key_created=1;
if (belle_sip_thread_key_create(&pools_key, cleanup_pool_stack)!=0){
......@@ -433,12 +446,13 @@ static belle_sip_list_t** get_current_pool_stack(void){
pool_stack=belle_sip_new(belle_sip_list_t*);
*pool_stack=NULL;
belle_sip_thread_setspecific(pools_key,pool_stack);
if (first_time) *first_time=1;
}
return pool_stack;
}
belle_sip_object_pool_t * belle_sip_object_pool_push(void){
belle_sip_list_t **pools=get_current_pool_stack();
belle_sip_list_t **pools=get_current_pool_stack(NULL);
belle_sip_object_pool_t *pool;
if (pools==NULL) {
belle_sip_error("Not possible to create a pool.");
......@@ -450,7 +464,7 @@ belle_sip_object_pool_t * belle_sip_object_pool_push(void){
}
void belle_sip_object_pool_pop(void){
belle_sip_list_t **pools=get_current_pool_stack();
belle_sip_list_t **pools=get_current_pool_stack(NULL);
belle_sip_object_pool_t *pool;
if (pools==NULL) {
belle_sip_error("Not possible to pop a pool.");
......@@ -466,10 +480,15 @@ void belle_sip_object_pool_pop(void){
}
belle_sip_object_pool_t *belle_sip_object_pool_get_current(void){
belle_sip_list_t **pools=get_current_pool_stack();
int first_time;
belle_sip_list_t **pools=get_current_pool_stack(&first_time);
if (pools==NULL) return NULL;
if (*pools==NULL){
belle_sip_warning("There is no object pool created. Use belle_sip_stack_push_pool() to create one. Unowned objects not unref'd will be leaked.");
if (*pools==NULL ){
if (first_time) {
belle_sip_warning("There is no object pool created in thread [%u]. "
"Use belle_sip_stack_push_pool() to create one. Unowned objects not unref'd will be leaked.",
(unsigned int)belle_sip_thread_self());
}
return NULL;
}
return (belle_sip_object_pool_t*)(*pools)->data;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment