Created
May 4, 2016 05:21
-
-
Save idispatch/f09c4c041ca7520b4abddd37d876c0d2 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <bsl_vector.h> | |
#include <bsl_string.h> | |
#include <bsl_iostream.h> | |
#include <bdlb_variant.h> | |
#include <ball_administration.h> | |
#include <ball_defaultobserver.h> | |
#include <ball_loggermanagerconfiguration.h> | |
#include <ball_loggermanager.h> | |
#include <ball_severity.h> | |
#include <ball_log.h> | |
#include <bslmt_mutex.h> | |
#include <bslmt_condition.h> | |
#include <bsl_future.h> | |
#include <bsls_systemtime.h> | |
#include <btlmt_tcptimereventmanager.h> | |
using namespace BloombergLP; | |
template<typename VALUE> | |
class Future_ValueHolder { | |
// DATA | |
VALUE d_originalValue; | |
VALUE d_futureValue; | |
bslmt::Mutex d_mutex; | |
bslmt::Condition d_cond; | |
// NOT IMPLEMENTED | |
Future_ValueHolder(const Future_ValueHolder&); // = delete; | |
Future_ValueHolder& operator= (const Future_ValueHolder&); // = delete; | |
public: | |
// CREATORS | |
Future_ValueHolder() | |
: d_originalValue(), | |
d_futureValue() | |
{ } | |
Future_ValueHolder(VALUE value) | |
: d_originalValue(value), | |
d_futureValue(value) | |
{ } | |
// MANIPULATORS | |
bool wait(VALUE *result) { | |
bslmt::LockGuard<bslmt::Mutex> guard(&d_mutex); | |
bool succeeded = true; | |
while (true) { | |
if (d_originalValue != d_futureValue) { | |
*result = d_futureValue; | |
break; | |
} | |
const int rc = d_cond.wait(&d_mutex); | |
if (rc != 0) { | |
succeeded = false; | |
break; | |
} | |
} | |
return succeeded; | |
} | |
bool timedWait(VALUE *result, | |
const bsls::TimeInterval& timeInterval) { | |
const bsls::TimeInterval now = bsls::SystemTime::nowRealtimeClock(); | |
const bsls::TimeInterval absoluteTime(now + timeInterval); | |
bslmt::LockGuard<bslmt::Mutex> guard(&d_mutex); | |
bool succeeded = true; | |
while (true) { | |
if (d_originalValue != d_futureValue) { | |
*result = d_futureValue; | |
break; | |
} | |
const int rc = d_cond.timedWait(&d_mutex, absoluteTime); | |
if (rc == 0) { | |
continue; | |
} else { | |
succeeded = false; | |
break; | |
} | |
} | |
return succeeded; | |
} | |
void set(VALUE value) { | |
bslmt::LockGuard<bslmt::Mutex> guard(&d_mutex); | |
if (value != d_futureValue) { | |
d_futureValue = value; | |
d_cond.signal(); | |
} | |
} | |
void reset() | |
{ | |
bslmt::LockGuard<bslmt::Mutex> guard(&d_mutex); | |
if (d_originalValue != d_futureValue) { | |
d_futureValue = d_originalValue; | |
d_cond.signal(); | |
} | |
} | |
}; | |
template<typename VALUE> | |
class Future | |
{ | |
// DATA | |
bsl::shared_ptr<Future_ValueHolder<VALUE> > d_holder_sp; | |
public: | |
// TYPES | |
typedef VALUE Value; | |
// CREATORS | |
explicit Future(bslma::Allocator *basicAllocator = 0) | |
{ | |
d_holder_sp.createInplace(basicAllocator); | |
} | |
Future(Value value, bslma::Allocator *basicAllocator = 0) | |
{ | |
d_holder_sp.createInplace(basicAllocator, value); | |
} | |
Future(const Future& other) | |
{ | |
d_holder_sp = other.d_holder_sp; | |
} | |
// MANIPULATORS | |
Future& operator= (const Future& other) | |
{ | |
if (this != &other) { | |
d_holder_sp = other.d_holder_sp; | |
} | |
return *this; | |
} | |
bool wait(Value *result) | |
{ | |
return d_holder_sp->wait(result); | |
} | |
bool timedWait(Value *result, | |
const bsls::TimeInterval& timeInterval) | |
{ | |
return d_holder_sp->timedWait(result, timeInterval); | |
} | |
void set(Value value) | |
{ | |
return d_holder_sp->set(value); | |
} | |
void reset() | |
{ | |
return d_holder_sp->reset(); | |
} | |
}; | |
typedef Future<int> FutureResult; | |
void worker(FutureResult f) | |
{ | |
bslmt::ThreadUtil::sleep(bsls::TimeInterval(2.0)); | |
f.set(42); | |
} | |
int main() { | |
ball::DefaultObserver observer(&bsl::cout); | |
ball::LoggerManagerConfiguration configuration; | |
configuration.setDefaultThresholdLevelsIfValid(ball::Severity::e_TRACE); | |
ball::LoggerManagerScopedGuard guard(&observer, configuration); | |
BALL_LOG_SET_CATEGORY("DEMO"); | |
FutureResult future; | |
btlmt::TcpTimerEventManager e; | |
e.enable(); | |
e.execute(std::bind(worker, future)); | |
BALL_LOG_INFO << "Waiting for value... " << BALL_LOG_END; | |
FutureResult::Value value; | |
if (future.wait(&value)) { | |
BALL_LOG_INFO << "Received: " << value << BALL_LOG_END; | |
} else { | |
BALL_LOG_ERROR << "???" << BALL_LOG_END; | |
} | |
future.reset(); | |
if (future.timedWait(&value, bsls::TimeInterval(30.0))) { | |
BALL_LOG_ERROR<< "???" << BALL_LOG_END; | |
} else { | |
BALL_LOG_INFO << "Timeout" << BALL_LOG_END; | |
} | |
e.disable(); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment