/* -*- Mode: C -*-
 *
 * $Header: /home/gene/library/website/docsrc/cloop/src/RCS/cloop.h,v 395.1 2008/04/20 17:25:50 gene Exp $
 *
 * Copyright (c) 2006 Gene Michael Stover.  All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301
 * USA
 */

#ifdef __cplusplus
#define CLOOP_API extern "C"
#else
#define CLOOP_API
#endif

#if CLOOP_WINDOWS
/* WINDOWS-SPECIFIC STUFF */
/*
 * Return 0 on success.
 */
CLOOP_API int CLOOP_LibStartup (HINSTANCE instance);
/*
 */
CLOOP_API void CLOOP_LibShutdown (void);
/*
 * Don't use this CLOOP_SocketType type.  I use it within the CLOOP
 * code to make it easy to change it by changing this typedef here.
 * Application code should use its own Socket type (or int or SOCKET
 * or whatever).  If the application wants to say
 * "typedef CLOOP_SocketType Socket", that would be okay.
 */
typedef SOCKET CLOOP_SocketType;
/*
 * Return the Windows handle of the CLOOP window.  It displays
 * statistics so you can see things changing while the program
 * runs.  If has a system menu & a close box, but when you close
 * it, it simply makes itself invisible.  It does not close until
 * you call CLOOP_LibShutdown.
 */
CLOOP_API HWND CLOOP_GetWnd (void);
#else
/* UNIX-SPECIFIC STUFF */
/*
 * Return 0 on success.
 */
CLOOP_API int CLOOP_LibStartup (void);
/*
 */
CLOOP_API void CLOOP_LibShutdown (void);
/* I guess we're on unix (or a "unix-like" system for those peeps
 * who disagree with Andrew S. Tanenbaum when he shows in his
 * first operating systems book that if you have a certain 40
 * system calls, you have a unix API.
 */
typedef int CLOOP_SocketType;
#endif

/*
 * Tell CLOOP whether or not it needs to use a mutex around its
 * critical sections.  If you're sure your program does not use
 * multi-threaded libraries, set this to false (0).  Otherwise,
 * set it to true (non-zero).  Defaults to true, which is safe.
 */
CLOOP_API void CLOOP_UseMutex (int b); /* B is a Boolean */

/*
 * Return true (non-zero) if CLOOP should retain this reader for
 * this socket.  If you want CLOOP to stop calling this reader
 * for this socket, return false (0).
 */
typedef int (*CLOOP_ReadFnType) (CLOOP_SocketType, void *);

/*
 * To clear the reader for a socket, set its reader to NULL.
 */
CLOOP_API void CLOOP_SetReader (CLOOP_SocketType s, CLOOP_ReadFnType, void *);

/*
 * Return true (non-zero) if CLOOP should retain this writer for
 * this socket.  If you want CLOOP to stop calling this writer
 * for this socket, return false (0).
 */
typedef int (*CLOOP_WriteFnType) (CLOOP_SocketType, void *);

/*
 * To clear the writer for a socket, set its writer to NULL.
 */
CLOOP_API void CLOOP_SetWriter (CLOOP_SocketType s, CLOOP_WriteFnType, void *);

/*
 * Return true (non-zero) if CLOOP should retain this timer
 * callback at the original interval.
 * If you want CLOOP to stop calling this timer callback,
 * return false (0).
 */
typedef int (*CLOOP_TimeFnType) (time_t, void *);

/*
 * To clear a timer callback, it should return false (0).
 * DELAY is the number of seconds in the future when the
 * event should happen.
 *
 * EXAMPLES:
 * 
 * DELAY = 0 (or a negative) number means
 * as soon as possible.
 *
 * DELAY = 1 means one second in the future.
 * 3600 means one hour in the future.
 *
 * It's bad style if the function pointer is NULL, but it's not
 * an error.  CLOOP will simply ignore a callback pointer which
 * is NULL.
 */
CLOOP_API void CLOOP_SetAlarm (int delay, CLOOP_TimeFnType, void *);

/*
 * Call this to tell CLOOP's loop to exit.
 * On Windows you could post a quit message.
 */
CLOOP_API void CLOOP_SetDone (int value);

/*
 */
CLOOP_API int CLOOP_Run (void);

/*
 * A long, human-readable string which identifies the version of
 * CLOOP.
 * Don't modify the string.
 */
CLOOP_API char *CLOOP_GetLongVersion (void);

/*
 */
struct CLOOP_Statistics {
  /*
   * Number of times through the event loop.
   * If it ever over-flows, it & all the other statistics are
   * cleared, & they start again.
   */
  unsigned long loop_count;
  /*
   * Maximum number of events which were ever in the alarm queue
   */
  int teq_count_max;
  /*
   * Maximum number of alarms we dispatched in a single pass through
   * the event loop.
   */
  int alarm_count_max;

  /*
   * Only on Microsoft Windows!  On other platforms, it's always 0.
   *
   * Number of WM_TIMER messages we received.
   */
  unsigned long wm_timer_count;

  /*
   * Only on unix-like systems!  On other platforms, this is always 0.
   *
   * Maximum number of sockets ready for I/O after a call to "select".
   */
  int select_max;
};
extern struct CLOOP_Statistics CLOOP_stats;

/*
 */
CLOOP_API void CLOOP_DumpStatistics (FILE *strm);

/*
 * Enable or disable debugging messages.  Debugging messages are
 * for programmers; they are copious, usually ugly, trace messages
 * printed to stdout.
 *
 * "b" is a boolean.  True (non-zero) enables the messages.  False
 * (0) disables them.  The default is false.
 */
CLOOP_API void CLOOP_EnableTrace (int b); /* b is a boolean */

/* --- end of file --- */
