PrevUpHomeNext

Chapter 1. Motivating Examples

Version checking
Public Holiday Schedules
Concepts and properties of a schedule
Building the schedule
Complete schedule

A simple example of using synkronize's timepoint generator is performing a version check every now and then according to user preferences.

This example checks every month, week or day for a new version of some fact of your choice.

The actual version check and handling of preferences is irrelevant; the main focus is on the simplicity of using the timepoint generator, whose resulting timepoints are fed into a threadpool timer.

Code Outline

namespace fd {
// fwd decl timepoint generator
class schedule_timepiece;
}


// window of some description
class MyTrayWindow :
    public ATL::CWindowImpl<MyTrayWindow, ATL::CWindow, ATL::CWinTraits<WS_OVERLAPPED>>
{
private:
    // this method gets called initially or on changing settings/preferences
    void SetupVersionCheck();
    void ScheduleNextVersionCheck();

private:
    // version checker of some description
    fd_version_checker vchecker_;

    // the timepoint generator
    std::unique_ptr<fd::schedule_timepiece> vscheduler_;
    // threadpool timer of some description
    threadpool_periodic_timer vtimer_;
};
#include <fd/interval_schedule_data.h>
#include <fd/schedule_timepiece.h>
using namespace fd;

void MyTrayWindow::SetupVersionCheck()
{
    // grab read-only program settings/preferences
    const auto prefs = globalRoSettings->SharedData();

    if (prefs->vcheckInterval == MySettingsStore::VCheckOff)
    {
        vtimer_.cancel();
        vscheduler_ = nullptr;
        return;
    }


    // prepare schedule definition
    interval_schedule_data sd
    {
        prefs->vcheckInterval == MySettingsStore::VCheckMonthly ? month_interval :
        prefs->vcheckInterval == MySettingsStore::VCheckWeekly ? week_interval :
        day_interval
    };
    // create and initialize timepoint generator from schedule definition
    vscheduler_ = std::make_unique<schedule_timepiece>
    (
        sd,
        // first version check should trigger immediately (rewind),
        // changing settings should trigger now or next (adjacent)
        vscheduler_ ? timepiece_move::to_adjacent : timepiece_move::rewind
    );

    // extract generated timepoint as unix timestamp
    std::chrono::seconds next = currently_scheduled_at__s(*vscheduler_);

    // feed timepoint to threadpool timer
    vtimer_.restart(next, winapi_milliseconds::zero(), [this]()
    {
        // might get called any time, retrieve window handle once and check
        if (ATL::CWindow wnd = m_hWnd)
            // message handler method will call MyTrayWindow::ScheduleNextVersionCheck()
            wnd.PostMessage(CheckVersion);
    });
}

void MyTrayWindow::ScheduleNextVersionCheck()
{
    auto checkResult = vchecker_.check_result();
    // not up-to-date -> no need to check anymore
    if (checkResult->checkState == fd_version_check_state::already_checked && !checkResult->isUpToDate)
        return;


    // advance to next timepoint and extract generated timepoint as unix timestamp
    std::chrono::seconds next = advance__s(*vscheduler_, timepiece_move::to_adjacent);

    // feed timepoint to threadpool timer
    vtimer_.restart(next, winapi_milliseconds::zero(), [this]()
    {
        // might get called any time, retrieve window handle once and check
        if (ATL::CWindow wnd = m_hWnd)
            // message handler method will call MyTrayWindow::ScheduleNextVersionCheck()
            wnd.PostMessage(CheckVersion);
    });
}

PrevUpHomeNext