TuttleOFX  1
TuttleOFX/libraries/tuttle/src/tuttle/host/ThreadEnv.hpp
Go to the documentation of this file.
00001 #ifndef _TUTTLE_HOST_CORE_THREADENV_HPP_
00002 #define _TUTTLE_HOST_CORE_THREADENV_HPP_
00003 
00004 #include <tuttle/host/NodeListArg.hpp>
00005 #include <tuttle/host/ComputeOptions.hpp>
00006 #include <tuttle/host/memory/MemoryCache.hpp>
00007 
00008 #include <boost/thread/thread.hpp>
00009 #include <boost/thread/recursive_mutex.hpp>
00010 #include <boost/thread/tss.hpp>
00011 #include <tuttle/common/atomic.hpp>
00012 #include <boost/bind.hpp>
00013 
00014 #include <boost/signals2.hpp>
00015 
00016 
00017 namespace tuttle {
00018 namespace host {
00019 
00020 class Graph;
00021 
00022 /**
00023  * Utility class to compute a graph inside a thread.
00024  */
00025 class ThreadEnv
00026 {
00027 public:
00028         typedef ThreadEnv This;
00029         typedef boost::signals2::signal<void ()> SignalType;
00030         
00031         ThreadEnv( const bool asynchronous = true )
00032         : _asynchronous( asynchronous )
00033         , _isRunning(false)
00034         , _result(false)
00035         {
00036                 // By default the Thread doesn't return a buffer.
00037                 _options.setReturnBuffers(false);
00038         }
00039         
00040         inline memory::MemoryCache& getImageCache() { return _imageCache; }
00041         inline const memory::MemoryCache& getImageCache() const { return _imageCache; }
00042         
00043         inline ComputeOptions& getComputeOptions() { return _options; }
00044         inline const ComputeOptions& getComputeOptions() const { return _options; }
00045         
00046         inline This& setAsynchronous( const bool v = true )
00047         {
00048                 _asynchronous = v;
00049                 return *this;
00050         }
00051         
00052         /// @brief Main functions
00053         /// @{
00054         
00055         /**
00056          * @brief Is this ThreadEnv executing a compute?
00057          * Thread Safe
00058          */
00059         inline bool isRunning() { return _isRunning.load( boost::memory_order_relaxed ); }
00060 
00061         /**
00062          * @brief Launch the graph computation in a synchrone or asynchrone way.
00063          */
00064         void compute( Graph& graph, const NodeListArg& nodes = NodeListArg() );
00065         
00066         /**
00067          * @brief The application would like to abort the process (from another thread).
00068          * Thread Safe
00069          */
00070         inline void abort() { _options.abort(); }
00071         
00072         inline void join() { _thread.join(); }
00073         
00074         /**
00075          * @brief Result status of the lastest compute.
00076          * Thread Safe
00077          */
00078         inline bool getResult() const { return _result.load( boost::memory_order_relaxed ); }
00079         
00080         inline SignalType& getSignalEnd() { return _signalEnd; }
00081         
00082         /// @}
00083         
00084 private:
00085         static void runProcessFunc( ThreadEnv* threadEnv, Graph& graph, const std::list<std::string>& nodes );
00086         
00087         /**
00088          * @brief Result status of the lastest compute.
00089          * Thread Safe
00090          */
00091         void setResult( const bool res ) { _result.store( res, boost::memory_order_relaxed ); }
00092         
00093         /**
00094          * @brief Is this ThreadEnv executing a compute?
00095          * Thread Safe
00096          */
00097         void setIsRunning( const bool res ) { _isRunning.store( res, boost::memory_order_relaxed ); }
00098         
00099 private:
00100         boost::thread _thread;
00101 
00102         bool _asynchronous;
00103         memory::MemoryCache _imageCache;
00104         ComputeOptions _options;
00105 
00106         boost::atomic_bool _isRunning;
00107         boost::atomic_bool _result;
00108         
00109         SignalType _signalEnd;
00110 };
00111 
00112 }
00113 }
00114 
00115 #endif