16#ifndef INCLUDED_RMQT_FUTURE
17#define INCLUDED_RMQT_FUTURE
19#include <rmqt_result.h>
23#include <bslmt_condition.h>
24#include <bslmt_lockguard.h>
25#include <bslmt_mutex.h>
26#include <bsls_assert.h>
27#include <bsls_systemtime.h>
29#include <bsl_exception.h>
30#include <bsl_functional.h>
32#include <bsl_memory.h>
33#include <bsl_utility.h>
46namespace BloombergLP {
107template <
typename T =
void>
129 static Pair make(
const bsl::function<
void()>& cancelFunction);
178 template <
typename newT>
182 template <
typename newT>
195 template <
typename newT>
199 template <typename newT>
205 bsl::shared_ptr<Impl> d_impl;
213 template <
typename A,
typename B>
216 template <
typename A,
typename B>
217 static bsl::function<Future<B>(
const Result<A>&)> propagateError(
218 const bsl::function<
Future<B>(
const bsl::shared_ptr<A>&)>& fn)
220 return bdlf::BindUtil::bind(
221 &propagateErrorImplWithItem<A, B>, fn, bdlf::PlaceHolders::_1);
224 template <
typename T>
226 propagateError(
const bsl::function<
Future<T>()>& fn)
229 return bdlf::BindUtil::bind(
230 &propagateErrorImpl<T>, fn, bdlf::PlaceHolders::_1);
233 template <
typename T>
234 static bsl::function<rmqt::Result<T>()>
235 resultWrapper(
const bsl::function<T()>& tProducer)
237 return bdlf::BindUtil::bind(&resultWrapperImpl<T>, tProducer);
240 template <
typename T>
242 const bsl::function<
Result<T>()>& resultProducer)
244 maker(resultProducer());
247 template <
typename T>
248 static bsl::function<Result<T>(
const Result<T>&)>
251 return bdlf::BindUtil::bind(
252 &makerWrapperImpl<T>, maker, bdlf::PlaceHolders::_1);
255 template <
typename T>
256 static bsl::function<Future<T>(
const Result<
Future<T> >&)> unravelFuture()
258 bsl::function<Future<T>(
const bsl::shared_ptr<
Future<T> >&)> convert =
259 bdlf::BindUtil::bind(&unravelImpl<T>, bdlf::PlaceHolders::_1);
260 return propagateError<Future<T> >(convert);
263 template <
typename T>
266 return futurefuture.template thenFuture<T>(
267 FutureUtil::unravelFuture<T>());
271 template <
typename T>
283 template <
typename A,
typename B>
284 static Future<B> propagateErrorImplWithItem(
285 const bsl::function<
Future<B>(
const bsl::shared_ptr<A>&)>& b,
296 template <
typename T>
304 template <
typename T>
310 template <
typename T>
311 static Result<T> resultWrapperImpl(
const bsl::function<T()>& tProducer);
318 f.d_impl = bsl::make_shared<Impl>(bsl::function<
void()>());
320 return bsl::make_pair(f.d_impl->generateMaker(), f);
324bsl::pair<typename Future<T>::Maker,
Future<T> >
328 f.d_impl = bsl::make_shared<Impl>(cancelFunction);
330 return bsl::make_pair(f.d_impl->generateMaker(), f);
347 d_impl->blockUntilMade();
348 return d_impl->result();
354 bsls::TimeInterval timeoutTime = bsls::SystemTime::nowRealtimeClock();
355 timeoutTime += relativeTimeout;
362 if (d_impl->timedWaitUntilMade(absoluteTime)) {
363 return d_impl->result();
373 d_impl = p.second.d_impl;
385: d_impl(future.d_impl)
392 this->d_impl = future.d_impl;
397template <
typename newT>
401 return d_impl->addChain(converter);
405template <
typename newT>
406Future<newT> Future<T>::thenFuture(
407 const bsl::function<Future<newT>(
const Result<T>&)>& nextFutureMaker)
409 return d_impl->addChain(nextFutureMaker);
413Result<T> FutureUtil::resultWrapperImpl(
const bsl::function<T()>& tProducer)
415 return rmqt::Result<T>(bsl::make_shared<T>(tProducer()));
420FutureUtil::resultWrapperImpl<void>(
const bsl::function<
void()>& tProducer);
422template <
typename A,
typename B>
426 bslma::ManagedPtr<A> am(a.
value().managedPtr());
427 return Result<B>(bsl::shared_ptr<B>(
new B(am)));
434:
public bsl::enable_shared_from_this<typename Future<T>::Impl> {
436 static void made(
const bsl::weak_ptr<
typename Future<T>::Impl>& weakSelf,
439 bsl::shared_ptr<Future<T>::Impl>
self = weakSelf.lock();
442 BALL_LOG_SET_CATEGORY(
"RMQT.FUTURE.IMPL");
443 BALL_LOG_DEBUG <<
"Resolved " << bsl::string(!item ?
"un" :
"")
444 <<
"successful future<" <<
typeid(T).name()
452 bslmt::LockGuard<bslmt::Mutex> guard(&self->d_mutex);
453 self->d_result = item;
455 self->notifyChain(&guard);
456 self->d_condition.broadcast();
459 template <
typename newT>
460 void static converter(
465 maker(newTConverter(result));
475 template <
typename newT>
476 static void futureConverter(
482 bsl::shared_ptr<typename Future<newT>::Impl> bImpl = wpBImpl.lock();
487 cFut.then(FutureUtil::makerWrapper<newT>(bMaker));
489 bImpl->updateCancel(dFut.d_impl->getLifetimeExtension());
494 extendChainParentLifetime(
const bsl::shared_ptr<
typename Future<T>::Impl>&)
523 Impl(
const bsl::function<
void()>& cancelFunc)
529 , d_cancelFunc(cancelFunc)
535 BALL_LOG_SET_CATEGORY(
"RMQT.FUTURE.IMPL");
537 bslmt::LockGuard<bslmt::Mutex> guard(&d_mutex);
538 if (!d_done && d_cancelFunc) {
542 catch (bsl::exception& e) {
543 BALL_LOG_ERROR <<
"Caught exception in future<" <<
typeid(T).name()
544 <<
"> dtor: " << e.what();
547 BALL_LOG_ERROR <<
"Caught unknown exception in future<"
548 <<
typeid(T).name() <<
"> dtor";
552 void blockUntilMade()
554 bslmt::LockGuard<bslmt::Mutex> guard(&d_mutex);
556 d_condition.wait(&d_mutex);
561 bool timedWaitUntilMade(
const bsls::TimeInterval& absoluteTime)
563 bslmt::LockGuard<bslmt::Mutex> guard(&d_mutex);
565 if (bslmt::Condition::e_TIMED_OUT ==
566 d_condition.timedWait(&d_mutex, absoluteTime)) {
577 bdlf::PlaceHolders::_1);
580 const Result<T>& result(bslmt::LockGuard<bslmt::Mutex>* haveGuard = 0)
583 bslmt::LockGuard<bslmt::Mutex> guard(&d_mutex);
584 return resultNoLock();
586 BSLS_ASSERT(haveGuard->ptr() == &d_mutex);
587 return resultNoLock();
590 template <
typename newT>
597 bslmt::LockGuard<bslmt::Mutex> guard(&d_mutex);
599 converter(futurePair.first, newTConverter, result(&guard));
606 bdlf::PlaceHolders::_1));
609 return futurePair.second;
612 template <
typename newT>
619 bslmt::LockGuard<bslmt::Mutex> guard(&d_mutex);
621 futureConverter<newT>(
625 futurePair.second.d_impl),
629 d_chain.push_back(bdlf::BindUtil::bind(
634 futurePair.second.d_impl),
635 bdlf::PlaceHolders::_1));
637 return futurePair.second;
640 bsl::function<void()> getLifetimeExtension()
648 void updateCancel(
const bsl::function<
void()>& newCanc)
650 bslmt::LockGuard<bslmt::Mutex> guard(&d_mutex);
651 d_cancelFunc = newCanc;
661 void notifyChain(bslmt::LockGuard<bslmt::Mutex>* haveGuard)
663 BSLS_ASSERT(haveGuard);
664 typename bsl::list<bsl::function<void(
const Result<T>&)> >::iterator it;
665 for (it = d_chain.begin(); it != d_chain.end(); ++it) {
666 (*it)(result(haveGuard));
672 bslmt::Mutex d_mutex;
673 bslmt::Condition d_condition;
675 bsl::list<typename rmqt::Future<T>::Maker> d_chain;
681 bsl::function<void()> d_cancelFunc;
Definition: rmqt_future.h:208
static Result< B > convertViaManagedPtr(const Result< A > &a)
Definition: rmqt_future.h:423
Definition: rmqt_future.h:434
An async-style Future/Promise object.
Definition: rmqt_future.h:108
Future & operator=(const Future &future)
Assignment (copy) Future.
Definition: rmqt_future.h:390
bsl::function< void(const Result< T > &result)> Maker
Used to resolve a Future<T>. Somewhat equivalent to std::promise.
Definition: rmqt_future.h:111
Result< T > waitResult(const bsls::TimeInterval &relativeTimeout)
Fetch the result, waiting up to relativeTimeout period (from now) if it isn't ready.
Definition: rmqt_future.h:352
static Pair make()
Creates a pair of (Promise, Future).
Definition: rmqt_future.h:315
bsl::pair< typename Future< T >::Maker, Future< T > > Pair
A (Promise, Future) pair. Used to create Futures.
Definition: rmqt_future.h:114
Result< T > blockResult()
Fetch the result, and block if it isn't ready yet.
Definition: rmqt_future.h:345
Result< T > timedWaitResult(const bsls::TimeInterval &absoluteTime)
Fetch the result, waiting up to absoluteTime if it isn't ready.
Definition: rmqt_future.h:360
~Future()
Destructor.
Definition: rmqt_future.h:334
Result< T > tryResult()
Attempt to fetch the result, do not block.
Definition: rmqt_future.h:339
A result of an operation.
Definition: rmqt_result.h:37
const bsl::shared_ptr< T > & value() const
Definition: rmqt_result.h:71
const bsl::string & error() const
Definition: rmqt_result.h:75
int returnCode() const
Definition: rmqt_result.h:79