wow. that was easy: git mv core nucleus
[feisty_meow.git] / nucleus / library / processes / ethread.h
diff --git a/nucleus/library/processes/ethread.h b/nucleus/library/processes/ethread.h
new file mode 100644 (file)
index 0000000..9adab46
--- /dev/null
@@ -0,0 +1,184 @@
+#ifndef ETHREAD_CLASS
+#define ETHREAD_CLASS
+
+/*****************************************************************************\
+*                                                                             *
+*  Name   : ethread (easy thread)                                             *
+*  Author : Chris Koeritz                                                     *
+*                                                                             *
+*******************************************************************************
+* Copyright (c) 1998-$now By Author.  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 is online at:      *
+*     http://www.fsf.org/copyleft/gpl.html                                    *
+* Please send any updates to: fred@gruntose.com                               *
+\*****************************************************************************/
+
+#include <basis/contracts.h>
+#include <timely/time_stamp.h>
+
+#include <signal.h>
+
+#ifndef __APPLE__
+#ifdef __UNIX__
+//  typedef long unsigned int pthread_t;
+#endif
+#endif
+
+namespace processes {
+
+//! Provides a platform-independent object for adding threads to a program.
+/*!
+  This greatly simplifies creating and managing threads by hiding all the
+  operating system details.  The user just needs to override one virtual
+  function in their derived object to perform the main activity of their
+  thread.  The thread can be a one time invocation or it can run periodically.
+  Control over the thread remains in the hands of the program that started
+  it.
+*/
+
+class ethread : public virtual basis::root_object
+{
+public:
+  ethread();
+    //!< creates a single-shot thread object.
+    /*!< the OS-level thread is not started until the start() method is
+    invoked.  this constructor creates a thread that will only execute
+    once; when start() is called, the thread starts up and performs its
+    activity.  it will then stop.  to run it again, start() must be invoked
+    again.  however, if the perform_activity() method just keeps running,
+    then the single-shot thread can live as long as needed.  it is important
+    for such a thread to periodically check should_exit() to avoid having
+    the program hang-up when it's supposed to be shutting down. */
+
+  enum timed_thread_types { TIGHT_INTERVAL, SLACK_INTERVAL };
+
+  ethread(int sleep_timer, timed_thread_types how = SLACK_INTERVAL);
+    //!< creates a managed thread object that runs on a periodic interval.
+    /*!< the thread will activate every "sleep_timer" milliseconds.  when
+    start() is invoked, the thread's action (via the perform_activity()
+    method) will be performed at regular intervals (using the specified value
+    for "sleep_timer").  the thread will continue activating until the stop()
+    method is called.  a faster interval is used internally during sleep
+    periods such that calling stop() will not consume the whole "sleep_timer"
+    period.  if the "how" is TIGHT_INTERVAL, then the thread will activate
+    every "sleep_timer" milliseconds, as accurately as possible.  if the "how"
+    is SLACK_INTERVAL, then the thread will activate after a delay of
+    "sleep_timer" milliseconds from its last activation.  the latter mode
+    allows the thread to consume its entire intended operation time knowing
+    that there will still be slack time between when it is active.  the
+    former mode requires the thread to only run for some amount of time less
+    than its "sleep_timer"; otherwise it will hog a lot of the CPU. */
+
+  virtual ~ethread();
+
+  DEFINE_CLASS_NAME("ethread");
+
+  bool start(void *thread_data);
+    //!< causes the thread to start, if it has not already been started.
+    /*!< if the thread has terminated previously, then this will restart the
+    thread.  true is returned if the thread could be started.  false is
+    returned if the thread could not be started or if it is already running. */
+
+  void stop();
+    //!< tells the thread to shutdown and waits for the shutdown to occur.
+    /*!< this will cause the OS thread to terminate once the current (if any)
+    perform_activity() invocation completes.  the thread may be restarted
+    with start(). */
+
+  void cancel() { _stop_thread = true; }
+    //!< stops the thread but does not wait until it has terminated.
+    /*!< this is appropriate for use within the perform_activity() method. */
+
+//  virtual void pre_thread();
+    //!< invoked just after after start(), when the OS thread is created.
+    /*!< the call comes in _from_ the thread itself, so the derived method
+    must be thread-safe. */
+//  virtual void post_thread();
+    //!< this is invoked just before the thread is to be terminated.
+    /*!< the call also comes in from the thread itself, so the implementation
+    must be thread-safe. */
+
+  virtual void perform_activity(void *thread_data) = 0;
+    //!< carries out the main activity of the thread.
+    /*!< this is called repeatedly by the main thread management function and
+    so should return as soon as possible.  if it does not return fairly
+    regularly, then the thread shutdown process will not occur until the
+    function exits on its own. */
+
+  void exempt_stop();
+    //!< this special form of stop() does not wait for the thread to exit.
+    /*!< it is required in certain weird OS situations where the thread does
+    not exit properly and stop() would cause an infinite wait.  don't use it
+    unless you are SURE that this is the case. */
+
+  void reschedule(int delay = 0);
+    //!< causes a periodic thread to activate after "delay" milliseconds from now.
+    /*!< this resets the normal activation period, but after the next
+    activation occurs, the normal activation interval takes over again. */
+
+  int sleep_time() const { return _sleep_time; }
+    //!< returns the current periodic thread interval.
+    /*!< this is only meaningful for periodic threads. */
+
+  void sleep_time(int new_sleep) { _sleep_time = new_sleep; }
+    //!< adjusts the period for the thread to the "new_sleep" interval.
+    /*!< this is only meaningful for periodic threads. */
+
+  // these functions report on the thread state.
+
+  bool thread_started() const { return _thread_ready; }
+    //!< returns true if the thread has been started.
+    /*!< this does not mean it is necessarily active. */
+
+  bool thread_finished() const { return !_thread_ready; }
+    //!< returns true if the thread has exited.
+    /*!< This can happen either by the thread responding to the stop() or
+    cancel() methods or when the thread stops of its own accord.  if this
+    returns true, it means that the thread will not start up again unless
+    the user invokes start(). */
+
+  bool thread_active() const { return _thread_active; }
+    //!< returns true if the thread is currently performing its activity.
+    /*!< this information is not necessarily relevant even at the point it is
+    returned (because of the nature of multethreading), so don't believe this
+    information for anything important. */
+
+  bool should_stop() const { return _stop_thread; }
+    //!< reports whether the thread should stop right now.
+    /*!< this returns true due to an invocation of stop() or cancel(). */
+
+private:
+  bool _thread_ready;  //!< is the thread ready to run (or running)?
+  bool _thread_active;  //!< is the thread currently performing?
+  bool _stop_thread;  //!< true if the thread should stop now.
+  void *_data;  //!< holds the thread's link back to whatever.
+#ifdef __UNIX__
+  pthread_t *_handle;  //!< thread structure for our thread.
+#elif defined(__WIN32__)
+  uintptr_t _handle;  //!< thread handle for the active thread, or zero.
+#endif
+  int _sleep_time;  //!< threads perform at roughly this interval.
+  bool _periodic;  //!< true if this thread should run repeatedly.
+  timely::time_stamp *_next_activation;  //!< the next time perform_activity is called.
+  timed_thread_types _how;  //!< how is the period evaluated?
+
+  // the OS level thread functions.
+#ifdef __UNIX__
+  static void *periodic_thread_driver(void *hidden_pointer);
+  static void *one_shot_thread_driver(void *hidden_pointer);
+#elif defined(__WIN32__)
+  static void periodic_thread_driver(void *hidden_pointer);
+  static void one_shot_thread_driver(void *hidden_pointer);
+#endif
+
+  // forbidden.
+  ethread(const ethread &);
+  ethread &operator =(const ethread &);
+};
+
+} //namespace.
+
+#endif
+