flatten 20260225

This commit is contained in:
Timothy Prepscius
2026-02-25 12:39:24 -05:00
commit fa54be052a
315 changed files with 49791 additions and 0 deletions

View File

@@ -0,0 +1,2 @@
The scheduler needs to be redone.

View File

@@ -0,0 +1,161 @@
// TJP COPYRIGHT HEADER
//
// Timer.h
// algorithm
//
// Created by Timothy Prepscius on 1/19/18.
// Copyright © 2018 Timothy Prepscius. All rights reserved.
//
#pragma once
#include "Scheduler.hpp"
#include <core/future/Future.hpp>
namespace timprepscius {
namespace core {
namespace time {
struct RetryImmediateFailure : Exception
{
RetryImmediateFailure(Exception &&e) :
exception(std::move(e))
{}
Exception exception;
} ;
struct RetryOverrideDelayFailure : Exception
{
RetryOverrideDelayFailure(Exception &&e, float delay_) :
exception(std::move(e)),
delay(delay_)
{}
Exception exception;
float delay;
} ;
template<typename R, typename G, typename F>
void retry_(
const typename PromiseOfFutures<R>::Instance &promise,
const WeakSchedulerPtr &scheduler_,
int remaining, float m,
G &&delayF,
F &&f,
int retries
)
{
promise->add(
f().then([promise, scheduler_, remaining, m, delayF=std::move(delayF), f=std::move(f), retries](auto &&future) {
sLogDebug("core::time::retry", "time::retry " << logVar(remaining) << logVar(retries) << logVar(m));
if (remaining == 0)
{
promise->consume(future);
}
else
{
auto executeRetry = [&](int retries, float delay)
{
if (auto scheduler = strong(scheduler_))
{
sLogDebug("core::time::retry", "time::retry scheduling try " << logVar(remaining) << logVar(retries) << logVar(m) << logVar(delay));
promise->add(
scheduler->schedule<void>(
delay,
[promise, scheduler_, remaining, m, delayF=std::move(delayF), f=std::move(f), retries]() {
retry_<R>(
promise, scheduler_, remaining-1, m,
std::move(delayF),
std::move(f),
retries
);
}
)
);
}
else
{
promise->consume(future_of_exception<R>(NullPointerException{}));
}
} ;
try
{
promise->consume_throw_exception(future);
sLogDebug("core::time::retry", "time::retry consume_throw_exception succeeded " << logVar(remaining) << logVar(retries) << logVar(m));
}
catch (RetryImmediateFailure &e)
{
sLogDebug("core::time::retry", "time::retry failed RetryImmediateFailure " << logVar(e.what()));
promise->consume(future_of_exception<R>(std::move(e.exception)));
}
catch (RetryOverrideDelayFailure &e)
{
sLogDebug("core::time::retry", "time::retry failed RetryOverrideDelayFailure " << logVar(e.what()));
executeRetry(
retries+1,
e.delay
);
}
catch (Exception &e)
{
sLogDebug("core::time::retry", "time::retry failed " << logVar(e.what()));
executeRetry(
retries+1,
delayF(retries+1, m)
);
}
}
})
);
}
template<typename R, typename C, typename F>
Future<R> retry_function(const SchedulerPtr &scheduler, int count, float delay, C &&calc, F &&f)
{
auto promise = PromiseOfFutures<R>::generate();
retry_<R>(promise, weak(scheduler), count, delay, std::forward<C>(calc), std::forward<F>(f), 0);
return promise->get_future();
}
template<typename R, typename F>
Future<R> retry_exponential(const SchedulerPtr &scheduler, int count, float delay, F &&f)
{
auto expontial = [](int count, float delay) { return (count*count) * delay; };
return retry_function<R>(scheduler, count, delay, expontial, std::forward<F>(f));
}
template<typename R, typename F>
Future<R> retry_linear(const SchedulerPtr &scheduler, int count, float delay, F &&f)
{
auto linear = [](int count, float delay) { return count * delay; };
return retry_function<R>(scheduler, count, delay, linear, std::forward<F>(f));
}
template<typename R, typename F>
Future<R> retry_constant(const SchedulerPtr &scheduler, int count, float delay, F &&f)
{
auto constant = [](int count, float delay) { return delay; };
return retry_function<R>(scheduler, count, delay, constant, std::forward<F>(f));
}
template<typename R, typename F>
Future<R> retry(const SchedulerPtr &scheduler, int count, float delay, F &&f)
{
return retry_linear<R>(scheduler, count, delay, std::forward<F>(f));
}
} // namespace
} // namespace
} // namespace

View File

@@ -0,0 +1,34 @@
// TJP COPYRIGHT HEADER
//
// Timer.h
// algorithm
//
// Created by Timothy Prepscius on 1/19/18.
// Copyright © 2018 Timothy Prepscius. All rights reserved.
//
#include "Scheduler.hpp"
namespace timprepscius::core::time {
Scheduler::~Scheduler ()
{
}
Future<void> Scheduler::after(Time period)
{
Promise<void> v;
auto event = schedule(
period,
false,
[v]() {
auto r = v;
r.set_value();
}
);
return v.get_future().then([event](auto &&f) { return f.get(); });
}
} // namespace

View File

@@ -0,0 +1,24 @@
// TJP COPYRIGHT HEADER
//
// Timer.h
// algorithm
//
// Created by Timothy Prepscius on 1/19/18.
// Copyright © 2018 Timothy Prepscius. All rights reserved.
//
#pragma once
#include <core/ptr/Ptr.h>
namespace timprepscius::core::time {
struct Scheduler;
struct SchedulerEvent;
using SchedulerEventPtr = StrongPtr<SchedulerEvent>;
using SchedulerPtr = StrongPtr<Scheduler>;
using WeakSchedulerPtr = WeakPtr<Scheduler>;
} // namespace

View File

@@ -0,0 +1,52 @@
// TJP COPYRIGHT HEADER
//
// Timer.h
// algorithm
//
// Created by Timothy Prepscius on 1/19/18.
// Copyright © 2018 Timothy Prepscius. All rights reserved.
//
#pragma once
#include "Scheduler.h"
#include <core/future/Future.hpp>
#include <functional>
#include "Time.h"
namespace timprepscius::core::time {
struct SchedulerEvent {
virtual ~SchedulerEvent () {}
virtual void cancel () = 0;
} ;
struct Scheduler
{
virtual SchedulerEventPtr schedule(Duration period, bool repeat, std::function<void()> &&f) = 0;
virtual ~Scheduler();
Future<void> after(Duration period);
template<typename T, typename F>
Future<T> schedule(Duration period, F &&f);
template<typename T, typename F>
Future<T> schedule_future(Duration period, F &&f);
template<typename T, typename F>
Future<T> schedule(F &&f);
template<typename T, typename F>
Future<T> schedule_future(F &&f);
template<typename F>
void run(F &&f);
};
} // namespace
#include "Scheduler.inl"

View File

@@ -0,0 +1,97 @@
// TJP COPYRIGHT HEADER
//
// Timer.h
// algorithm
//
// Created by Timothy Prepscius on 1/19/18.
// Copyright © 2018 Timothy Prepscius. All rights reserved.
//
#pragma once
#include "Scheduler.h"
#include <core/future/Future.hpp>
#include <core/future/PromiseOfFutures.hpp>
#include <functional>
#include "Time.h"
namespace timprepscius::core::time {
template<typename T, typename F>
Future<T> Scheduler::schedule(Duration period, F &&f)
{
Promise<T> v;
auto event = schedule(
period,
false,
[v, f=std::move(f)]() {
auto r = v;
r.consume(f);
}
);
return v.get_future().then([event](auto &&f) { return f.get(); });
}
// this should be rewritten to use the above "after", should be much simpler
template<typename T, typename F>
Future<T> Scheduler::schedule_future(Duration period, F &&f_)
{
auto v = PromiseOfFutures<T>::generate();
auto execute = Promise<void>();
v->add(
execute.get_future().then(
[v_=weak(v), f=std::move(f_)](auto &&) {
if (auto v = strong(v_))
{
v->add(
f().then(
[v_](auto &&r) {
if (auto v = strong(v_))
v->consume(r);
}
)
);
}
}
)
);
auto event = schedule(
period,
false,
[execute]() {
auto execute_ = execute;
execute_.set_value();
}
);
return v->get_future().then([event](auto &&f) { return f.get(); });
}
template<typename T, typename F>
Future<T> Scheduler::schedule(F &&f)
{
return schedule<T>(Immediate, std::forward<F>(f));
}
template<typename T, typename F>
Future<T> Scheduler::schedule_future(F &&f)
{
return schedule_future<T>(Immediate, std::forward<F>(f));
}
template<typename F>
void Scheduler::run(F &&f)
{
return schedule<void>(std::forward<F>(f)).wait();
}
} // namespace

View File

@@ -0,0 +1,229 @@
// TJP COPYRIGHT HEADER
//
// Timer.h
// algorithm
//
// Created by Timothy Prepscius on 1/19/18.
// Copyright © 2018 Timothy Prepscius. All rights reserved.
//
#include "SchedulerManual.hpp"
#include <core/log/Log.h>
namespace timprepscius {
namespace core {
namespace time {
SchedulerManual::SchedulerManual(const StrongPtr<TimeSource> &timeSource_) :
timeSource (timeSource_),
running(false),
stopped(false),
nextIndex(1)
{
}
SchedulerManual::~SchedulerManual()
{
debug_assert(!running);
}
SchedulerManual::EventImp::EventImp(
SchedulerManual *parent_,
Time period_,
bool repeat_,
std::function<void()> &&f_
) :
parent(parent_),
period(period_),
repeat(repeat_),
f(f_)
{
}
SchedulerEventPtr SchedulerManual::schedule_no_lock (const StrongPtr<EventImp> &eventImp, Time now)
{
debug_assert(mutex.locked_by_caller());
eventImp->at = { now + eventImp->period, nextIndex++ };
sLogDebug ("core::time::SchedulerManual", logVar(ptr_of(eventImp)) << logVar(now) << logVar(eventImp->at.time) << logVar(eventImp->period) << logVar(eventImp->repeat));
auto insertion = events.emplace(eventImp->at, weak(eventImp));
debug_assert(insertion.second);
debug_assert(eventImp->position == events.end());
eventImp->position = insertion.first;
changed.notify_all();
return eventImp;
}
SchedulerEventPtr SchedulerManual::schedule (const StrongPtr<EventImp> &eventImp, Time now)
{
auto l = lock_of(mutex);
return schedule_no_lock(eventImp, now);
}
SchedulerEventPtr SchedulerManual::schedule (Time period, bool repeat, std::function<void()> &&f)
{
auto eventImp = strong<EventImp>(
this,
period,
repeat,
std::move(f)
);
eventImp->position = events.end();
schedule(eventImp, timeSource->getTime());
return eventImp;
}
void SchedulerManual::EventImp::cancel ()
{
auto lock = lock_of(mutex);
parent->cancel(this);
}
void SchedulerManual::cancel(EventImp *event)
{
sLogDebug("core::time::scheduler", logVar(event));
if (event)
{
auto l = lock_of(mutex);
if (event->position != events.end())
events.erase(event->position);
event->position = events.end();
changed.notify_all();
}
}
Duration SchedulerManual::durationUntilNextEvent()
{
debug_assert(mutex.locked_by_caller());
if (events.empty())
return time::FarFuture;
return events.begin()->first.time - timeSource->getTime();
}
void SchedulerManual::update_has_lock ()
{
auto currentTime = EventTime { timeSource->getTime(), nextIndex };
while (!events.empty())
{
if (stopped)
return;
auto position = events.begin();
auto &event_ = position->second;
if (position->first < currentTime)
{
auto event = strong(event_);
debug_assert(mutex.locked_by_caller());
events.erase(position);
if (event)
{
event->position = events.end();
if (event->repeat)
{
schedule_no_lock(event, currentTime.time);
}
}
mutex.unlock();
if (event)
{
auto lock = lock_of(event->mutex);
try
{
event->f();
}
catch (Exception &e)
{
sLogError("core::time::SchedulerManual", "there was a problem houston " << e.what());
}
}
}
else
{
break;
}
mutex.lock();
}
};
void SchedulerManual::run()
{
running = true;
stopped = false;
mutex.lock();
while (!stopped)
{
auto duration = std::chrono::duration<double>(toReal(durationUntilNextEvent()));
auto now = std::chrono::system_clock::now();
auto then = now + duration;
changed.wait_until(mutex, then);
update_has_lock();
}
running = false;
stopped_.notify_all();
mutex.unlock();
}
void SchedulerManual::cycle()
{
mutex.lock();
running = true;
if (!events.empty())
{
update_has_lock();
}
running = false;
mutex.unlock();
}
void SchedulerManual::stop ()
{
auto lock = lock_of(mutex);
stopped = true;
changed.notify_all();
}
void SchedulerManual::clear ()
{
auto l = lock_of(mutex);
for (auto &[id, event_]: events)
{
if (auto event = strong(event_))
{
event->position = events.end();
}
}
events.clear();
}
} // namespace
} // namespace
} // namespace

View File

@@ -0,0 +1,21 @@
// TJP COPYRIGHT HEADER
//
// Timer.h
// algorithm
//
// Created by Timothy Prepscius on 1/19/18.
// Copyright © 2018 Timothy Prepscius. All rights reserved.
//
#pragma once
namespace timprepscius {
namespace core {
namespace time {
struct SchedulerManual;
} // namespace
} // namespace
} // namespace

View File

@@ -0,0 +1,121 @@
// TJP COPYRIGHT HEADER
//
// Timer.h
// algorithm
//
// Created by Timothy Prepscius on 1/19/18.
// Copyright © 2018 Timothy Prepscius. All rights reserved.
//
#pragma once
#include "Scheduler.hpp"
#include <core/types/Types.h>
#include <core/ptr/Ptr.hpp>
#include <core/threads/Lock.h>
#include <core/allocator/MapAllocator.hpp>
#include <core/containers/Map.h>
#include <core/threads/Atomic.h>
#include "TimeSource.hpp"
#include <set>
#include <map>
#include <atomic>
namespace timprepscius {
namespace core {
namespace time {
struct SchedulerManual : Scheduler
{
struct EventImp;
struct EventTime
{
Time time;
u64 index;
bool operator<(const EventTime &rhs) const
{
if (time == rhs.time)
return index < rhs.index;
return time < rhs.time;
}
bool operator==(const EventTime &rhs) const
{
return time == rhs.time && index == rhs.index;
}
} ;
typedef WeakPtr<EventImp> WeakEventPtr;
typedef core::MapAllocator<EventTime, WeakEventPtr> Allocator;
typedef Map<EventTime, WeakEventPtr,std::less<EventTime>,Allocator> Events;
// typedef Map<EventTime, WeakEventPtr> Events;
struct EventImp : SchedulerEvent
{
SchedulerManual *parent;
Time period;
bool repeat;
std::function<void()> f;
EventTime at;
RecursiveMutex mutex;
Events::iterator position;
EventImp(
SchedulerManual *parent,
Time period,
bool repeat,
std::function<void()> &&f
);
bool operator<(const EventImp &rhs) const
{
return at < rhs.at;
}
void cancel () override;
} ;
Atomic<u64> nextIndex;
StrongPtr<TimeSource> timeSource;
Mutex mutex;
Events events;
SchedulerManual(const StrongPtr<TimeSource> &timeSource_);
~SchedulerManual();
SchedulerEventPtr schedule (Time period, bool repeat, std::function<void()> &&f) override;
SchedulerEventPtr schedule (const StrongPtr<EventImp> &event, Time now);
SchedulerEventPtr schedule_no_lock (const StrongPtr<EventImp> &event, Time now);
void cancel(EventImp *event);
Time durationUntilNextEvent();
Event changed;
void update_has_lock();
bool running, stopped;
Event stopped_;
void run();
void cycle();
void stop();
void clear();
};
} // namespace
} // namespace
} // namespace

View File

@@ -0,0 +1,101 @@
// TJP COPYRIGHT HEADER
//
// Timer.h
// algorithm
//
// Created by Timothy Prepscius on 1/19/18.
// Copyright © 2018 Timothy Prepscius. All rights reserved.
//
#include "SchedulerPool.hpp"
namespace timprepscius {
namespace core {
namespace time {
SchedulerPool::SchedulerPool () :
nextIndex(0)
{
}
SchedulerPool::~SchedulerPool ()
{
clear();
}
SchedulerEventPtr SchedulerPool::schedule(const SchedulerPtr &scheduler, Time period, std::function<void()> &&f)
{
auto event = scheduler->schedule(period, true, std::move(f));
auto lock = lock_of(mutex);
events.insert(event);
return event;
}
SchedulerEventPtr SchedulerPool::once(const SchedulerPtr &scheduler, Time period, std::function<void()> &&f)
{
auto index = nextIndex++;
auto weak = weak_this(this);
// I'm locking before the schedule because, very rarely, the scheduler runs the event
// before I can put it in the map, which causes it to stay in the map forever.
// If this causes some locking problem in the future, I could also
// allocate it in the map, then schedule, and then finally, if the map still
// has the entry for it, set it - if not discard.
auto lock = lock_of(mutex);
auto event = scheduler->schedule(
period,
false,
[this, weak, f=std::move(f), index]() {
if (auto that = strong(weak))
{
remove_once(index);
f();
}
}
);
onces.emplace(index, event);
sLogDebug("core::time::SchedulerPool", logOfThis(this) << logVar(index) << logVar(onces.size()) << logVar(period) << logVar(event));
return event;
}
void SchedulerPool::remove_once_no_lock(size_t index)
{
debug_assert(mutex.locked_by_caller());
auto i = onces.find(index);
if (i != onces.end())
{
sLogDebug("core::time::SchedulerPool", logOfThis(this) << logVar(index) << logVar(onces.size()) << logVar(i->second));
onces.erase(i);
}
else
{
sLogDebug("core::time::SchedulerPool", logOfThis(this) << logVar(index) << logVar(onces.size()) << logLabel("failed"));
}
}
void SchedulerPool::remove_once(size_t index)
{
auto lock = lock_of(mutex);
remove_once_no_lock(index);
}
void SchedulerPool::clear ()
{
auto lock = lock_of(mutex);
onces.clear();
events.clear();
}
} // namespace
} // namespace
} // namespace

View File

@@ -0,0 +1,21 @@
// TJP COPYRIGHT HEADER
//
// Timer.h
// algorithm
//
// Created by Timothy Prepscius on 1/19/18.
// Copyright © 2018 Timothy Prepscius. All rights reserved.
//
#pragma once
namespace timprepscius {
namespace core {
namespace time {
struct SchedulerPool;
} // namespace
} // namespace
} // namespace

View File

@@ -0,0 +1,47 @@
// TJP COPYRIGHT HEADER
//
// Timer.h
// algorithm
//
// Created by Timothy Prepscius on 1/19/18.
// Copyright © 2018 Timothy Prepscius. All rights reserved.
//
#pragma once
#include "SchedulerPool.h"
#include "Scheduler.hpp"
#include <core/threads/Lock.hpp>
#include <core/ptr/Ptr.hpp>
#include <map>
#include <set>
namespace timprepscius {
namespace core {
namespace time {
struct SchedulerPool : StrongThis<SchedulerPool>
{
QMutex mutex;
std::set<SchedulerEventPtr> events;
std::atomic<size_t> nextIndex;
std::map<size_t, SchedulerEventPtr> onces;
SchedulerPtr scheduler;
SchedulerPool();
virtual ~SchedulerPool ();
SchedulerEventPtr schedule(const SchedulerPtr &scheduler, Time period, std::function<void()> &&f);
SchedulerEventPtr once(const SchedulerPtr &scheduler, Time offset, std::function<void()> &&f);
void remove_once(size_t index);
void remove_once_no_lock(size_t index);
void clear();
} ;
} // namespace
} // namespace
} // namespace

View File

@@ -0,0 +1,50 @@
// TJP COPYRIGHT HEADER
/*
* Author: Timothy Prepscius
* Copyright: See copyright located at COPYRIGHTLOCATION
*/
#include "Time.h"
#include <thread>
#include <chrono>
#include <core/testing/catch.hpp>
namespace timprepscius::core::time {
SCENARIO("time::Time")
{
GIVEN("a time source")
{
auto t0 = v1::now();
std::this_thread::sleep_for(std::chrono::milliseconds(20));
auto t1 = v1::now();
auto dt = t1 - t0;
auto mL = 15 * v1::Millisecond;
auto mR = 25 * v1::Millisecond;
auto between = mL < dt && dt < mR;
REQUIRE(between);
}
GIVEN("a time source")
{
auto t0 = v2::now();
std::this_thread::sleep_for(std::chrono::milliseconds(20));
auto t1 = v2::now();
auto dt = t1 - t0;
auto mL = 15 * v2::Millisecond;
auto mR = 25 * v2::Millisecond;
auto between = mL < dt && dt < mR;
REQUIRE(between);
}
}
} // namespace

View File

@@ -0,0 +1,20 @@
// TJP COPYRIGHT HEADER
//
// Timer.h
// algorithm
//
// Created by Timothy Prepscius on 1/19/18.
// Copyright © 2018 Timothy Prepscius. All rights reserved.
//
#pragma once
#include "Time_v1.h"
#include "Time_v2.h"
namespace timprepscius::core::time {
using namespace v1;
}

View File

@@ -0,0 +1,39 @@
// TJP COPYRIGHT HEADER
/*
* Author: Timothy Prepscius
* Copyright: See copyright located at COPYRIGHTLOCATION
*/
#include "TimeSource.hpp"
#include "Time.h"
#include <thread>
#include <chrono>
#include <core/testing/catch.hpp>
namespace timprepscius::core::time {
SCENARIO("time::TimeSource")
{
GIVEN("a time source")
{
auto ts = new TimeSourceStandard();
auto t0 = ts->getTime();
std::this_thread::sleep_for(std::chrono::milliseconds(20));
auto t1 = ts->getTime();
auto dt = t1 - t0;
auto mL = 15 * Millisecond;
auto mR = 25 * Millisecond;
auto between = mL < dt && dt < mR;
REQUIRE(between);
}
}
} // namespace

View File

@@ -0,0 +1,32 @@
// TJP COPYRIGHT HEADER
//
// Server.hpp
// TimeSync
//
// Created by Timothy Prepscius on 1/27/17.
// Copyright © 2017 Timothy Prepscius. All rights reserved.
//
#pragma once
namespace timprepscius {
namespace core {
namespace time {
class TimeSource;
template<typename Resolution>
class TimeSourceResolution;
template<typename clock_type_t, typename Resolution>
class TimeSourceResolutionStandard;
class ManualTimeSource;
class TimeSourceStandard;
} // namespace
} // namespace
} // namespace

View File

@@ -0,0 +1,129 @@
// TJP COPYRIGHT HEADER
//
// Server.hpp
// TimeSync
//
// Created by Timothy Prepscius on 1/27/17.
// Copyright © 2017 Timothy Prepscius. All rights reserved.
//
#pragma once
#include "TimeSource.h"
#include "Time.h"
#include <chrono>
namespace timprepscius {
namespace core {
namespace time {
class TimeSource
{
public:
virtual ~TimeSource () {}
virtual Time getTime () = 0;
virtual size_t getTimeTicks () = 0;
virtual Time getTimeAt (size_t ticks) = 0;
} ;
template<typename Resolution>
class TimeSourceResolution : public TimeSource
{
public:
typedef Resolution resolution;
Time getTime () override
{
return getTimeAt(getTimeTicks());
}
Time getTimeAt (size_t ticks) override
{
auto denominator = Resolution::period::den;
if (time::Denominator == 1)
return toTime((time::V)ticks / denominator);
const auto d0 = time::Denominator;
const auto d1 = denominator;
if (d0 > d1)
{
V r = d0 / d1;
return toTime( (time::V)ticks * r );
}
else
{
V r = d1 / d0;
return toTime( (time::V)ticks / r );
}
}
} ;
template<typename clock_type_t, typename Resolution = std::chrono::microseconds>
class TimeSourceResolutionStandard : public TimeSourceResolution<Resolution>
{
public:
typedef clock_type_t clock_type;
protected:
clock_type clock;
typename clock_type::time_point startTime;
public:
TimeSourceResolutionStandard ()
{
startTime = clock.now();
}
size_t getTimeTicks () override
{
return std::chrono::duration_cast<Resolution>(clock.now() - startTime).count() + 0;
}
} ;
class ManualTimeSource : public TimeSource
{
protected:
TimeSource *source;
size_t ticks;
public:
ManualTimeSource(TimeSource *source_) :
source(source_)
{
ticks = source_->getTimeTicks();
}
size_t getTimeTicks () override
{
return ticks;
}
Time getTime () override
{
return source->getTimeAt(ticks);
}
Time getTimeAt (size_t ticks) override
{
return source->getTimeAt(ticks);
}
void update ()
{
ticks = source->getTimeTicks();
}
} ;
class TimeSourceStandard : public TimeSourceResolutionStandard<std::chrono::high_resolution_clock>
{
public:
TimeSourceStandard() {}
} ;
} // namespace
} // namespace
} // namespace

View File

@@ -0,0 +1,140 @@
// TJP COPYRIGHT HEADER
//
// Timer.h
// algorithm
//
// Created by Timothy Prepscius on 1/19/18.
// Copyright © 2018 Timothy Prepscius. All rights reserved.
//
#include "Time_v1.h"
#include <chrono>
#include <ctime>
#include <sys/time.h>
#include <time.h>
#include <cmath>
#include <cstring>
namespace timprepscius::core::time::v1 {
Time now()
{
return getSecondsSince1970();
}
Real toReal(Time v)
{
return v;
}
Time toTime(Real v)
{
return v;
}
size_t getMillisecondsSince1970_count()
{
auto t = std::chrono::duration_cast< std::chrono::milliseconds > (std::chrono::system_clock::now().time_since_epoch());
return t.count();
}
size_t getSecondsSince1970_count()
{
auto t = std::chrono::duration_cast< std::chrono::seconds > (std::chrono::system_clock::now().time_since_epoch());
return t.count();
}
double getSecondsSince1970 ()
{
auto t = std::chrono::duration_cast< std::chrono::milliseconds > (
std::chrono::system_clock::now().time_since_epoch()
);
return t.count() / 1000.0;
}
double getSecondsSince1970_UTC ()
{
return getSecondsSince1970();
/*
std::chrono::system_clock clock;
auto now = clock.now();
auto timenow = clock.to_time_t(now);
time_t t = ::time(NULL);
std::tm tm;
struct timeval now;
struct timezone zone;
std::memset(&tm, 0, sizeof(tm));
std::memset(&now, 0, sizeof(now));
std::memset(&zone, 0, sizeof(zone));
::gmtime_r(&t, &tm);
gettimeofday(&now, &zone);
auto secondsAtNow = ::mktime(&tm);
auto partialSeconds = ((double)now.tv_usec)/(1000 * 1000);
return (double)secondsAtNow + partialSeconds;
*/
}
double getUTCFromLocal(double time)
{
// https://stackoverflow.com/questions/38686405/convert-time-t-from-localtime-zone-to-utc
std::time_t lt = time;
std::tm tm;
std::memset(&tm, 0, sizeof(tm));
::gmtime_r(&lt, &tm);
tm.tm_isdst = -1;
auto utc = std::mktime(&tm);
double iptr;
auto result = utc + modf(time, &iptr);
return result;
}
// https://arstechnica.com/civis/viewtopic.php?t=136625
size_t getLocalFromUTCOffset ()
{
time_t currtime;
struct tm * timeinfo;
::time ( &currtime );
timeinfo = gmtime ( &currtime );
time_t utc = mktime( timeinfo );
timeinfo = localtime ( &currtime );
time_t local = mktime( timeinfo );
// Get offset in hours from UTC
size_t HOUR_IN_SECONDS = 60 *60;
double offsetFromUTC = difftime(utc, local);
// Adjust for DST
if (timeinfo->tm_isdst)
{
offsetFromUTC -= 1 * HOUR_IN_SECONDS;
}
return offsetFromUTC;
}
} // namespace

View File

@@ -0,0 +1,45 @@
// TJP COPYRIGHT HEADER
//
// Timer.h
// algorithm
//
// Created by Timothy Prepscius on 1/19/18.
// Copyright © 2018 Timothy Prepscius. All rights reserved.
//
#pragma once
#include <cstddef>
namespace timprepscius::core::time::v1 {
using V = double;
using Time = V;
using Duration = Time;
const V Denominator = 1.0;
using Real = double;
const Time Zero = 0;
const Duration FarFuture = 10000000000.0;
const Duration Immediate = 0;
const Duration Second = 1.0;
const Duration Decisecond = Second / 10;
const Duration Centisecond = Second / 100;
const Duration Millisecond = Second / 1000;
size_t getMillisecondsSince1970_count();
size_t getSecondsSince1970_count();
double getSecondsSince1970 ();
double getSecondsSince1970_UTC ();
double getUTCFromLocal(double time);
size_t getLocalFromUTCOffset ();
Time now();
Real toReal(Time t);
Time toTime(V v);
} // namespace

View File

@@ -0,0 +1,51 @@
// TJP COPYRIGHT HEADER
//
// Timer.h
// algorithm
//
// Created by Timothy Prepscius on 1/19/18.
// Copyright © 2018 Timothy Prepscius. All rights reserved.
//
#include "Time_v2.h"
#include <ostream>
#include <limits>
#include <chrono>
namespace timprepscius::core::time::v2 {
const Duration Millisecond = { 1000 };
const Duration Centisecond = { 10 * Millisecond };
const Duration Decisecond = { 100 * Millisecond };
const Duration Second = { 1000 * Millisecond };
const V Denominator = Second.v;
const Time FarFuture = { std::numeric_limits<V>::max() };
const Duration Immediate = { 0 };
const Time Zero = { 0 };
std::ostream &operator <<(std::ostream &o, const Duration &v)
{
return o << v.v;
}
Time now()
{
auto t = std::chrono::duration_cast< std::chrono::milliseconds > (std::chrono::system_clock::now().time_since_epoch());
return (size_t)t.count() * Millisecond;
}
double toReal(Time time)
{
return (double)time.v / Second.v;
}
Time toTime(V v)
{
return { v };
}
} // namespace

View File

@@ -0,0 +1,61 @@
// TJP COPYRIGHT HEADER
//
// Timer.h
// algorithm
//
// Created by Timothy Prepscius on 1/19/18.
// Copyright © 2018 Timothy Prepscius. All rights reserved.
//
#pragma once
#include <core/types/Types.h>
#include <iosfwd>
namespace timprepscius::core::time::v2 {
using V = s64;
struct Duration {
V v;
} ;
using Time = Duration;
extern const V Denominator;
extern const Duration Second;
extern const Duration Decisecond;
extern const Duration Centisecond;
extern const Duration Millisecond;
extern const Time FarFuture;
extern const Duration Immediate;
extern const Time Zero;
Duration operator *(const Duration &lhs, const Duration &rhs);
Duration operator /(const Duration &lhs, const Duration &rhs);
Duration operator +(const Duration &lhs, const Duration &rhs);
Duration operator -(const Duration &lhs, const Duration &rhs);
bool operator >(const Duration &lhs, const Duration &rhs);
bool operator <(const Duration &lhs, const Duration &rhs);
bool operator ==(const Duration &lhs, const Duration &rhs);
bool operator !=(const Duration &lhs, const Duration &rhs);
Duration operator *(int, const Duration &rhs);
Duration operator *(size_t, const Duration &rhs);
Duration operator *(double, const Duration &rhs);
Duration operator /(const Duration &rhs, double);
Duration operator /(const Duration &rhs, int);
Duration operator /(const Duration &rhs, size_t);
std::ostream &operator <<(std::ostream &o, const Duration &v);
Time now();
double toReal(Time);
Time toTime(V v);
} // namespace
#include "Time_v2.inl"

View File

@@ -0,0 +1,114 @@
// TJP COPYRIGHT HEADER
//
// Timer.h
// algorithm
//
// Created by Timothy Prepscius on 1/19/18.
// Copyright © 2018 Timothy Prepscius. All rights reserved.
//
#pragma once
#include "Time_v2.h"
namespace timprepscius::core::time::v2 {
inline
Duration operator *(const Duration &lhs, const Duration &rhs)
{
return { lhs.v * rhs.v };
}
inline
Duration operator /(const Duration &lhs, const Duration &rhs)
{
return { lhs.v / rhs.v };
}
inline
Duration operator +(const Duration &lhs, const Duration &rhs)
{
return { lhs.v + rhs.v };
}
inline
Duration operator -(const Duration &lhs, const Duration &rhs)
{
return { lhs.v - rhs.v };
}
inline
bool operator >(const Duration &lhs, const Duration &rhs)
{
return lhs.v > rhs.v;
}
inline
bool operator <(const Duration &lhs, const Duration &rhs)
{
return lhs.v < rhs.v;
}
inline
bool operator ==(const Duration &lhs, const Duration &rhs)
{
return lhs.v == rhs.v;
}
inline
bool operator !=(const Duration &lhs, const Duration &rhs)
{
return lhs.v != rhs.v;
}
template<typename T>
Duration mul(T lhs, const Duration &rhs)
{
return { (V)(lhs * rhs.v) };
}
template<typename T>
Duration dev(const Duration &lhs, T t)
{
return { (V)(lhs.v / t) };
}
inline
Duration operator *(int lhs, const Duration &rhs)
{
return mul(lhs, rhs);
}
inline
Duration operator *(size_t lhs, const Duration &rhs)
{
return mul(lhs, rhs);
}
inline
Duration operator *(double lhs, const Duration &rhs)
{
return mul(lhs, rhs);
}
inline
Duration operator /(const Duration &lhs, double rhs)
{
return dev(lhs, rhs);
}
inline
Duration operator /(const Duration &lhs, int rhs)
{
return dev(lhs, rhs);
}
inline
Duration operator /(const Duration &lhs, size_t rhs)
{
return dev(lhs, rhs);
}
} // namespace