#include <functional>
#include <iostream>
#include <chrono>
#include <thread>
#include <atomic>
#include <mutex>

std::mutex mutex;
std::atomic<bool> stop = {false};
unsigned last_result = 0; // Whatever thread_1ms produces.

void thread_1ms_action() {
    // Do the work.

    // Update the last result.
    {
        std::unique_lock<std::mutex> lock(mutex);
        ++last_result;
    }
}

void thread_1333us_action() {
    // Copy thread_1ms result.
    unsigned last_result_copy;
    {
        std::unique_lock<std::mutex> lock(mutex);
        last_result_copy = last_result;
    }

    // Do the work.
    std::cout << last_result_copy << '\n';
}

void periodic_action_thread(std::chrono::microseconds period, std::function<void()> const& action) {
    auto const start = std::chrono::steady_clock::now();
    while(!stop.load(std::memory_order_relaxed)) {
        // Do the work.
        action();

        // Wait till the next period start.
        auto now = std::chrono::steady_clock::now();
        auto iterations = (now - start) / period;
        auto next_start = start + (iterations + 1) * period;
        std::this_thread::sleep_until(next_start);
    }
}

int main() {
    std::thread a(periodic_action_thread, std::chrono::milliseconds(1), thread_1ms_action);
    std::thread b(periodic_action_thread, std::chrono::microseconds(13333), thread_1333us_action);

    std::this_thread::sleep_for(std::chrono::seconds(1));
    stop = true;
    a.join();
    b.join();
}
