/* Arisa Threading Linkage Header */

#define _ARISA_THREADING_H

/**********************
 * Threading
 **********************/

#ifdef HAVE_PTHREAD_H
#include <pthread.h>
#elif HAVE_PTHREAD_MIT_PTHREAD_H
#include <pthread/mit/pthread.h>
#else
#error Unable to locate pthread.h
#endif

/* Sun kindly define a lock_t already, but not the type we want. */
#ifdef HAVE_SUNOS
#define lock_t alock_t
#endif /* HAVE_SUNOS */

/* locking */
typedef pthread_mutex_t		lock_t;
typedef pthread_rwlock_t	rwlock_t;

#define LOCK_INIT(x)						\
	do {							\
		/* memset((x),0,sizeof(lock_t)); */		\
		pthread_mutex_init((x),NULL);			\
	} while(0)
#define LOCK_RW_INIT(x)						\
	do {							\
		/* memset((x),0,sizeof(rwlock_t)); */		\
		pthread_rwlock_init((x),NULL);			\
	} while(0)

#define LOCK_FREE(x) 						\
	do { 							\
		int ret = pthread_mutex_destroy((x));		\
		assert(ret == 0);				\
	} while(0)
#define LOCK_RW_FREE(x)						\
	do {							\
		int ret = pthread_rwlock_destroy((x));		\
		assert(ret == 0);				\
	} while(0)

#define LOCKR(x)		pthread_mutex_lock((x))
#define LOCK(x)			LOCKR(&((x)->lock))

#define RLOCKR(x)		pthread_rwlock_rdlock((x))
#define WLOCKR(x)		pthread_rwlock_wrlock((x))
#define RLOCK(x)		RLOCKR(&((x)->lock))
#define WLOCK(x)		WLOCKR(&((x)->lock))

#define UNLOCKR(x)		pthread_mutex_unlock((x))
#define UNLOCK(x)		UNLOCKR(&((x)->lock))

#define RWUNLOCKR(x)		pthread_rwlock_unlock((x))
#define RUNLOCKR(x)		RWUNLOCKR(x)
#define WUNLOCKR(x)		RWUNLOCKR(x)
#define RUNLOCK(x)		RUNLOCKR(&((x)->lock))
#define WUNLOCK(x)		WUNLOCKR(&((x)->lock))

/* threading */
typedef struct thread_t {
	pthread_t	thread;
	volatile int	end;
	pthread_cond_t	signal;
	pthread_mutex_t	rlock;
	pthread_mutex_t	alock;
} thread_t;

void	thread_init(thread_t *t);
void	thread_free(thread_t *t);
int	thread_create(thread_t *t, void *(*code)(void *), void *arg);
int	thread_join(thread_t *t, void **ret_val);
int	thread_wake_up(thread_t *t);
int	thread_end(thread_t *t);
int	thread_is_running(thread_t *t);
void	thread_signal_started(thread_t *t);
void	thread_signal_finished(void);
int	thread_should_end(void);
int	thread_sleep(unsigned long sec);
int	interruptable_connect(int sockfd, const struct sockaddr *serv_addr, 
				socklen_t addrlen);
