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; ...@@ -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); belle_sip_object_pool_t * belle_sip_object_pool_push(void);
void belle_sip_object_pool_pop(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); void belle_sip_object_pool_clean(belle_sip_object_pool_t *obj);
#endif #endif
......
...@@ -115,7 +115,6 @@ typedef struct weak_ref{ ...@@ -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); void *belle_sip_object_get_interface_methods(belle_sip_object_t *obj, belle_sip_interface_id_t ifid);
/*used internally by unref()*/ /*used internally by unref()*/
void belle_sip_object_delete(void *obj); 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_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); 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){ ...@@ -343,6 +343,12 @@ void belle_sip_main_loop_iterate(belle_sip_main_loop_t *ml){
int ret; int ret;
uint64_t cur; uint64_t cur;
belle_sip_list_t *copy; 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 */ /*prepare the pollfd table */
memset(pfd, 0, pfd_size); memset(pfd, 0, pfd_size);
...@@ -413,7 +419,8 @@ void belle_sip_main_loop_iterate(belle_sip_main_loop_t *ml){ ...@@ -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); }else belle_sip_main_loop_remove_source(ml,s);
} }
belle_sip_list_free_with_data(copy,belle_sip_object_unref); 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){ 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 ...@@ -391,8 +391,19 @@ void belle_sip_object_pool_remove(belle_sip_object_pool_t *pool, belle_sip_objec
obj->pool=NULL; 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){ void belle_sip_object_pool_clean(belle_sip_object_pool_t *pool){
belle_sip_list_t *elem,*next; 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){ for(elem=pool->objects;elem!=NULL;elem=next){
belle_sip_object_t *obj=(belle_sip_object_t*)elem->data; belle_sip_object_t *obj=(belle_sip_object_t*)elem->data;
if (obj->ref==0){ if (obj->ref==0){
...@@ -417,11 +428,13 @@ static void cleanup_pool_stack(void *data){ ...@@ -417,11 +428,13 @@ static void cleanup_pool_stack(void *data){
belle_sip_free(pool_stack); 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 belle_sip_thread_key_t pools_key;
static int pools_key_created=0; static int pools_key_created=0;
belle_sip_list_t **pool_stack; belle_sip_list_t **pool_stack;
if (first_time) *first_time=0;
if (!pools_key_created){ if (!pools_key_created){
pools_key_created=1; pools_key_created=1;
if (belle_sip_thread_key_create(&pools_key, cleanup_pool_stack)!=0){ 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){ ...@@ -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=belle_sip_new(belle_sip_list_t*);
*pool_stack=NULL; *pool_stack=NULL;
belle_sip_thread_setspecific(pools_key,pool_stack); belle_sip_thread_setspecific(pools_key,pool_stack);
if (first_time) *first_time=1;
} }
return pool_stack; return pool_stack;
} }
belle_sip_object_pool_t * belle_sip_object_pool_push(void){ 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; belle_sip_object_pool_t *pool;
if (pools==NULL) { if (pools==NULL) {
belle_sip_error("Not possible to create a pool."); belle_sip_error("Not possible to create a pool.");
...@@ -450,7 +464,7 @@ belle_sip_object_pool_t * belle_sip_object_pool_push(void){ ...@@ -450,7 +464,7 @@ belle_sip_object_pool_t * belle_sip_object_pool_push(void){
} }
void belle_sip_object_pool_pop(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; belle_sip_object_pool_t *pool;
if (pools==NULL) { if (pools==NULL) {
belle_sip_error("Not possible to pop a pool."); belle_sip_error("Not possible to pop a pool.");
...@@ -466,10 +480,15 @@ void belle_sip_object_pool_pop(void){ ...@@ -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_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) return NULL;
if (*pools==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 (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 NULL;
} }
return (belle_sip_object_pool_t*)(*pools)->data; 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