/usr/include/ossim/base/Thread.h is in libossim-dev 2.2.2-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 | #ifndef ossimThread_HEADER
#define ossimThread_HEADER 1
#include <ossim/base/ossimConstants.h>
#include <ossim/base/Barrier.h>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <atomic>
#include <string>
namespace ossim{
/**
* Thread is an abstract class. It provides a
* general purpose thread interface that handles preliminary setup
* of the std c++11 thread. It allows one to derive
* from Thread and override the run method. Your thread should have calls
* to interrupt() whenever your thread is in a location that is
* interruptable. If cancel is called then any thread that is interruptable will
* throw an Interrupt and be caught in the base Thread class and then exit
* the thread.
*
* Example:
* @code
* #include <ossim/base/Thread.h>
* #include <ossim/base/Barrier.h>
* class TestThread : public ossim::Thread
* {
* public:
* TestThread():ossim::Thread(){}
* ~TestThread(){
* waitForCompletion();
* }
*
* protected:
* virtual void run()
* {
* barrierStart.block();
* for(int x =0 ; x < 10;++x){
* std::cout << "THREAD: " << getCurrentThreadId() << "\n";
* // simulate 10 milliseconds of uninterruptable work
* sleepInMilliSeconds(10);
* interrupt();
* }
* barrierFinished.block();
* }
* };
* int main(int agrc, char* argv[])
* {
* std::vector<std::shared_ptr<TestThread> > threads(nThreads);
* for(auto& thread:threads)
* {
* thread = std::make_shared<TestThread>();
* thread->start();
* }
*
* // now let's wait for each thread to finish
* // before exiting
* for(auto& thread:threads)
* {
* thread->waitForCompletion();
* }
* }
* @endcode
*/
class OSSIM_DLL Thread
{
public:
/**
* This is an Interrupt exception that is thrown if the @see cancel()
* is called and a call to @see interrupt() is made.
*/
class Interrupt : public std::exception{
public:
Interrupt(const std::string& what=""):m_what(what){}
virtual const char* what() const throw(){return m_what.c_str();}
protected:
std::string m_what;
};
/**
* Constructor for this thread
*/
Thread();
/**
* Destructor for this thread. It will determine if this thread is joinable
* to the main thread and if so it will do a join before continuing. If
* this is not done then an exeption is thrown by the std.
*/
virtual ~Thread();
/**
* Will actually start the thread and will call the @see internalRun.
*/
void start();
/**
* @return true if the current thread is running and false otherwise.
*/
bool isRunning()const{return m_running.load(std::memory_order_relaxed);}
/**
* This is typically set if @see cancel() is called or if @see setCancel
* is called with argument set to true.
*
* @return true if the thread is interruptable and false otherwise.
*/
bool isInterruptable()const{return m_interrupt.load(std::memory_order_relaxed);}
/**
* This basically requests that the thread be canceled. @see setCancel. Note,
* cancellation is not done immediately and a thread is only cancleed if derived
* classes call the interrupt().
*
* we will make these virtual just in case derived classes want to set conditions
*/
virtual void cancel(){setCancel(true);}
/**
* @param flag if true will enable the thread to be interruptable and if false
* the thread is not interruptable.
*/
virtual void setCancel(bool flag);
/**
* Convenience to allow one to wait for this thread to finish it's work.
*
* Allow this to be overriden.
*/
virtual void waitForCompletion();
/**
* Enables the thread to be paused. If the interrupt is called
* it will block the thread
*/
void pause();
/**
* This will resume a blocked thread.
*/
void resume();
/**
* @return true if the thread is blocked and false otherwise
*/
bool isPaused()const;
/**
* Utility method to allow one to sleep in seconds
*
* @param seconds to sleep
*/
static void sleepInSeconds(ossim_uint64 seconds);
/**
* Utility method to allow one to sleep in milliseconds
*
* @param millis to sleep
*/
static void sleepInMilliSeconds(ossim_uint64 millis);
/**
* Utility method to allow one to sleep in microseconds
*
* @param micros to sleep
*/
static void sleepInMicroSeconds(ossim_uint64 micros);
/**
* Utility method to get the current thread ID
*
* @return current thread ID
*/
static std::thread::id getCurrentThreadId();
/**
* Utility to return the number of processors (concurrent threads)
*/
static ossim_uint64 getNumberOfProcessors();
/**
* Will yield the current thread.
*/
static void yieldCurrentThread();
protected:
/**
* This method must be overriden and is the main entry
* point for any work that needs to be done
*/
virtual void run()=0;
/**
* This is the interrupt interface and will cause an internal exception that
* is caught by @see runInternal
*/
virtual void interrupt();
/**
* runInternal sets up internal flags such as setting m_running to true and checks
* to make sure it's not interrupted and will then call the @see run() method.
*
* runInternal also will trap any Interrupt exceptions. If the thread is interruptable
* and the work calls interrupt then an exception is thrown and the work is stopped and
* the execution of the thread is marked as not running and returns.
*/
virtual void runInternal();
private:
std::shared_ptr<std::thread> m_thread;
std::atomic<bool> m_running;
std::atomic<bool> m_interrupt;
std::shared_ptr<ossim::Barrier> m_pauseBarrier;
std::condition_variable m_runningCondition;
mutable std::mutex m_runningMutex;
/**
* @see cancel and @see setCancel
*/
void setInterruptable(bool flag);
};
}
#endif
|