first check-in of feisty meow codebase. many things broken still due to recent
[feisty_meow.git] / core / library / processes / ethread.h
1 #ifndef ETHREAD_CLASS
2 #define ETHREAD_CLASS
3
4 /*****************************************************************************\
5 *                                                                             *
6 *  Name   : ethread (easy thread)                                             *
7 *  Author : Chris Koeritz                                                     *
8 *                                                                             *
9 *******************************************************************************
10 * Copyright (c) 1998-$now By Author.  This program is free software; you can  *
11 * redistribute it and/or modify it under the terms of the GNU General Public  *
12 * License as published by the Free Software Foundation; either version 2 of   *
13 * the License or (at your option) any later version.  This is online at:      *
14 *     http://www.fsf.org/copyleft/gpl.html                                    *
15 * Please send any updates to: fred@gruntose.com                               *
16 \*****************************************************************************/
17
18 #include <basis/contracts.h>
19 #include <timely/time_stamp.h>
20
21 #include <signal.h>
22
23 #ifndef __APPLE__
24 #ifdef __UNIX__
25 //  typedef long unsigned int pthread_t;
26 #endif
27 #endif
28
29 namespace processes {
30
31 //! Provides a platform-independent object for adding threads to a program.
32 /*!
33   This greatly simplifies creating and managing threads by hiding all the
34   operating system details.  The user just needs to override one virtual
35   function in their derived object to perform the main activity of their
36   thread.  The thread can be a one time invocation or it can run periodically.
37   Control over the thread remains in the hands of the program that started
38   it.
39 */
40
41 class ethread : public virtual basis::root_object
42 {
43 public:
44   ethread();
45     //!< creates a single-shot thread object.
46     /*!< the OS-level thread is not started until the start() method is
47     invoked.  this constructor creates a thread that will only execute
48     once; when start() is called, the thread starts up and performs its
49     activity.  it will then stop.  to run it again, start() must be invoked
50     again.  however, if the perform_activity() method just keeps running,
51     then the single-shot thread can live as long as needed.  it is important
52     for such a thread to periodically check should_exit() to avoid having
53     the program hang-up when it's supposed to be shutting down. */
54
55   enum timed_thread_types { TIGHT_INTERVAL, SLACK_INTERVAL };
56
57   ethread(int sleep_timer, timed_thread_types how = SLACK_INTERVAL);
58     //!< creates a managed thread object that runs on a periodic interval.
59     /*!< the thread will activate every "sleep_timer" milliseconds.  when
60     start() is invoked, the thread's action (via the perform_activity()
61     method) will be performed at regular intervals (using the specified value
62     for "sleep_timer").  the thread will continue activating until the stop()
63     method is called.  a faster interval is used internally during sleep
64     periods such that calling stop() will not consume the whole "sleep_timer"
65     period.  if the "how" is TIGHT_INTERVAL, then the thread will activate
66     every "sleep_timer" milliseconds, as accurately as possible.  if the "how"
67     is SLACK_INTERVAL, then the thread will activate after a delay of
68     "sleep_timer" milliseconds from its last activation.  the latter mode
69     allows the thread to consume its entire intended operation time knowing
70     that there will still be slack time between when it is active.  the
71     former mode requires the thread to only run for some amount of time less
72     than its "sleep_timer"; otherwise it will hog a lot of the CPU. */
73
74   virtual ~ethread();
75
76   DEFINE_CLASS_NAME("ethread");
77
78   bool start(void *thread_data);
79     //!< causes the thread to start, if it has not already been started.
80     /*!< if the thread has terminated previously, then this will restart the
81     thread.  true is returned if the thread could be started.  false is
82     returned if the thread could not be started or if it is already running. */
83
84   void stop();
85     //!< tells the thread to shutdown and waits for the shutdown to occur.
86     /*!< this will cause the OS thread to terminate once the current (if any)
87     perform_activity() invocation completes.  the thread may be restarted
88     with start(). */
89
90   void cancel() { _stop_thread = true; }
91     //!< stops the thread but does not wait until it has terminated.
92     /*!< this is appropriate for use within the perform_activity() method. */
93
94 //  virtual void pre_thread();
95     //!< invoked just after after start(), when the OS thread is created.
96     /*!< the call comes in _from_ the thread itself, so the derived method
97     must be thread-safe. */
98 //  virtual void post_thread();
99     //!< this is invoked just before the thread is to be terminated.
100     /*!< the call also comes in from the thread itself, so the implementation
101     must be thread-safe. */
102
103   virtual void perform_activity(void *thread_data) = 0;
104     //!< carries out the main activity of the thread.
105     /*!< this is called repeatedly by the main thread management function and
106     so should return as soon as possible.  if it does not return fairly
107     regularly, then the thread shutdown process will not occur until the
108     function exits on its own. */
109
110   void exempt_stop();
111     //!< this special form of stop() does not wait for the thread to exit.
112     /*!< it is required in certain weird OS situations where the thread does
113     not exit properly and stop() would cause an infinite wait.  don't use it
114     unless you are SURE that this is the case. */
115
116   void reschedule(int delay = 0);
117     //!< causes a periodic thread to activate after "delay" milliseconds from now.
118     /*!< this resets the normal activation period, but after the next
119     activation occurs, the normal activation interval takes over again. */
120
121   int sleep_time() const { return _sleep_time; }
122     //!< returns the current periodic thread interval.
123     /*!< this is only meaningful for periodic threads. */
124
125   void sleep_time(int new_sleep) { _sleep_time = new_sleep; }
126     //!< adjusts the period for the thread to the "new_sleep" interval.
127     /*!< this is only meaningful for periodic threads. */
128
129   // these functions report on the thread state.
130
131   bool thread_started() const { return _thread_ready; }
132     //!< returns true if the thread has been started.
133     /*!< this does not mean it is necessarily active. */
134
135   bool thread_finished() const { return !_thread_ready; }
136     //!< returns true if the thread has exited.
137     /*!< This can happen either by the thread responding to the stop() or
138     cancel() methods or when the thread stops of its own accord.  if this
139     returns true, it means that the thread will not start up again unless
140     the user invokes start(). */
141
142   bool thread_active() const { return _thread_active; }
143     //!< returns true if the thread is currently performing its activity.
144     /*!< this information is not necessarily relevant even at the point it is
145     returned (because of the nature of multethreading), so don't believe this
146     information for anything important. */
147
148   bool should_stop() const { return _stop_thread; }
149     //!< reports whether the thread should stop right now.
150     /*!< this returns true due to an invocation of stop() or cancel(). */
151
152 private:
153   bool _thread_ready;  //!< is the thread ready to run (or running)?
154   bool _thread_active;  //!< is the thread currently performing?
155   bool _stop_thread;  //!< true if the thread should stop now.
156   void *_data;  //!< holds the thread's link back to whatever.
157 #ifdef __UNIX__
158   pthread_t *_handle;  //!< thread structure for our thread.
159 #elif defined(__WIN32__)
160   uintptr_t _handle;  //!< thread handle for the active thread, or zero.
161 #endif
162   int _sleep_time;  //!< threads perform at roughly this interval.
163   bool _periodic;  //!< true if this thread should run repeatedly.
164   timely::time_stamp *_next_activation;  //!< the next time perform_activity is called.
165   timed_thread_types _how;  //!< how is the period evaluated?
166
167   // the OS level thread functions.
168 #ifdef __UNIX__
169   static void *periodic_thread_driver(void *hidden_pointer);
170   static void *one_shot_thread_driver(void *hidden_pointer);
171 #elif defined(__WIN32__)
172   static void periodic_thread_driver(void *hidden_pointer);
173   static void one_shot_thread_driver(void *hidden_pointer);
174 #endif
175
176   // forbidden.
177   ethread(const ethread &);
178   ethread &operator =(const ethread &);
179 };
180
181 } //namespace.
182
183 #endif
184