/*

sshtimeouts.h

Author: Tatu Ylonen <ylo@ssh.fi>
        Antti Huima <huima@ssh.fi>
        Tero Kivinen <kivinen@ssh.fi>

Copyright (c) 1995-2000 SSH Communications Security, Finland
              All rights reserved.

Timeout processing.  This header is part of the event loop interface.
This header is machine-independent; however, the implementation is
machine-dependent.

*/

#ifndef SSHTIMEOUTS_H
#define SSHTIMEOUTS_H

#ifdef __cplusplus
extern "C" {
#endif

/* Special wild-card context arguments to ssh_cancel_timeouts. */
#define SSH_ALL_CALLBACKS ((SshTimeoutCallback)1)
#define SSH_ALL_CONTEXTS  ((void *)1)

/* Callback functions of this type are called when a timeout occurs.
   The function receives as argument the context supplied when the
   timeout was registered.  A timeout is delivered only once, but can
   be reregistered in the callback function.  There are no
   restrictions as to what operations can be performed in timeout
   callbacks. */
typedef void (*SshTimeoutCallback)(void *context);

/* Registers a timeout function that is to be called once when the specified
   time has elapsed.  The time may be zero, in which case the callback will
   be called as soon as possible from the bottom of the event loop.  There
   is no guarantee about the order in which callbacks with zero timeouts are
   delivered.

   The timeout will be delivered approximately after the specified time.  The
   exact time may differ somewhat from the specified time.  The timeout will
   be delivered from the bottom of the event loop (i.e., it will be delayed if
   another callback from the event loop is being executed).

   The arguments are as follows:
     seconds        number of full seconds after which the timeout is delivered
     microseconds   number of microseconds to add to full seconds
                    (this may be larger than 1000000, meaning several seconds)
     callback       the callback function to call
     context        context argument to pass to callback function. */
void
ssh_register_timeout(long seconds, long microseconds,
                     SshTimeoutCallback callback, void *context);

/* Registers an idle timeout function.  An idle timeout will be called once
   when the system has been sufficiently idle for the specified amount of
   time.  The definition of idle is somewhat implementation-dependent, but
   typically means when it is a good time to perform cpu-intensive operations.
   There is no guarantee that the idle timeout ever gets called.  Idle timeouts
   are always delivered from the bottom of the event loop.

   The arguments are as follows:
     seconds        number of seconds the system must be idle before delivering
     microseconds   number of microseconds to add to full seconds
                    (this may be larger than 1000000, meaning several seconds)
     callback       the callback function to call
     context        context argument to pass to callback function. */
void
ssh_register_idle_timeout(long seconds, long microseconds,
                          SshTimeoutCallback callback, void *context);

/* Cancels any timeouts with a matching callback function and context.
   `callback' may be SSH_ALL_CALLBACKS, which matches any function, and
   `context' may be SSH_ALL_CONTEXTS, which matches any context.
   It is guaranteed that the timeout will not be delivered once it has
   been cancelled, even if it had elapsed (but not yet delivered) before
   cancelling it. */
void
ssh_cancel_timeouts(SshTimeoutCallback callback, void *context);

/* SSH library functions can only be called from single thread. This SSH main
   thread is the thread that is running the event loop. If the program is
   multiple threads and the other threads want to call some SSH library
   functions they must pass the execution of that code to the SSH main thread.
   Only method of doing that is to call ssh_register_threaded_timeout. That
   function can be called from other threads also, and it will pass the timeout
   given to it to the SSH main thread. When the timeout expires it is run on
   the SSH main thread. If you want to the call to be done as soon as possible
   use zero length timeout. The SSH library contains few other functions that
   can be called from other threads also. Each of those functions contains a
   note saying that they can be called from other threads also. */

/* Initialize function for timeouts in multithreaded environment. If program
   uses multiple threads, it MUST call this function before calling
   ssh_register_threaded_timeout function. If the system environment does not
   support threads this will call ssh_fatal. If program does not use multiple
   threads it should not call this function, but it may still call
   ssh_register_threaded_timeout. This function MUST be called from the SSH
   main thread after the event loop has been initialized. */
void ssh_threaded_timeouts_init(void);

/* Uninitialize multithreading environment. This should be called before the
   program ends. After this is called the program MUST NOT call any other
   ssh_register_threaded_timeout functions before calling the
   ssh_threaded_timeouts_init function again. This function MUST be called from
   the SSH main thread. */
void ssh_threaded_timeouts_uninit(void);

/* Insert timeout to the SSH library thread on the given time. This function
   can be called from the any thread, provided that ssh_threaded_timeouts_init
   function is called before this. This function can also be called without
   calling the ssh_threaded_timeouts_init, but in that case this function
   assumes that there is no other threads and it will just call regular
   ssh_register_timeout directly. See documentation for ssh_register_timeout
   for more information. These timeouts can be cancelled normally using the
   ssh_cancel_timeouts, but ONLY from the SSH main thread. Note, also that
   there might be race conditions on that kind of situations, the other thread
   might be just calling this function while the SSH main thread is cancelling
   the timeout. In that case the timeout might be inserted again when this
   message from here receives the SSH main thread. */
void ssh_register_threaded_timeout(long seconds, long microseconds,
                                   SshTimeoutCallback callback,
                                   void *context);

#ifdef __cplusplus
}
#endif

#endif /* SSHTIMEOUTS_H */
