4 * @copyright © Copyright 2008 by Intra2net AG
10 #include "async_callout.hpp"
12 #include <tracefunc.hpp>
13 #include <logfunc.hpp>
24 typedef boost::shared_ptr< Detail::Caller > CallerPtr;
26 typedef std::map< unsigned long, CallerPtr > CallMap;
29 unsigned long l_last_id=0;
35 * @brief creates a new id value for a call out.
38 * The id value is basically just a counter.
39 * It is implemented in a way that it can not be 0 and can deal with wrap arounds.
41 unsigned long create_call_out_id_value()
43 while ( l_call_map.find(++l_last_id) != l_call_map.end() and l_last_id != 0);
45 } // eo create_call_out_id_value
48 void add_call( CallerPtr caller )
52 l_call_map[ caller->getCallOutId().getValue() ] = caller;
57 bool remove_call( unsigned long id_value )
59 CallMap::iterator it= l_call_map.find(id_value);
60 if (it != l_call_map.end())
66 } // eo remove_call(unsigned long)
69 CallerPtr get_call(unsigned long id_value)
71 CallMap::iterator it= l_call_map.find(id_value);
72 if (it != l_call_map.end())
77 } // eo get_call(unsigned long)
80 bool has_call( unsigned long id_value )
82 CallMap::iterator it= l_call_map.find(id_value);
83 return (it != l_call_map.end() );
84 } // eo has_call(unsigned long)
88 } // eo namespace <anonymous>
93 ** implementation of class CallOutId
96 CallOutId::CallOutId()
99 } // eo CallOutId::CallOutId()
102 CallOutId::CallOutId(unsigned long value)
105 } // eo CallOutId::CallOutId(unsigned long)
108 bool CallOutId::thaw() const
110 if (m_caller_weak_ptr.expired())
114 CallerPtr call_ptr= get_call(m_value);
117 return call_ptr->thaw();
120 } // eo CallOutId::thaw() const
123 bool CallOutId::remove()
125 if (m_caller_weak_ptr.expired())
129 unsigned long value= m_value;
131 return remove_call(value);
132 } // eo CallOutId::remove()
135 bool CallOutId::active() const
137 return m_value!=0 and not m_caller_weak_ptr.expired() and has_call(m_value);
138 } // eo CallOutId::active() const
142 * @brief retruns if the call is frozen.
143 * @return @a true iff the call is frozen.
145 bool CallOutId::frozen() const
147 CallerPtr caller= m_caller_weak_ptr.lock();
152 return caller->frozen();
153 } // eo CallOutId::frozen() const
157 * @brief returns the remaining time until the call is done or thrown away (on frozen calls).
158 * @return the remaining time.
160 * The result only makes sense if the call is still active.
162 MilliTime CallOutId::remaining_time()
164 CallerPtr caller= m_caller_weak_ptr.lock();
165 if ( not active() or not caller )
170 get_current_monotonic_time(t);
171 MilliTime result= caller->getWhenTime();
174 return (result < t_null ? t_null : result);
175 } // eo CallOutId::remaining_time()
182 ** implementation of class Caller
185 Caller::Caller( boost::function< void() > f, long delta_sec, long delta_msec, bool frozen)
187 , m_call_out_id( create_call_out_id_value() )
192 setDeltaWhenTime( delta_sec, delta_msec);
193 } // eo Caller::Caller(boost::function< void() >,long)
199 } // eo Caller::~Caller()
202 void Caller::execute()
205 // NOTE: since the func may throw an exception, we first get a shared pointer
206 // (to prevent early deletion) and then we remove us from the call map.
207 CallerPtr ptr= shared_from_this();
208 m_call_out_id.remove();
210 if (m_func and not m_waiting)
212 m_func(); // may throw..., but at this point it doesn't harm.
213 //( it may harm at other places,...)
215 } // eo Caller::execute()
223 setDeltaWhenTime( 0, 0 );
227 } // eo Caller::thaw()
230 bool Caller::joinId()
232 if (m_call_out_id.m_caller_weak_ptr.expired())
234 m_call_out_id.m_caller_weak_ptr= shared_from_this();
239 } // eo Caller::joinId()
242 bool Caller::frozen() const
245 } // eo Caller::frozen() const
248 } // eo namespace Detail
253 * @brief remove a pending call by id.
255 * @param id the call id which should be removed.
256 * @return @a true iff the call was removed, @a false if no call with the given id was found.
258 bool removeCallOut( CallOutId& id )
261 } // eo removeCallOut(CallOutId&)
266 CallOutId callOut( boost::function< void() > f, long delta_sec)
268 CallerPtr caller( new Detail::Caller(f,delta_sec) );
270 return caller->getCallOutId();
271 } // eo callOut(boost::function< void() >,long)
274 CallOutId callOut( boost::function< void() > f, int delta_sec)
276 return callOut<long>(f,delta_sec);
277 } // eo callOut(boost::function< void() >,int)
281 CallOutId callOut( boost::function< void() > f, double delta_sec )
283 long delta_sec_i = (long)delta_sec;
284 long delta_sec_m = (long)((delta_sec - (double)delta_sec_i)*1000.0);
285 CallerPtr caller( new Detail::Caller(f,delta_sec_i, delta_sec_m) );
287 return caller->getCallOutId();
288 } // eo callOut(boost::function< void() >,double)
292 CallOutId callOut( boost::function< void() > f, float delta_sec )
294 return callOut<double>(f,delta_sec);
295 } // eo callOut(boost::function< void() >,float)
301 CallOutId frozenCall( boost::function< void() > f, long delta_sec)
303 CallerPtr caller( new Detail::Caller(f,delta_sec, 0, true) );
305 return caller->getCallOutId();
306 } // eo frozenCall(boost::function< void() >,long)
309 CallOutId frozenCall( boost::function< void() > f, int delta_sec)
311 return frozenCall<long>(f,delta_sec);
312 } // eo frozenCall(boost::function< void() >,int)
316 CallOutId frozenCall( boost::function< void() > f, double delta_sec )
318 long delta_sec_i = (long)delta_sec;
319 long delta_sec_m = (long)((delta_sec - (double)delta_sec_i)*1000.0);
320 CallerPtr caller( new Detail::Caller(f,delta_sec_i, delta_sec_m, true) );
322 return caller->getCallOutId();
323 } // eo frozenCall(boost::function< void() >,double)
327 CallOutId frozenCall( boost::function< void() > f, float delta_sec )
329 return frozenCall<double>(f,delta_sec);
330 } // eo frozenCall(boost::function< void() >,float)
333 } // eo namespace AsyncIo