lib/cds/ref_cntr.c
b4a18a29
 #include <cds/ref_cntr.h>
 #include <cds/logger.h>
 #include <cds/memory.h>
 
c8d7930f
 /* functions for initialization and destruction */
b4a18a29
 
c8d7930f
 reference_counter_group_t *create_reference_counter_group(int mutex_cnt)
b4a18a29
 {
c8d7930f
 	reference_counter_group_t *g;
 	int i;
 
 	g = cds_malloc(sizeof(*g) + mutex_cnt * sizeof(cds_mutex_t));
 	if (!g) {
 		ERROR_LOG("can't allocate memory\n");
 		return NULL;
 	}
 
 	for (i = 0; i < mutex_cnt; i++) {
 		cds_mutex_init(&g->mutexes[i]);
b4a18a29
 	}
c8d7930f
 	g->mutex_to_assign = 0;
 	g->mutex_cnt = mutex_cnt;
 
 	return g;
b4a18a29
 }
 
c8d7930f
 void free_reference_counter_group(reference_counter_group_t *grp)
b4a18a29
 {
c8d7930f
 	int i;
 	if (grp) {
 		for (i = 0; i < grp->mutex_cnt; i++) {
 			cds_mutex_destroy(&grp->mutexes[i]);
 		}
 		cds_free(grp);
b4a18a29
 	}
 }
 
 /* -------------------------------------------------------------------- */
 
c8d7930f
 void init_reference_counter(reference_counter_group_t *grp, reference_counter_data_t *ref)
b4a18a29
 {
c8d7930f
 	int m;
 	if (ref && grp) {
 		m = grp->mutex_to_assign;
b4a18a29
 		ref->cntr = 1;
c8d7930f
 		ref->mutex = grp->mutexes + m;
 		m = (m + 1) % grp->mutex_cnt; /* can't be less than zero */
 		grp->mutex_to_assign = m;
b4a18a29
 	}
 }
 
 void add_reference(reference_counter_data_t *ref)
 {
 	if (ref) {
 		if (ref->mutex) cds_mutex_lock(ref->mutex);
 		ref->cntr++;
 		if (ref->mutex) cds_mutex_unlock(ref->mutex);
 	}
 }
 
 int get_reference_count(reference_counter_data_t *ref)
 {
 	int res = 0;
 	if (ref) {
 		if (ref->mutex) cds_mutex_lock(ref->mutex);
 		res = ref->cntr;
 		if (ref->mutex) cds_mutex_unlock(ref->mutex);
 	}
 	return res;
 }
 
 int remove_reference(reference_counter_data_t *ref)
 {
 	int res = 0;
 	if (ref) {
 		if (ref->mutex) cds_mutex_lock(ref->mutex);
 		if (ref->cntr > 0) ref->cntr--;
 		if (ref->cntr == 0) res = 1;
 		if (ref->mutex) cds_mutex_unlock(ref->mutex);
 	}
 	return res;
 }