#ifndef	_EPP_H
#define	_EPP_H

#include <epp/epp_pal.h>

#ifdef	EPP_MULTIPLE_ENGINES
#	include <pthread.h>
#	define	EPP_LOCKABLE(VARIABLE)			pthread_mutex_t	VARIABLE ## _lock
#	define	EPP_LOCK_INIT(VARIABLE)			pthread_mutex_init(&VARIABLE ## _lock, NULL)
#	define	EPP_OBJECT_LOCK_INIT(OBJECT)		pthread_mutex_init(&OBJECT -> _lock, NULL)
#	define	EPP_LOCK_SHUTDOWN(VARIABLE)		pthread_mutex_destroy(&VARIABLE ## _lock)
#	define	EPP_OBJECT_LOCK_SHUTDOWN(OBJECT)	pthread_mutex_destroy(&OBJECT -> _lock)
#	define	EPP_LOCK(VARIABLE)			pthread_mutex_lock(&VARIABLE ## _lock)
#	define	EPP_OBJECT_LOCK(OBJECT)			pthread_mutex_lock(&OBJECT -> _lock)
#	define	EPP_TRYLOCK(VARIABLE)			!pthread_mutex_trylock(&VARIABLE ## _lock)
#	define	EPP_OBJECT_TRYLOCK(OBJECT)		!pthread_mutex_trylock(&OBJECT -> _lock)
#	define	EPP_UNLOCK(VARIABLE)			pthread_mutex_unlock(&VARIABLE ## _lock)
#	define	EPP_OBJECT_UNLOCK(OBJECT)		pthread_mutex_unlock(&OBJECT -> _lock)
#	define	EPP_WAITABLE(VARIABLE)			pthread_cond_t VARIABLE ## _cond
#	define	EPP_WAIT_INIT(VARIABLE)			pthread_cond_init(&VARIABLE ## _cond, NULL)
#	define	EPP_OBJECT_WAIT_INIT(OBJECT)		pthread_cond_init(&OBJECT -> _cond, NULL)
#	define	EPP_WAIT_SHUTDOWN(VARIABLE)		pthread_cond_destroy(&VARIABLE ## _cond)
#	define	EPP_OBJECT_WAIT_SHUTDOWN(OBJECT)	pthread_cond_destroy(&OBJECT -> _cond)
#	define	EPP_WAIT(VARIABLE)			pthread_cond_wait(&VARIABLE ## _cond, &VARIABLE ## _lock)
#	define	EPP_OBJECT_WAIT(OBJECT)			pthread_cond_wait(&OBJECT -> _cond, &OBJECT -> _lock)
#	define	EPP_SIGNAL(VARIABLE)			pthread_cond_broadcast(&VARIABLE ## _cond)
#	define	EPP_OBJECT_SIGNAL(OBJECT)		pthread_cond_broadcast(&OBJECT -> _cond)
#else	/* EPP_MULTIPLE_ENGINES */
#	define	EPP_LOCKABLE(VARIABLE)
#	define	EPP_LOCK_INIT(VARIABLE)
#	define	EPP_OBJECT_LOCK_INIT(OBJECT)
#	define	EPP_LOCK_SHUTDOWN(VARIABLE)
#	define	EPP_OBJECT_LOCK_SHUTDOWN(OBJECT)
#	define	EPP_LOCK(VARIABLE)
#	define	EPP_OBJECT_LOCK(OBJECT)
#	define	EPP_UNLOCK(VARIABLE)
#	define	EPP_OBJECT_UNLOCK(OBJECT)
#	define	EPP_WAITABLE(VARIABLE)
#	define	EPP_WAIT_INIT(VARIABLE)
#	define	EPP_OBJECT_WAIT_INIT(OBJECT)
#	define	EPP_WAIT_SHUTDOWN(VARIABLE)
#	define	EPP_OBJECT_WAIT_SHUTDOWN(OBJECT)
#	define	EPP_WAIT(VARIABLE)
#	define	EPP_OBJECT_WAIT(OBJECT)
#	define	EPP_SIGNAL(VARIABLE)
#	define	EPP_OBJECT_SIGNAL(OBJECT)
#	define	EPP_TRYLOCK(VARIABLE)			1
#	define	EPP_OBJECT_TRYLOCK(OBJECT)		1
#endif	/* EPP_MULTIPLE_ENGINES */

#define	EPP_DIRECT_CALL		-1

#define	EPP_CLOSE_QUERY		0
#define	EPP_NEXT_SOLUTION	1

#define	EPP_NO_BLOCK		0x00000001

typedef struct	__epp_event_descriptor {
    av_alist				open_query_call;
    pl_query				query;
    int					retval;
    void				*userdata;
    struct __epp_event_descriptor	*next;
    int (*notify)			(int retval, void *userdata);
} epp_event_descriptor;

typedef struct {
    pl_query				plquery;
    int					retval;
    enum { NONE, FIRST_CALL,
	   NO_MORE_CALLS,DIRECT }	flags;

    EPP_LOCKABLE(); EPP_WAITABLE();
} epp_query;

typedef	int	(*epp_notify_function)(int retval, void *userdata);

extern	int	epp_acall(epp_notify_function callback, void *userdata, unsigned int priority, const char *predicate, const char *params_spec, ...);
extern	int	epp_vacall(epp_notify_function callback, void *userdata, unsigned int priority, const char *predicate, const char *params_spec, va_list args);

extern	int	epp_call(unsigned int priority, const char *predicate, const char *params_spec, ...);
extern	int	epp_vcall(unsigned int priority, const char *predicate, const char *params_spec, va_list args);

extern	int	epp_open_query(epp_query *query, unsigned int priority, const char *predicate, const char *params_spec, ...);
extern	int	epp_vopen_query(epp_query *query, unsigned int priority, const char *predicate, const char *params_spec, va_list args);
extern	int	epp_next_solution(epp_query *query);
extern	void	epp_close_query(epp_query *query);

extern	unsigned int	EPP_Process(unsigned int maxevents, unsigned int min, unsigned int max, unsigned int flags);
extern	void		EPP_ProcessUnblockAll(void);

#endif
