iceoryx_hoofs/posix_wrapper/timer.hpp🔗
Namespaces🔗
| Name | 
|---|
| iox building block to easily create free function for logging in a library context | 
| iox::posix | 
| iox::units::duration_literals | 
Classes🔗
| Name | |
|---|---|
| class | iox::posix::Timer Interface for timers on POSIX operating systems. | 
Source code🔗
// Copyright (c) 2019 by Robert Bosch GmbH. All rights reserved.
// Copyright (c) 2021 by Apex.AI Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// SPDX-License-Identifier: Apache-2.0
#ifndef IOX_HOOFS_POSIX_WRAPPER_TIMER_HPP
#define IOX_HOOFS_POSIX_WRAPPER_TIMER_HPP
#include "iceoryx_hoofs/cxx/optional.hpp"
#include "iceoryx_hoofs/cxx/vector.hpp"
#include "iceoryx_hoofs/design_pattern/creation.hpp"
#include "iceoryx_hoofs/internal/units/duration.hpp"
#include "iceoryx_hoofs/platform/signal.hpp"
#include "iceoryx_hoofs/platform/time.hpp"
#include <atomic>
#include <condition_variable>
#include <cstdint>
#include <ctime>
#include <functional>
#include <limits>
namespace iox
{
namespace posix
{
enum class TimerError
{
    NO_ERROR,
    TIMER_NOT_INITIALIZED,
    NO_VALID_CALLBACK,
    KERNEL_ALLOC_FAILED,
    INVALID_ARGUMENTS,
    ALLOC_MEM_FAILED,
    NO_PERMISSION,
    INVALID_POINTER,
    NO_TIMER_TO_DELETE,
    TIMEOUT_IS_ZERO,
    INTERNAL_LOGIC_ERROR
};
using namespace iox::units::duration_literals;
class Timer
{
  public:
    enum class RunMode
    {
        ONCE,
        PERIODIC
    };
    enum class CatchUpPolicy
    {
        SKIP_TO_NEXT_BEAT,
        IMMEDIATE,
        TERMINATE
    };
  private:
    static constexpr size_t SIZE_OF_COMBINDED_INDEX_AND_DESCRIPTOR = sizeof(uint32_t);
    static constexpr size_t SIZE_OF_SIGVAL_INT = sizeof(int);
    static_assert(SIZE_OF_SIGVAL_INT >= SIZE_OF_COMBINDED_INDEX_AND_DESCRIPTOR, "size of sigval_int is to low");
    static constexpr uint32_t MAX_NUMBER_OF_CALLBACK_HANDLES = 100u;
    static_assert(MAX_NUMBER_OF_CALLBACK_HANDLES <= std::numeric_limits<uint8_t>::max(),
                  "number of callback handles exceeds max index value");
    class OsTimer;
    struct OsTimerCallbackHandle
    {
        static constexpr uint32_t MAX_DESCRIPTOR_VALUE{(1u << 24u) - 1u};
        static sigval indexAndDescriptorToSigval(uint8_t index, uint32_t descriptor) noexcept;
        static uint8_t sigvalToIndex(sigval intVal) noexcept;
        static uint32_t sigvalToDescriptor(sigval intVal) noexcept;
        void incrementDescriptor() noexcept;
        std::mutex m_accessMutex;
        std::atomic<uint32_t> m_descriptor{0u};
        // must be operator= otherwise it is undefined, see https://en.cppreference.com/w/cpp/atomic/ATOMIC_FLAG_INIT
        std::atomic_flag m_callbackIsAboutToBeExecuted = ATOMIC_FLAG_INIT;
        std::atomic<bool> m_inUse{false};
        std::atomic<bool> m_isTimerActive{false};
        std::atomic<uint64_t> m_timerInvocationCounter{0u};
        CatchUpPolicy m_catchUpPolicy{CatchUpPolicy::TERMINATE};
        OsTimer* m_timer{nullptr};
    };
    class OsTimer
    {
#ifdef __QNX__
        static constexpr timer_t INVALID_TIMER_ID = 0;
#else
        static constexpr timer_t INVALID_TIMER_ID = nullptr;
#endif
      public:
        static void callbackHelper(sigval data) noexcept;
        OsTimer(const units::Duration timeToWait, const std::function<void()>& callback) noexcept;
        OsTimer(const OsTimer&) = delete;
        OsTimer(OsTimer&&) = delete;
        OsTimer& operator=(const OsTimer&) = delete;
        OsTimer& operator=(OsTimer&&) = delete;
        virtual ~OsTimer() noexcept;
        cxx::expected<TimerError> start(const RunMode runMode, const CatchUpPolicy catchUpPolicy) noexcept;
        cxx::expected<TimerError> stop() noexcept;
        cxx::expected<TimerError>
        restart(const units::Duration timeToWait, const RunMode runMode, const CatchUpPolicy catchUpPolicy) noexcept;
        // @brief Returns the time until the timer expires the next time
        cxx::expected<units::Duration, TimerError> timeUntilExpiration() noexcept;
        cxx::expected<uint64_t, TimerError> getOverruns() noexcept;
        bool hasError() const noexcept;
        TimerError getError() const noexcept;
      private:
        void executeCallback() noexcept;
      private:
        units::Duration m_timeToWait;
        std::function<void()> m_callback;
        timer_t m_timerId{INVALID_TIMER_ID};
        uint8_t m_callbackHandleIndex{0u};
        bool m_isInitialized{false};
        TimerError m_errorValue{TimerError::NO_ERROR};
        static OsTimerCallbackHandle s_callbackHandlePool[MAX_NUMBER_OF_CALLBACK_HANDLES];
    };
  public:
    Timer(const units::Duration timeToWait) noexcept;
    Timer(const units::Duration timeToWait, const std::function<void()>& callback) noexcept;
    static cxx::expected<units::Duration, TimerError> now() noexcept;
    Timer(const Timer& other) = delete;
    Timer(Timer&& other) = delete;
    Timer& operator=(const Timer& other) = delete;
    Timer& operator=(Timer&& other) = delete;
    virtual ~Timer() noexcept = default;
    cxx::expected<TimerError> start(const RunMode runMode, const CatchUpPolicy catchUpPolicy) noexcept;
    cxx::expected<TimerError> stop() noexcept;
    cxx::expected<TimerError>
    restart(const units::Duration timeToWait, const RunMode runMode, const CatchUpPolicy catchUpPolicy) noexcept;
    // @brief Returns the time until the timer expires the next time
    cxx::expected<units::Duration, TimerError> timeUntilExpiration() noexcept;
    cxx::expected<uint64_t, TimerError> getOverruns() noexcept;
    bool hasError() const noexcept;
    TimerError getError() const noexcept;
  private:
    cxx::optional<OsTimer> m_osTimer;
    static cxx::error<TimerError> createErrorFromErrno(const int32_t errnum) noexcept;
    units::Duration m_timeToWait;
    units::Duration m_creationTime;
    TimerError m_errorValue{TimerError::NO_ERROR};
};
} // namespace posix
} // namespace iox
#endif // IOX_HOOFS_POSIX_WRAPPER_TIMER_HPP
Updated on 31 May 2022 at 11:34:55 CEST