/*
    GSK - a library to write servers
    Copyright (C) 1999-2000 Dave Benson

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA

    Contact:
        daveb@ffem.org <Dave Benson>
*/

#ifndef __GSK_MAIN_LOOP_KQUEUE_H_
#define __GSK_MAIN_LOOP_KQUEUE_H_


typedef struct _GskMainLoopKqueue GskMainLoopKqueue;
typedef struct _GskMainLoopKqueueClass GskMainLoopKqueueClass;
typedef struct _GskKqueueUpdate GskKqueueUpdate;
typedef struct _GskKqueueEvent GskKqueueEvent;

#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */

#include "gskmainloop.h"

GtkType gsk_main_loop_kqueue_get_type();
#define GSK_TYPE_MAIN_LOOP_KQUEUE			(gsk_main_loop_kqueue_get_type ())
#define GSK_MAIN_LOOP_KQUEUE(obj)              (GTK_CHECK_CAST ((obj), GSK_TYPE_MAIN_LOOP_KQUEUE, GskMainLoopKqueue))
#define GSK_MAIN_LOOP_KQUEUE_CLASS(klass)      (GTK_CHECK_CLASS_CAST ((klass), GSK_TYPE_MAIN_LOOP_KQUEUE, GskMainLoopKqueueClass))
#define GSK_MAIN_LOOP_KQUEUE_GET_CLASS(obj)    (GSK_MAIN_LOOP_KQUEUE_CLASS(GTK_OBJECT(obj)->klass))
#define GSK_IS_MAIN_LOOP_KQUEUE(obj)           (GTK_CHECK_TYPE ((obj), GSK_TYPE_MAIN_LOOP_KQUEUE))
#define GSK_IS_MAIN_LOOP_KQUEUE_CLASS(klass)   (GTK_CHECK_CLASS_TYPE ((klass), GSK_TYPE_MAIN_LOOP_KQUEUE))

typedef enum _GskKqueueEventType
{
  /* If !in_out_separate */
  GSK_KQUEUE_EVENT_FD,

  /* If  in_out_separate */
  GSK_KQUEUE_EVENT_FD_IN,
  GSK_KQUEUE_EVENT_FD_OUT,

  GSK_KQUEUE_EVENT_WAITPID,
  GSK_KQUEUE_EVENT_SIGNAL
} GskKqueueEventType;

typedef enum _GskKqueueUpdateMode
{
  GSK_KQUEUE_ADD,
  GSK_KQUEUE_CHANGE,
  GSK_KQUEUE_REMOVE
} GskKqueueUpdateMode;

/* Derived classes may use GskKqueueSource's whose first member
 * is >= GSK_KQUEUE_SOURCE_FIRST_USER_ID.
 */
#define GSK_KQUEUE_SOURCE_FIRST_USER_ID		128

struct _GskKqueueUpdate
{
  GskKqueueUpdateMode mode;
  GskKqueueEventType  event_type;

  int                 id;     /* fd, signal num, pid, etc */

  /* Only for GSK_KQUEUE_EVENT_FD */
  GIOCondition        condition;
};

struct _GskKqueueEvent
{
  GskKqueueEventType  event_type;
  int                 id;     /* fd, signal num, pid, etc */
  GIOCondition        condition;
};

struct _GskMainLoopKqueueClass
{
  GskMainLoopClass	main_loop_class;

  /* Whether the base-class should generate
   * `fd' messages or `fd_in' and `fd_out' messages;
   * set this to whatever matches your native
   * implementation.
   */
  gboolean              in_out_separate;

  gboolean            (*setup) (GskMainLoop       *main_loop_kqueue);

  /* Returns FALSE only if an error occurs. */
  gboolean      (*do_polling)  (GskMainLoopKqueue *main_loop_kqueue,
			        guint              num_updates,
			        GskKqueueUpdate   *updates,
			        GArray            *kqueue_events_out,
			        gint64             max_micro_secs,
			        guint64           *micro_secs_out);

  void          (*signal_func) (int                sig_no);
};

typedef struct _GskSourceKqueue GskSourceKqueue;
struct _GskMainLoopKqueue
{
  GskMainLoop		main_loop;

  GTree                *timers;
  GHashTable           *signal_to_handler_list;
  GHashTable           *fd_to_source;
  GHashTable           *pid_to_source_list;
  GHashTable           *trapped_signals;
  guint                 source_count;
  gboolean		is_setup;

  GskSourceKqueue      *first_idle;
  GskSourceKqueue      *last_idle;
  GArray               *pending_updates;

  /* this may be used by init_polling / do_polling as the class desires,
   * except you must reset it to -1 before finalizing, or else
   * we will close(2) it.
   */
  int			kernel_queue_id;
};

#ifdef __cplusplus
}
#endif /* __cplusplus */

#endif
