signal.hh
Go to the documentation of this file.
00001 
00037 #ifndef LibMultiSense_details_signal_hh
00038 #define LibMultiSense_details_signal_hh
00039 
00040 #include "details/utility/Thread.hh"
00041 #include "details/wire/Protocol.h"
00042 #include "details/wire/AckMessage.h"
00043 
00044 #include <map>
00045 
00046 namespace crl {
00047 namespace multisense {
00048 namespace details {
00049 
00050 //
00051 // Here we provide a thread-safe, blocking, signaling
00052 // interface for sensor message RX.
00053 
00054 class MessageWatch {
00055 public:
00056 
00057     void signal(wire::IdType id,
00058                 Status       status=Status_Ok) {
00059         utility::ScopedLock lock(m_lock);
00060 
00061         Map::iterator it = m_map.find(id);
00062 
00063         if (m_map.end() != it)
00064             it->second->post(status);
00065     };
00066 
00067     void signal(const wire::Ack& ack) {
00068         signal(ack.command, ack.status);
00069     };
00070 
00071 private:
00072 
00073     friend class ScopedWatch;
00074 
00075     typedef utility::WaitVar<Status>        Signal;
00076     typedef std::map<wire::IdType, Signal*> Map;
00077 
00078     void insert(wire::IdType type, 
00079                 Signal      *signalP) {
00080         utility::ScopedLock lock(m_lock);
00081 
00082         Map::const_iterator it = m_map.find(type);
00083 
00084         //
00085         // Hmm.. this will prohibit multiple threads
00086         // simultaneously commanding the sensor with this 
00087         // message ID.
00088 
00089         if (m_map.end() != it)
00090             CRL_EXCEPTION("ack signal already set for id=%d", type);
00091 
00092         m_map[type] = signalP;
00093     };
00094 
00095     void remove(wire::IdType type) {
00096         utility::ScopedLock lock(m_lock);
00097 
00098         Map::iterator it = m_map.find(type);
00099 
00100         if (m_map.end() == it)
00101             CRL_EXCEPTION("ack signal not found for id=%d\n", type);
00102 
00103         m_map.erase(it);
00104     };
00105 
00106     utility::Mutex m_lock;
00107     Map            m_map;
00108 };
00109 
00110  //
00111  // Exception-safe [de]registration of signal handlers
00112 
00113 class ScopedWatch {
00114 public:
00115 
00116     ScopedWatch(wire::IdType  t,
00117                 MessageWatch& m) : m_id(t), m_map(m) {
00118         m_map.insert(m_id, &m_signal);
00119     };
00120 
00121     ~ScopedWatch() {
00122         m_map.remove(m_id);
00123     };
00124 
00125     bool wait(Status&       status, 
00126               const double& timeout) {
00127         return m_signal.timedWait(status, timeout);
00128     };
00129 
00130 private:
00131 
00132     wire::IdType         m_id;
00133     MessageWatch&        m_map;
00134     MessageWatch::Signal m_signal;
00135 };
00136 
00137 }; // namespace details
00138 }; // namespace multisense
00139 }; // namespace crl
00140 
00141 
00142 #endif //  LibMultiSense_details_signal_hh


multisense_lib
Author(s):
autogenerated on Thu Aug 27 2015 14:01:11