Program Listing for File TimedEvent.h

Program Listing for File TimedEvent.h#

Return to documentation for file (include/Karana/SOADyn/TimedEvent.h)

/*
 * Copyright (c) 2024-2026 Karana Dynamics Pty Ltd. All rights reserved.
 *
 * NOTICE TO USER:
 *
 * This source code and/or documentation (the "Licensed Materials") is
 * the confidential and proprietary information of Karana Dynamics Inc.
 * Use of these Licensed Materials is governed by the terms and conditions
 * of a separate software license agreement between Karana Dynamics and the
 * Licensee ("License Agreement"). Unless expressly permitted under that
 * agreement, any reproduction, modification, distribution, or disclosure
 * of the Licensed Materials, in whole or in part, to any third party
 * without the prior written consent of Karana Dynamics is strictly prohibited.
 *
 * THE LICENSED MATERIALS ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND.
 * KARANA DYNAMICS DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
 * BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, AND
 * FITNESS FOR A PARTICULAR PURPOSE.
 *
 * IN NO EVENT SHALL KARANA DYNAMICS BE LIABLE FOR ANY DAMAGES WHATSOEVER,
 * INCLUDING BUT NOT LIMITED TO LOSS OF PROFITS, DATA, OR USE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES, WHETHER IN CONTRACT, TORT,
 * OR OTHERWISE ARISING OUT OF OR IN CONNECTION WITH THE LICENSED MATERIALS.
 *
 * U.S. Government End Users: The Licensed Materials are a "commercial item"
 * as defined at 48 C.F.R. 2.101, and are provided to the U.S. Government
 * only as a commercial end item under the terms of this license.
 *
 * Any use of the Licensed Materials in individual or commercial software must
 * include, in the user documentation and internal source code comments,
 * this Notice, Disclaimer, and U.S. Government Use Provision.
 */

/**
 * @file
 * @brief Contains the declarations for the TimedEvent class.
 */

#pragma once

#include "Karana/KCore/Base.h"
#include "Karana/Math/Defs.h"
#include <functional>

namespace Karana::Dynamics {
    namespace km = Karana::Math;
    namespace kc = Karana::Core;

    /// TimedEvent function signature
    using f = std::function<void(const km::Ktime &t)>;

    /**
     * @brief This class is used to execute events at a given time. The initial time and function to
     * execute are constructor arguments. The callback function itself can be get/set afterwards as
     * well using the `f` member variable. The `period` and `reschedule_fn` are member variables
     * that are used for recurring callbacks. If the `period` is non-zero, then the `TimedEvent`
     * will be rescheduled using that period. If the period is 0, and the `reschedule_fn` is set,
     * then the result of the `reschedule_fn` will be used to determine the next reschedule time. If
     * the `period` is 0 and the `reschedule_fn` is not set, then the callback will not be
     * rescheduled.
     */
    class TimedEvent : public kc::Base {
        friend class Scheduler;

      public:
        /**
         * @brief TimedEvent constructor. The constructor is not meant to be called directly.
         *        Please use the create(...) method instead to create an instance.
         *
         * @param name The event's name.
         * @param t The time to execute the TimedEvent at.
         * @param fn The function to execute.
         * @param pre_hop This determines whether the timed event runs before or after the hop.
         */
        TimedEvent(std::string_view name, const km::Ktime &t, f fn, bool pre_hop);

        /** Copy constructor. */
        TimedEvent(const TimedEvent &);

        /** Move constructor. */
        TimedEvent(TimedEvent &&) noexcept;

        /**
         * @brief Constructor for TimedEvent.
         * @param name The event's name.
         * @param t The time to execute the TimedEvent at.
         * @param fn The function to execute.
         * @param pre_hop This determines whether the timed event runs before or after the hop.
         * @return the TimedEvent instance
         */
        static kc::ks_ptr<TimedEvent>
        create(std::string_view name, const km::Ktime &t, f fn, bool pre_hop);

        /**
         * @brief Dump the TimedEvent information to a string.
         *
         * @param prefix A string to use as prefix for each output line.
         * @param options Struct with options to tailor the output.
         * @return A string with the dump info for this TimedEvent.
         */
        std::string dumpString(std::string_view prefix = "",
                               const DumpOptions *options = nullptr) const override;

        /**
         * @brief Reschedules the callback if appropriate. This will update the internal time with
         * the new time if it should be rescheduled.
         * @returns true if the `TimedEvent` is rescheduled and false otherwise.
         */
        bool reschedule();

        /// The callback function that runs when this timed event is called
        f fn;

        /**
         * The priority for this callback. This differentiates callbacks that are running at the
         * same time. Lower is a higher priority.
         */
        int priority = 0;

        /**
         * The period to reschedule this callback at. If 0, then the reschedule_fn will be used.
         */
        km::Ktime period{0};

        /**
         * The reschedule_fn is used if and only if the period is 0. If the period is 0 and the
         * reschedule_fn is not defined, then this timed event will not be rescheduled. If the
         * reschedule_fn returns std::nullopt, then this will not be rescheduled.
         */
        std::function<std::optional<km::Ktime>(const km::Ktime &)> reschedule_fn;

        /**
         * @brief Comparison operator. Used mainly to order TimedEvents on a heap.
         *
         * First time is used to compare. If this is the same, then priority is used.
         * If this is also the same, then the id is used.
         *
         * @param other - The TimedEvent to compare this one against.
         * @return comparison status
         */
        bool operator>(const TimedEvent &other) const;

        /**
         * @brief Returns whether the TimedEvent is a pre-hop timed event or not.
         * @return `true` if the TimedEvent is a pre-hop timed event. `false` otherwise.
         */
        bool isPreHop() const;

        /**
         * @brief Get the next time this TimedEvent will execute its event function at.
         *
         * @return The next time this TimedEvent will execute its event function at.
         */
        const km::Ktime &nextEventTime() const;

      private:
        /**
         * @brief Modify the event so its next trigger time is at the
         * trigger location nearest to t.
         *
         * This must be at or after t if this is a before event, and after
         * t if it is an after event.
         *
         * @param t The time to reschedule this event for.
         * @param time_moved_backward true if the time has been moved backward, false otherwise.
         * @return true if the event is rescheduled at or after this time, and false if the event is
         * not rescheduled, i.e., it should be removed.
         */
        bool _rescheduleAt(const km::Ktime &t, bool time_moved_backward);

        /// Determines whether the TimedEvent runs before the hop or not.
        bool _pre_hop;

        /// Time the callback is called.
        km::Ktime _t;
    };
} // namespace Karana::Dynamics