datactl/syclock.h

datactl/syclock.h

datactl/syclock.h

Namespaces

Name
Syntalos

Classes

Name
structSyntalos::symaster_clock
Syntalos Master Clock.
classSyntalos::SyncTimer

Defines

Name
TIMER_FUNC_TIMESTAMP(T, F)
MTIMER_FUNC_TIMESTAMP(F)
FUNC_EXEC_TIMESTAMP(INIT_TIME, F)
FUNC_DONE_TIMESTAMP(INIT_TIME, F)

Macros Documentation

define TIMER_FUNC_TIMESTAMP

#define TIMER_FUNC_TIMESTAMP(
    T,
    F
)
    ({                                                                                 \
        const auto __stime = T->timeSinceStartNsec();                                  \
        F;                                                                             \
        std::chrono::round<microseconds_t>((__stime + T->timeSinceStartNsec()) / 2.0); \
    })

Compute a timestamp for “when this function acquired a value”. This is assumed to be the mean between function start and end time, rounded to milliseconds. For example, if the function F acquires a timestamp’ed value, this macro should return the equivalent timestamp on our timer T. This should balance out context switches if they are not too bad, and produce a reasonably accurate result in milliseconds. It is superior to measuring our timestamp for alignment after the other timestamping function was run.

The resulting timestamp is in µs

define MTIMER_FUNC_TIMESTAMP

#define MTIMER_FUNC_TIMESTAMP(
    F
)
(TIMER_FUNC_TIMESTAMP(m_syTimer, F))

define FUNC_EXEC_TIMESTAMP

#define FUNC_EXEC_TIMESTAMP(
    INIT_TIME,
    F
)
    ({                                                                                                         \
        const auto __stime = std::chrono::duration_cast<nanoseconds_t>(symaster_clock::now() - (INIT_TIME));   \
        F;                                                                                                     \
        std::chrono::round<microseconds_t>(                                                                    \
            (__stime + std::chrono::duration_cast<nanoseconds_t>(symaster_clock::now() - (INIT_TIME))) / 2.0); \
    })

Compute a timestamp for “when this function acquired a value”. This function is equivalent to TIMER_FUNC_TIMESTAMP(), but takes a starting timepoint instead of a timer as first parameter.

The resulting timestamp is in µs

define FUNC_DONE_TIMESTAMP

#define FUNC_DONE_TIMESTAMP(
    INIT_TIME,
    F
)
    ({                                                                                   \
        F;                                                                               \
        std::chrono::duration_cast<microseconds_t>(symaster_clock::now() - (INIT_TIME)); \
    })

Compute a timestamp for “when this function completed”. This macro does not return the average between starting and end-time of the function invocation, but rather just the time when it was completed.

The resulting timestamp is in µs

Source code

/*
 * Copyright (C) 2016-2024 Matthias Klumpp <matthias@tenstral.net>
 *
 * Licensed under the GNU Lesser General Public License Version 3
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the license, or
 * (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this software.  If not, see <http://www.gnu.org/licenses/>.
 */

#pragma once

#include <QLoggingCategory>
#include <QMetaType>
#include <atomic>
#include <chrono>
#include <memory>
#include <ratio>

Q_DECLARE_METATYPE(std::chrono::milliseconds);
Q_DECLARE_METATYPE(std::chrono::microseconds);
Q_DECLARE_METATYPE(std::chrono::nanoseconds);

namespace Syntalos
{

Q_DECLARE_LOGGING_CATEGORY(logTimeClock)


struct symaster_clock {
    typedef std::chrono::nanoseconds duration;
    typedef duration::rep rep;
    typedef duration::period period;
    typedef std::chrono::time_point<symaster_clock, duration> time_point;

    static constexpr bool is_steady = true;

    static time_point now() noexcept;
};

using symaster_timepoint = std::chrono::time_point<symaster_clock>;

using milliseconds_t = std::chrono::milliseconds;

using microseconds_t = std::chrono::duration<int64_t, std::micro>;

using nanoseconds_t = std::chrono::duration<int64_t, std::nano>;

inline milliseconds_t usecToMsec(const microseconds_t &usec)
{
    return std::chrono::duration_cast<milliseconds_t>(usec);
}

inline microseconds_t msecToUsec(const milliseconds_t &msec)
{
    return std::chrono::duration_cast<microseconds_t>(msec);
}

inline microseconds_t nsecToUsec(const nanoseconds_t &msec)
{
    return std::chrono::duration_cast<microseconds_t>(msec);
}

inline milliseconds_t timeDiffMsec(const symaster_timepoint &timePoint1, const symaster_timepoint &timePoint2) noexcept
{
    return std::chrono::duration_cast<milliseconds_t>(timePoint1 - timePoint2);
}

inline microseconds_t timeDiffUsec(const symaster_timepoint &timePoint1, const symaster_timepoint &timePoint2) noexcept
{
    return std::chrono::duration_cast<microseconds_t>(timePoint1 - timePoint2);
}

inline milliseconds_t timeDiffToNowMsec(const std::chrono::time_point<symaster_clock> &timePoint) noexcept
{
    return std::chrono::duration_cast<milliseconds_t>(symaster_clock::now() - timePoint);
}

inline symaster_timepoint currentTimePoint() noexcept
{
    return symaster_clock::now();
}

class SyncTimer
{
public:
    explicit SyncTimer();

    void start() noexcept;
    void startAt(const symaster_timepoint &startTimePoint) noexcept;

    inline milliseconds_t timeSinceStartMsec() noexcept
    {
        return std::chrono::duration_cast<milliseconds_t>(symaster_clock::now() - m_startTime);
    }

    inline microseconds_t timeSinceStartUsec() noexcept
    {
        return std::chrono::duration_cast<microseconds_t>(symaster_clock::now() - m_startTime);
    }

    inline nanoseconds_t timeSinceStartNsec() noexcept
    {
        return std::chrono::duration_cast<nanoseconds_t>(symaster_clock::now() - m_startTime);
    }

    inline symaster_timepoint currentTimePoint() noexcept
    {
        return symaster_clock::now();
    }

    symaster_timepoint startTime() noexcept
    {
        return m_startTime;
    }

private:
    symaster_timepoint m_startTime;
    bool m_started;
};

#define TIMER_FUNC_TIMESTAMP(T, F)                                                     \
    ({                                                                                 \
        const auto __stime = T->timeSinceStartNsec();                                  \
        F;                                                                             \
        std::chrono::round<microseconds_t>((__stime + T->timeSinceStartNsec()) / 2.0); \
    })
#define MTIMER_FUNC_TIMESTAMP(F) (TIMER_FUNC_TIMESTAMP(m_syTimer, F))

#define FUNC_EXEC_TIMESTAMP(INIT_TIME, F)                                                                      \
    ({                                                                                                         \
        const auto __stime = std::chrono::duration_cast<nanoseconds_t>(symaster_clock::now() - (INIT_TIME));   \
        F;                                                                                                     \
        std::chrono::round<microseconds_t>(                                                                    \
            (__stime + std::chrono::duration_cast<nanoseconds_t>(symaster_clock::now() - (INIT_TIME))) / 2.0); \
    })

#define FUNC_DONE_TIMESTAMP(INIT_TIME, F)                                                \
    ({                                                                                   \
        F;                                                                               \
        std::chrono::duration_cast<microseconds_t>(symaster_clock::now() - (INIT_TIME)); \
    })

} // namespace Syntalos

Updated on 2024-09-05 at 17:39:59 +0000