Skip to content

Instantly share code, notes, and snippets.

@idispatch
Created May 4, 2016 05:21
Show Gist options
  • Save idispatch/f09c4c041ca7520b4abddd37d876c0d2 to your computer and use it in GitHub Desktop.
Save idispatch/f09c4c041ca7520b4abddd37d876c0d2 to your computer and use it in GitHub Desktop.
#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