4 #include "ace/Future.h"
6 #if !defined (ACE_LACKS_PRAGMA_ONCE)
8 #endif /* ACE_LACKS_PRAGMA_ONCE */
10 #if defined (ACE_HAS_THREADS)
12 # include "ace/Guard_T.h"
13 # include "ace/Recursive_Thread_Mutex.h"
15 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
17 ACE_ALLOC_HOOK_DEFINE_Tc(ACE_Future_Holder
)
18 ACE_ALLOC_HOOK_DEFINE_Tc(ACE_Future_Observer
)
19 ACE_ALLOC_HOOK_DEFINE_Tc(ACE_Future_Rep
)
20 ACE_ALLOC_HOOK_DEFINE_Tc(ACE_Future
)
23 ACE_Future_Holder
<T
>::ACE_Future_Holder (void)
28 ACE_Future_Holder
<T
>::ACE_Future_Holder (const ACE_Future
<T
> &item
)
34 ACE_Future_Holder
<T
>::~ACE_Future_Holder (void)
39 ACE_Future_Observer
<T
>::ACE_Future_Observer (void)
44 ACE_Future_Observer
<T
>::~ACE_Future_Observer (void)
48 // Dump the state of an object.
50 template <class T
> void
51 ACE_Future_Rep
<T
>::dump (void) const
53 #if defined (ACE_HAS_DUMP)
54 ACELIB_DEBUG ((LM_DEBUG
, ACE_BEGIN_DUMP
, this));
55 ACELIB_DEBUG ((LM_DEBUG
,
57 (int) this->ref_count_
));
58 ACELIB_DEBUG ((LM_INFO
,"value_:\n"));
60 ACELIB_DEBUG ((LM_DEBUG
, ACE_TEXT (" (NON-NULL)\n")));
62 //FUZZ: disable check_for_NULL
63 ACELIB_DEBUG ((LM_DEBUG
, ACE_TEXT (" (NULL)\n")));
64 //FUZZ: enable check_for_NULL
66 ACELIB_DEBUG ((LM_INFO
,"value_ready_:\n"));
67 this->value_ready_
.dump ();
68 ACELIB_DEBUG ((LM_INFO
,"value_ready_mutex_:\n"));
69 this->value_ready_mutex_
.dump ();
70 ACELIB_DEBUG ((LM_DEBUG
, ACE_END_DUMP
));
71 #endif /* ACE_HAS_DUMP */
74 template <class T
> ACE_Future_Rep
<T
> *
75 ACE_Future_Rep
<T
>::internal_create (void)
77 ACE_Future_Rep
<T
> *temp
= 0;
84 template <class T
> ACE_Future_Rep
<T
> *
85 ACE_Future_Rep
<T
>::create (void)
87 // Yes set ref count to zero.
88 ACE_Future_Rep
<T
> *temp
= internal_create ();
89 #if defined (ACE_NEW_THROWS_EXCEPTIONS)
93 ACE_ASSERT (temp
!= 0);
94 #endif /* ACE_NEW_THROWS_EXCEPTIONS */
99 template <class T
> ACE_Future_Rep
<T
> *
100 ACE_Future_Rep
<T
>::attach (ACE_Future_Rep
<T
>*& rep
)
102 ACE_ASSERT (rep
!= 0);
103 // Use value_ready_mutex_ for both condition and ref count management
104 ACE_GUARD_RETURN (ACE_SYNCH_RECURSIVE_MUTEX
, r_mon
, rep
->value_ready_mutex_
, 0);
109 template <class T
> void
110 ACE_Future_Rep
<T
>::detach (ACE_Future_Rep
<T
>*& rep
)
112 ACE_ASSERT (rep
!= 0);
113 // Use value_ready_mutex_ for both condition and ref count management
114 ACE_GUARD (ACE_SYNCH_RECURSIVE_MUTEX
, r_mon
, rep
->value_ready_mutex_
);
116 if (rep
->ref_count_
-- == 0)
118 ACE_MT (r_mon
.release ());
119 // We do not need the lock when deleting the representation.
120 // There should be no side effects from deleting rep and we don
121 // not want to release a deleted mutex.
126 template <class T
> void
127 ACE_Future_Rep
<T
>::assign (ACE_Future_Rep
<T
>*& rep
, ACE_Future_Rep
<T
>* new_rep
)
129 ACE_ASSERT (rep
!= 0);
130 ACE_ASSERT (new_rep
!= 0);
131 // Use value_ready_mutex_ for both condition and ref count management
132 ACE_GUARD (ACE_SYNCH_RECURSIVE_MUTEX
, r_mon
, rep
->value_ready_mutex_
);
134 ACE_Future_Rep
<T
>* old
= rep
;
137 // detached old last for exception safety
138 if (old
->ref_count_
-- == 0)
140 ACE_MT (r_mon
.release ());
141 // We do not need the lock when deleting the representation.
142 // There should be no side effects from deleting rep and we don
143 // not want to release a deleted mutex.
149 ACE_Future_Rep
<T
>::ACE_Future_Rep (void)
152 value_ready_ (value_ready_mutex_
)
157 ACE_Future_Rep
<T
>::~ACE_Future_Rep (void)
162 template <class T
> int
163 ACE_Future_Rep
<T
>::ready (void) const
165 return this->value_
!= 0;
168 template <class T
> int
169 ACE_Future_Rep
<T
>::set (const T
&r
,
170 ACE_Future
<T
> &caller
)
172 // If the value is already produced, ignore it...
173 if (this->value_
== 0)
175 ACE_GUARD_RETURN (ACE_SYNCH_RECURSIVE_MUTEX
,
177 this->value_ready_mutex_
,
179 // Otherwise, create a new result value. Note the use of the
180 // Double-checked locking pattern to avoid multiple allocations.
182 if (this->value_
== 0) // Still no value, so proceed
184 ACE_NEW_RETURN (this->value_
,
188 // Remove and notify all subscribed observers.
189 typename
OBSERVER_COLLECTION::iterator iterator
=
190 this->observer_collection_
.begin ();
192 typename
OBSERVER_COLLECTION::iterator end
=
193 this->observer_collection_
.end ();
195 while (iterator
!= end
)
197 OBSERVER
*observer
= *iterator
++;
200 observer
->update (caller
);
204 // Signal all the waiting threads.
205 return this->value_ready_
.broadcast ();
207 // Destructor releases the lock.
212 template <class T
> int
213 ACE_Future_Rep
<T
>::get (T
&value
,
214 ACE_Time_Value
*tv
) const
216 // If the value is already produced, return it.
217 if (this->value_
== 0)
219 ACE_GUARD_RETURN (ACE_SYNCH_RECURSIVE_MUTEX
, ace_mon
,
220 this->value_ready_mutex_
,
222 // If the value is not yet defined we must block until the
223 // producer writes to it.
225 while (this->value_
== 0)
226 // Perform a timed wait.
227 if (this->value_ready_
.wait (tv
) == -1)
230 // Destructor releases the lock.
233 value
= *this->value_
;
237 template <class T
> int
238 ACE_Future_Rep
<T
>::attach (ACE_Future_Observer
<T
> *observer
,
239 ACE_Future
<T
> &caller
)
241 ACE_GUARD_RETURN (ACE_SYNCH_RECURSIVE_MUTEX
, ace_mon
, this->value_ready_mutex_
, -1);
243 // Otherwise, create a new result value. Note the use of the
244 // Double-checked locking pattern to avoid corrupting the list.
248 // If the value is already produced, then notify observer
249 if (this->value_
== 0)
250 result
= this->observer_collection_
.insert (observer
);
252 observer
->update (caller
);
257 template <class T
> int
258 ACE_Future_Rep
<T
>::detach (ACE_Future_Observer
<T
> *observer
)
260 ACE_GUARD_RETURN (ACE_SYNCH_RECURSIVE_MUTEX
, ace_mon
, this->value_ready_mutex_
, -1);
262 // Remove all occurrences of the specified observer from this
264 return this->observer_collection_
.remove (observer
);
268 ACE_Future_Rep
<T
>::operator T ()
270 // If the value is already produced, return it.
271 if (this->value_
== 0)
273 // Constructor of ace_mon acquires the mutex.
274 ACE_GUARD_RETURN (ACE_SYNCH_RECURSIVE_MUTEX
, ace_mon
, this->value_ready_mutex_
, 0);
276 // If the value is not yet defined we must block until the
277 // producer writes to it.
281 while (this->value_
== 0)
282 if (this->value_ready_
.wait () == -1)
283 // What to do in this case since we've got to indicate
284 // failure somehow? Exceptions would be nice, but they're
288 // Destructor releases the mutex
291 return *this->value_
;
295 ACE_Future
<T
>::ACE_Future (void)
296 : future_rep_ (FUTURE_REP::create ())
301 ACE_Future
<T
>::ACE_Future (const ACE_Future
<T
> &r
)
302 : future_rep_ (FUTURE_REP::attach (((ACE_Future
<T
> &) r
).future_rep_
))
307 ACE_Future
<T
>::ACE_Future (const T
&r
)
308 : future_rep_ (FUTURE_REP::create ())
310 this->future_rep_
->set (r
, *this);
314 ACE_Future
<T
>::~ACE_Future (void)
316 FUTURE_REP::detach (future_rep_
);
319 template <class T
> bool
320 ACE_Future
<T
>::operator== (const ACE_Future
<T
> &r
) const
322 return r
.future_rep_
== this->future_rep_
;
325 template <class T
> bool
326 ACE_Future
<T
>::operator!= (const ACE_Future
<T
> &r
) const
328 return r
.future_rep_
!= this->future_rep_
;
331 template <class T
> int
332 ACE_Future
<T
>::cancel (const T
&r
)
335 return this->future_rep_
->set (r
, *this);
338 template <class T
> int
339 ACE_Future
<T
>::cancel (void)
341 // If this ACE_Future is already attached to a ACE_Future_Rep,
342 // detach it (maybe delete the ACE_Future_Rep).
343 FUTURE_REP::assign (this->future_rep_
,
344 FUTURE_REP::create ());
348 template <class T
> int
349 ACE_Future
<T
>::set (const T
&r
)
351 // Give the pointer to the result to the ACE_Future_Rep.
352 return this->future_rep_
->set (r
, *this);
355 template <class T
> int
356 ACE_Future
<T
>::ready (void) const
358 // We're ready if the ACE_Future_rep is ready...
359 return this->future_rep_
->ready ();
362 template <class T
> int
363 ACE_Future
<T
>::get (T
&value
,
364 ACE_Time_Value
*tv
) const
366 // We return the ACE_Future_rep.
367 return this->future_rep_
->get (value
, tv
);
370 template <class T
> int
371 ACE_Future
<T
>::attach (ACE_Future_Observer
<T
> *observer
)
373 return this->future_rep_
->attach (observer
, *this);
376 template <class T
> int
377 ACE_Future
<T
>::detach (ACE_Future_Observer
<T
> *observer
)
379 return this->future_rep_
->detach (observer
);
383 ACE_Future
<T
>::operator T ()
385 // note that this will fail (and COREDUMP!)
386 // if future_rep_ == 0 !
389 // this is impossible unless somebody is so stupid to
390 // try something like this:
396 // perform type conversion on Future_Rep.
400 template <class T
> void
401 ACE_Future
<T
>::operator = (const ACE_Future
<T
> &rhs
)
405 // bind <this> to the same <ACE_Future_Rep> as <r>.
407 // This will work if &r == this, by first increasing the ref count
408 ACE_Future
<T
> &r
= (ACE_Future
<T
> &) rhs
;
409 FUTURE_REP::assign (this->future_rep_
,
410 FUTURE_REP::attach (r
.future_rep_
));
413 template <class T
> void
414 ACE_Future
<T
>::dump (void) const
416 #if defined (ACE_HAS_DUMP)
417 ACELIB_DEBUG ((LM_DEBUG
,
418 ACE_BEGIN_DUMP
, this));
420 if (this->future_rep_
)
421 this->future_rep_
->dump ();
423 ACELIB_DEBUG ((LM_DEBUG
,
425 #endif /* ACE_HAS_DUMP */
428 template <class T
> ACE_Future_Rep
<T
> *
429 ACE_Future
<T
>::get_rep ()
431 return this->future_rep_
;
434 ACE_END_VERSIONED_NAMESPACE_DECL
436 #endif /* ACE_HAS_THREADS */
438 #endif /* ACE_FUTURE_CPP */