Blame memkind-1.10.0/jemalloc/test/include/test/mq.h

Packit Service 724aca
void	mq_nanosleep(unsigned ns);
Packit Service 724aca
Packit Service 724aca
/*
Packit Service 724aca
 * Simple templated message queue implementation that relies on only mutexes for
Packit Service 724aca
 * synchronization (which reduces portability issues).  Given the following
Packit Service 724aca
 * setup:
Packit Service 724aca
 *
Packit Service 724aca
 *   typedef struct mq_msg_s mq_msg_t;
Packit Service 724aca
 *   struct mq_msg_s {
Packit Service 724aca
 *           mq_msg(mq_msg_t) link;
Packit Service 724aca
 *           [message data]
Packit Service 724aca
 *   };
Packit Service 724aca
 *   mq_gen(, mq_, mq_t, mq_msg_t, link)
Packit Service 724aca
 *
Packit Service 724aca
 * The API is as follows:
Packit Service 724aca
 *
Packit Service 724aca
 *   bool mq_init(mq_t *mq);
Packit Service 724aca
 *   void mq_fini(mq_t *mq);
Packit Service 724aca
 *   unsigned mq_count(mq_t *mq);
Packit Service 724aca
 *   mq_msg_t *mq_tryget(mq_t *mq);
Packit Service 724aca
 *   mq_msg_t *mq_get(mq_t *mq);
Packit Service 724aca
 *   void mq_put(mq_t *mq, mq_msg_t *msg);
Packit Service 724aca
 *
Packit Service 724aca
 * The message queue linkage embedded in each message is to be treated as
Packit Service 724aca
 * externally opaque (no need to initialize or clean up externally).  mq_fini()
Packit Service 724aca
 * does not perform any cleanup of messages, since it knows nothing of their
Packit Service 724aca
 * payloads.
Packit Service 724aca
 */
Packit Service 724aca
#define mq_msg(a_mq_msg_type)	ql_elm(a_mq_msg_type)
Packit Service 724aca
Packit Service 724aca
#define mq_gen(a_attr, a_prefix, a_mq_type, a_mq_msg_type, a_field)	\
Packit Service 724aca
typedef struct {							\
Packit Service 724aca
	mtx_t			lock;					\
Packit Service 724aca
	ql_head(a_mq_msg_type)	msgs;					\
Packit Service 724aca
	unsigned		count;					\
Packit Service 724aca
} a_mq_type;								\
Packit Service 724aca
a_attr bool								\
Packit Service 724aca
a_prefix##init(a_mq_type *mq) {						\
Packit Service 724aca
									\
Packit Service 724aca
	if (mtx_init(&mq->lock)) {					\
Packit Service 724aca
		return true;						\
Packit Service 724aca
	}								\
Packit Service 724aca
	ql_new(&mq->msgs);						\
Packit Service 724aca
	mq->count = 0;							\
Packit Service 724aca
	return false;							\
Packit Service 724aca
}									\
Packit Service 724aca
a_attr void								\
Packit Service 724aca
a_prefix##fini(a_mq_type *mq) {						\
Packit Service 724aca
	mtx_fini(&mq->lock);						\
Packit Service 724aca
}									\
Packit Service 724aca
a_attr unsigned								\
Packit Service 724aca
a_prefix##count(a_mq_type *mq) {					\
Packit Service 724aca
	unsigned count;							\
Packit Service 724aca
									\
Packit Service 724aca
	mtx_lock(&mq->lock);						\
Packit Service 724aca
	count = mq->count;						\
Packit Service 724aca
	mtx_unlock(&mq->lock);						\
Packit Service 724aca
	return count;							\
Packit Service 724aca
}									\
Packit Service 724aca
a_attr a_mq_msg_type *							\
Packit Service 724aca
a_prefix##tryget(a_mq_type *mq) {					\
Packit Service 724aca
	a_mq_msg_type *msg;						\
Packit Service 724aca
									\
Packit Service 724aca
	mtx_lock(&mq->lock);						\
Packit Service 724aca
	msg = ql_first(&mq->msgs);					\
Packit Service 724aca
	if (msg != NULL) {						\
Packit Service 724aca
		ql_head_remove(&mq->msgs, a_mq_msg_type, a_field);	\
Packit Service 724aca
		mq->count--;						\
Packit Service 724aca
	}								\
Packit Service 724aca
	mtx_unlock(&mq->lock);						\
Packit Service 724aca
	return msg;							\
Packit Service 724aca
}									\
Packit Service 724aca
a_attr a_mq_msg_type *							\
Packit Service 724aca
a_prefix##get(a_mq_type *mq) {						\
Packit Service 724aca
	a_mq_msg_type *msg;						\
Packit Service 724aca
	unsigned ns;							\
Packit Service 724aca
									\
Packit Service 724aca
	msg = a_prefix##tryget(mq);					\
Packit Service 724aca
	if (msg != NULL) {						\
Packit Service 724aca
		return msg;						\
Packit Service 724aca
	}								\
Packit Service 724aca
									\
Packit Service 724aca
	ns = 1;								\
Packit Service 724aca
	while (true) {							\
Packit Service 724aca
		mq_nanosleep(ns);					\
Packit Service 724aca
		msg = a_prefix##tryget(mq);				\
Packit Service 724aca
		if (msg != NULL) {					\
Packit Service 724aca
			return msg;					\
Packit Service 724aca
		}							\
Packit Service 724aca
		if (ns < 1000*1000*1000) {				\
Packit Service 724aca
			/* Double sleep time, up to max 1 second. */	\
Packit Service 724aca
			ns <<= 1;					\
Packit Service 724aca
			if (ns > 1000*1000*1000) {			\
Packit Service 724aca
				ns = 1000*1000*1000;			\
Packit Service 724aca
			}						\
Packit Service 724aca
		}							\
Packit Service 724aca
	}								\
Packit Service 724aca
}									\
Packit Service 724aca
a_attr void								\
Packit Service 724aca
a_prefix##put(a_mq_type *mq, a_mq_msg_type *msg) {			\
Packit Service 724aca
									\
Packit Service 724aca
	mtx_lock(&mq->lock);						\
Packit Service 724aca
	ql_elm_new(msg, a_field);					\
Packit Service 724aca
	ql_tail_insert(&mq->msgs, msg, a_field);			\
Packit Service 724aca
	mq->count++;							\
Packit Service 724aca
	mtx_unlock(&mq->lock);						\
Packit Service 724aca
}