Skip to content

Commit

Permalink
Reformatted.
Browse files Browse the repository at this point in the history
  • Loading branch information
Bosma committed Feb 17, 2018
1 parent e18fe3a commit 3894d0c
Show file tree
Hide file tree
Showing 4 changed files with 298 additions and 285 deletions.
162 changes: 81 additions & 81 deletions Cron.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,95 +5,95 @@
#include <iterator>

namespace Bosma {
using Clock = std::chrono::system_clock;

inline void add(std::tm &tm, Clock::duration time) {
auto tp = Clock::from_time_t(std::mktime(&tm));
auto tp_adjusted = tp + time;
auto tm_adjusted = Clock::to_time_t(tp_adjusted);
tm = *std::localtime(&tm_adjusted);
}
using Clock = std::chrono::system_clock;

inline void verify_and_set(const std::string& token, const std::string &expression,
int &field, const int lower_bound, const int upper_bound, const bool adjust = false) {
if (token == "*")
field = -1;
else {
field = std::stoi(token);
if (field < lower_bound || field > upper_bound) throw std::runtime_error("cron out of range: " + expression);
if (adjust)
field--;
inline void add(std::tm &tm, Clock::duration time) {
auto tp = Clock::from_time_t(std::mktime(&tm));
auto tp_adjusted = tp + time;
auto tm_adjusted = Clock::to_time_t(tp_adjusted);
tm = *std::localtime(&tm_adjusted);
}
}

class Cron {
public:
explicit Cron(const std::string &expression) {
std::istringstream iss(expression);
std::vector<std::string> tokens{std::istream_iterator<std::string>{iss},
std::istream_iterator<std::string>{}};

if (tokens.size() != 5) throw std::runtime_error("malformed cron string: " + expression);

verify_and_set(tokens[0], expression, minute, 0, 59);
verify_and_set(tokens[1], expression, hour, 0, 23);
verify_and_set(tokens[2], expression, day, 1, 31);
verify_and_set(tokens[3], expression, month, 1, 12, true);
verify_and_set(tokens[4], expression, day_of_week, 0, 6);
inline void verify_and_set(const std::string &token, const std::string &expression,
int &field, const int lower_bound, const int upper_bound, const bool adjust = false) {
if (token == "*")
field = -1;
else {
field = std::stoi(token);
if (field < lower_bound || field > upper_bound) throw std::runtime_error("cron out of range: " + expression);
if (adjust)
field--;
}
}

// http://stackoverflow.com/a/322058/1284550
Clock::time_point cron_to_next() const {
// get current time as a tm object
auto now = Clock::to_time_t(Clock::now());
std::tm next(*std::localtime(&now));
// it will always at least run the next minute
next.tm_sec = 0;
add(next, std::chrono::minutes(1));
while (true) {
if (month != -1 && next.tm_mon != month) {
// add a month
// if this will bring us over a year, increment the year instead and reset the month
if (next.tm_mon + 1 > 11) {
next.tm_mon = 0;
next.tm_year++;
} else
next.tm_mon++;
class Cron {
public:
explicit Cron(const std::string &expression) {
std::istringstream iss(expression);
std::vector<std::string> tokens{std::istream_iterator<std::string>{iss},
std::istream_iterator<std::string>{}};

next.tm_mday = 1;
next.tm_hour = 0;
next.tm_min = 0;
continue;
}
if (day != -1 && next.tm_mday != day) {
add(next, std::chrono::hours(24));
next.tm_hour = 0;
next.tm_min = 0;
continue;
}
if (day_of_week != -1 && next.tm_wday != day_of_week) {
add(next, std::chrono::hours(24));
next.tm_hour = 0;
next.tm_min = 0;
continue;
}
if (hour != -1 && next.tm_hour != hour) {
add(next, std::chrono::hours(1));
next.tm_min = 0;
continue;
if (tokens.size() != 5) throw std::runtime_error("malformed cron string: " + expression);

verify_and_set(tokens[0], expression, minute, 0, 59);
verify_and_set(tokens[1], expression, hour, 0, 23);
verify_and_set(tokens[2], expression, day, 1, 31);
verify_and_set(tokens[3], expression, month, 1, 12, true);
verify_and_set(tokens[4], expression, day_of_week, 0, 6);
}
if (minute != -1 && next.tm_min != minute) {

// http://stackoverflow.com/a/322058/1284550
Clock::time_point cron_to_next() const {
// get current time as a tm object
auto now = Clock::to_time_t(Clock::now());
std::tm next(*std::localtime(&now));
// it will always at least run the next minute
next.tm_sec = 0;
add(next, std::chrono::minutes(1));
continue;
}
break;
}
while (true) {
if (month != -1 && next.tm_mon != month) {
// add a month
// if this will bring us over a year, increment the year instead and reset the month
if (next.tm_mon + 1 > 11) {
next.tm_mon = 0;
next.tm_year++;
} else
next.tm_mon++;

// telling mktime to figure out dst
next.tm_isdst = -1;
return Clock::from_time_t(std::mktime(&next));
}
next.tm_mday = 1;
next.tm_hour = 0;
next.tm_min = 0;
continue;
}
if (day != -1 && next.tm_mday != day) {
add(next, std::chrono::hours(24));
next.tm_hour = 0;
next.tm_min = 0;
continue;
}
if (day_of_week != -1 && next.tm_wday != day_of_week) {
add(next, std::chrono::hours(24));
next.tm_hour = 0;
next.tm_min = 0;
continue;
}
if (hour != -1 && next.tm_hour != hour) {
add(next, std::chrono::hours(1));
next.tm_min = 0;
continue;
}
if (minute != -1 && next.tm_min != minute) {
add(next, std::chrono::minutes(1));
continue;
}
break;
}

// telling mktime to figure out dst
next.tm_isdst = -1;
return Clock::from_time_t(std::mktime(&next));
}

int minute, hour, day, month, day_of_week;
};
int minute, hour, day, month, day_of_week;
};
}
97 changes: 53 additions & 44 deletions InterruptableSleep.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,48 +7,57 @@
#include <sstream>

namespace Bosma {
class InterruptableSleep {

using Clock = std::chrono::system_clock;

// InterruptableSleep offers a sleep that can be interrupted by any thread.
// It can be interrupted multiple times
// and be interrupted before any sleep is called (the sleep will immediately complete)
// Has same interface as condition_variables and futures, except with sleep instead of wait.
// For a given object, sleep can be called on multiple threads safely, but is not recommended as behaviour is undefined.

public:
InterruptableSleep() : interrupted(false) {
}
InterruptableSleep(const InterruptableSleep &) = delete;
InterruptableSleep(InterruptableSleep &&) noexcept = delete;
~InterruptableSleep() noexcept = default;
InterruptableSleep& operator=(const InterruptableSleep &) noexcept = delete;
InterruptableSleep& operator=(InterruptableSleep &&) noexcept = delete;

void sleep_for(Clock::duration duration) {
std::unique_lock<std::mutex> ul(m);
cv.wait_for(ul, duration, [this] { return interrupted; });
interrupted = false;
}
void sleep_until(Clock::time_point time) {
std::unique_lock<std::mutex> ul(m);
cv.wait_until(ul, time, [this] { return interrupted; });
interrupted = false;
}
void sleep() {
std::unique_lock<std::mutex> ul(m);
cv.wait(ul, [this] { return interrupted; });
interrupted = false;
}
void interrupt() {
std::lock_guard<std::mutex> lg(m);
interrupted = true;
cv.notify_one();
}
private:
bool interrupted;
std::mutex m;
std::condition_variable cv;
};
class InterruptableSleep {

using Clock = std::chrono::system_clock;

// InterruptableSleep offers a sleep that can be interrupted by any thread.
// It can be interrupted multiple times
// and be interrupted before any sleep is called (the sleep will immediately complete)
// Has same interface as condition_variables and futures, except with sleep instead of wait.
// For a given object, sleep can be called on multiple threads safely, but is not recommended as behaviour is undefined.

public:
InterruptableSleep() : interrupted(false) {
}

InterruptableSleep(const InterruptableSleep &) = delete;

InterruptableSleep(InterruptableSleep &&) noexcept = delete;

~InterruptableSleep() noexcept = default;

InterruptableSleep &operator=(const InterruptableSleep &) noexcept = delete;

InterruptableSleep &operator=(InterruptableSleep &&) noexcept = delete;

void sleep_for(Clock::duration duration) {
std::unique_lock<std::mutex> ul(m);
cv.wait_for(ul, duration, [this] { return interrupted; });
interrupted = false;
}

void sleep_until(Clock::time_point time) {
std::unique_lock<std::mutex> ul(m);
cv.wait_until(ul, time, [this] { return interrupted; });
interrupted = false;
}

void sleep() {
std::unique_lock<std::mutex> ul(m);
cv.wait(ul, [this] { return interrupted; });
interrupted = false;
}

void interrupt() {
std::lock_guard<std::mutex> lg(m);
interrupted = true;
cv.notify_one();
}

private:
bool interrupted;
std::mutex m;
std::condition_variable cv;
};
}
Loading

0 comments on commit 3894d0c

Please sign in to comment.