/*
 * Copyright (c) 2000-2005 The Regents of The University of Michigan
 * Copyright (c) 2013 Advanced Micro Devices, Inc.
 * Copyright (c) 2013 Mark D. Hill and David A. Wood
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/* @file
 * EventQueue interfaces
 */

#ifndef __SIM_EVENTQ_HH__
#define __SIM_EVENTQ_HH__

#include <algorithm>
#include <cassert>
#include <climits>
#include <functional>
#include <iosfwd>
#include <memory>
#include <mutex>
#include <string>

#include "base/debug.hh"
#include "base/flags.hh"
#include "base/types.hh"
#include "debug/Event.hh"
#include "sim/serialize.hh"

class EventQueue;       // forward declaration
class BaseGlobalEvent;

//! Simulation Quantum for multiple eventq simulation.
//! The quantum value is the period length after which the queues
//! synchronize themselves with each other. This means that any
//! event to scheduled on Queue A which is generated by an event on
//! Queue B should be at least simQuantum ticks away in future.
extern Tick simQuantum;

//! Current number of allocated main event queues.
extern uint32_t numMainEventQueues;

//! Array for main event queues.
extern std::vector<EventQueue *> mainEventQueue;

//! The current event queue for the running thread. Access to this queue
//! does not require any locking from the thread.

extern __thread EventQueue *_curEventQueue;

//! Current mode of execution: parallel / serial
extern bool inParallelMode;

//! Function for returning eventq queue for the provided
//! index. The function allocates a new queue in case one
//! does not exist for the index, provided that the index
//! is with in bounds.
EventQueue *getEventQueue(uint32_t index);

inline EventQueue *curEventQueue() { return _curEventQueue; }
inline void curEventQueue(EventQueue *q) { _curEventQueue = q; }

/**
 * Common base class for Event and GlobalEvent, so they can share flag
 * and priority definitions and accessor functions.  This class should
 * not be used directly.
 */
class EventBase
{
  protected:
    typedef unsigned short FlagsType;
    typedef ::Flags<FlagsType> Flags;

    static const FlagsType PublicRead    = 0x003f; // public readable flags
    static const FlagsType PublicWrite   = 0x001d; // public writable flags
    static const FlagsType Squashed      = 0x0001; // has been squashed
    static const FlagsType Scheduled     = 0x0002; // has been scheduled
    static const FlagsType Managed       = 0x0004; // Use life cycle manager
    static const FlagsType AutoDelete    = Managed; // delete after dispatch
    /**
     * This used to be AutoSerialize. This value can't be reused
     * without changing the checkpoint version since the flag field
     * gets serialized.
     */
    static const FlagsType Reserved0     = 0x0008;
    static const FlagsType IsExitEvent   = 0x0010; // special exit event
    static const FlagsType IsMainQueue   = 0x0020; // on main event queue
    static const FlagsType Initialized   = 0x7a40; // somewhat random bits
    static const FlagsType InitMask      = 0xffc0; // mask for init bits

  public:
    /**
     * @ingroup api_eventq
     */
    typedef int8_t Priority;

    /// Event priorities, to provide tie-breakers for events scheduled
    /// at the same cycle.  Most events are scheduled at the default
    /// priority; these values are used to control events that need to
    /// be ordered within a cycle.

    /**
     * Minimum priority
     *
     * @ingroup api_eventq
     */
    static const Priority Minimum_Pri =          SCHAR_MIN;

    /**
     * If we enable tracing on a particular cycle, do that as the
     * very first thing so we don't miss any of the events on
     * that cycle (even if we enter the debugger).
     *
     * @ingroup api_eventq
     */
    static const Priority Debug_Enable_Pri =          -101;

    /**
     * Breakpoints should happen before anything else (except
     * enabling trace output), so we don't miss any action when
     * debugging.
     *
     * @ingroup api_eventq
     */
    static const Priority Debug_Break_Pri =           -100;

    /**
     * CPU switches schedule the new CPU's tick event for the
     * same cycle (after unscheduling the old CPU's tick event).
     * The switch needs to come before any tick events to make
     * sure we don't tick both CPUs in the same cycle.
     *
     * @ingroup api_eventq
     */
    static const Priority CPU_Switch_Pri =             -31;

    /**
     * For some reason "delayed" inter-cluster writebacks are
     * scheduled before regular writebacks (which have default
     * priority).  Steve?
     *
     * @ingroup api_eventq
     */
    static const Priority Delayed_Writeback_Pri =       -1;

    /**
     * Default is zero for historical reasons.
     *
     * @ingroup api_eventq
     */
    static const Priority Default_Pri =                  0;

    /**
     * DVFS update event leads to stats dump therefore given a lower priority
     * to ensure all relevant states have been updated
     *
     * @ingroup api_eventq
     */
    static const Priority DVFS_Update_Pri =             31;

    /**
     * Serailization needs to occur before tick events also, so
     * that a serialize/unserialize is identical to an on-line
     * CPU switch.
     *
     * @ingroup api_eventq
     */
    static const Priority Serialize_Pri =               32;

    /**
     * CPU ticks must come after other associated CPU events
     * (such as writebacks).
     *
     * @ingroup api_eventq
     */
    static const Priority CPU_Tick_Pri =                50;

    /**
     * If we want to exit a thread in a CPU, it comes after CPU_Tick_Pri
     *
     * @ingroup api_eventq
     */
    static const Priority CPU_Exit_Pri =                64;

    /**
     * Statistics events (dump, reset, etc.) come after
     * everything else, but before exit.
     *
     * @ingroup api_eventq
     */
    static const Priority Stat_Event_Pri =              90;

    /**
     * Progress events come at the end.
     *
     * @ingroup api_eventq
     */
    static const Priority Progress_Event_Pri =          95;

    /**
     * If we want to exit on this cycle, it's the very last thing
     * we do.
     *
     * @ingroup api_eventq
     */
    static const Priority Sim_Exit_Pri =               100;

    /**
     * Maximum priority
     *
     * @ingroup api_eventq
     */
    static const Priority Maximum_Pri =          SCHAR_MAX;
};

/*
 * An item on an event queue.  The action caused by a given
 * event is specified by deriving a subclass and overriding the
 * process() member function.
 *
 * Caution, the order of members is chosen to maximize data packing.
 */
class Event : public EventBase, public Serializable
{
    friend class EventQueue;

  private:
    // The event queue is now a linked list of linked lists.  The
    // 'nextBin' pointer is to find the bin, where a bin is defined as
    // when+priority.  All events in the same bin will be stored in a
    // second linked list (a stack) maintained by the 'nextInBin'
    // pointer.  The list will be accessed in LIFO order.  The end
    // result is that the insert/removal in 'nextBin' is
    // linear/constant, and the lookup/removal in 'nextInBin' is
    // constant/constant.  Hopefully this is a significant improvement
    // over the current fully linear insertion.
    Event *nextBin;
    Event *nextInBin;

    static Event *insertBefore(Event *event, Event *curr);
    static Event *removeItem(Event *event, Event *last);

    Tick _when;         //!< timestamp when event should be processed
    Priority _priority; //!< event priority
    Flags flags;

#ifndef NDEBUG
    /// Global counter to generate unique IDs for Event instances
    static Counter instanceCounter;

    /// This event's unique ID.  We can also use pointer values for
    /// this but they're not consistent across runs making debugging
    /// more difficult.  Thus we use a global counter value when
    /// debugging.
    Counter instance;

    /// queue to which this event belongs (though it may or may not be
    /// scheduled on this queue yet)
    EventQueue *queue;
#endif

#ifdef EVENTQ_DEBUG
    Tick whenCreated;   //!< time created
    Tick whenScheduled; //!< time scheduled
#endif

    void
    setWhen(Tick when, EventQueue *q)
    {
        _when = when;
#ifndef NDEBUG
        queue = q;
#endif
#ifdef EVENTQ_DEBUG
        whenScheduled = curTick();
#endif
    }

    bool
    initialized() const
    {
        return (flags & InitMask) == Initialized;
    }

  protected:
    Flags
    getFlags() const
    {
        return flags & PublicRead;
    }

    bool
    isFlagSet(Flags _flags) const
    {
        assert(_flags.noneSet(~PublicRead));
        return flags.isSet(_flags);
    }

    void
    setFlags(Flags _flags)
    {
        assert(_flags.noneSet(~PublicWrite));
        flags.set(_flags);
    }

    void
    clearFlags(Flags _flags)
    {
        assert(_flags.noneSet(~PublicWrite));
        flags.clear(_flags);
    }

    void
    clearFlags()
    {
        flags.clear(PublicWrite);
    }

    /**
     * This function isn't really useful if TRACING_ON is not defined
     *
     * @ingroup api_eventq
     */
    virtual void trace(const char *action);     //!< trace event activity

    /// Return the instance number as a string.
    const std::string instanceString() const;

  protected: /* Memory management */
    /**
     * @{
     * Memory management hooks for events that have the Managed flag set
     *
     * Events can use automatic memory management by setting the
     * Managed flag. The default implementation automatically deletes
     * events once they have been removed from the event queue. This
     * typically happens when events are descheduled or have been
     * triggered and not rescheduled.
     *
     * The methods below may be overridden by events that need custom
     * memory management. For example, events exported to Python need
     * to impement reference counting to ensure that the Python
     * implementation of the event is kept alive while it lives in the
     * event queue.
     *
     * @note Memory managers are responsible for implementing
     * reference counting (by overriding both acquireImpl() and
     * releaseImpl()) or checking if an event is no longer scheduled
     * in releaseImpl() before deallocating it.
     */

    /**
     * Managed event scheduled and being held in the event queue.
     */
    void acquire()
    {
        if (flags.isSet(Event::Managed))
            acquireImpl();
    }

    /**
     * Managed event removed from the event queue.
     */
    void release() {
        if (flags.isSet(Event::Managed))
            releaseImpl();
    }

    virtual void acquireImpl() {}

    virtual void releaseImpl() {
        if (!scheduled())
            delete this;
    }

    /** @} */

  public:

    /*
     * Event constructor
     * @param queue that the event gets scheduled on
     *
     * @ingroup api_eventq
     */
    Event(Priority p = Default_Pri, Flags f = 0)
        : nextBin(nullptr), nextInBin(nullptr), _when(0), _priority(p),
          flags(Initialized | f)
    {
        assert(f.noneSet(~PublicWrite));
#ifndef NDEBUG
        instance = ++instanceCounter;
        queue = NULL;
#endif
#ifdef EVENTQ_DEBUG
        whenCreated = curTick();
        whenScheduled = 0;
#endif
    }

    /**
     * @ingroup api_eventq
     * @{
     */
    virtual ~Event();
    virtual const std::string name() const;

    /// Return a C string describing the event.  This string should
    /// *not* be dynamically allocated; just a const char array
    /// describing the event class.
    virtual const char *description() const;

    /// Dump the current event data
    void dump() const;
    /** @}*/ //end of api group

  public:
    /*
     * This member function is invoked when the event is processed
     * (occurs).  There is no default implementation; each subclass
     * must provide its own implementation.  The event is not
     * automatically deleted after it is processed (to allow for
     * statically allocated event objects).
     *
     * If the AutoDestroy flag is set, the object is deleted once it
     * is processed.
     *
     * @ingroup api_eventq
     */
    virtual void process() = 0;

    /**
     * Determine if the current event is scheduled
     *
     * @ingroup api_eventq
     */
    bool scheduled() const { return flags.isSet(Scheduled); }

    /**
     * Squash the current event
     *
     * @ingroup api_eventq
     */
    void squash() { flags.set(Squashed); }

    /**
     * Check whether the event is squashed
     *
     * @ingroup api_eventq
     */
    bool squashed() const { return flags.isSet(Squashed); }

    /**
     * See if this is a SimExitEvent (without resorting to RTTI)
     *
     * @ingroup api_eventq
     */
    bool isExitEvent() const { return flags.isSet(IsExitEvent); }

    /**
     * Check whether this event will auto-delete
     *
     * @ingroup api_eventq
     */
    bool isManaged() const { return flags.isSet(Managed); }

    /**
     * The function returns true if the object is automatically
     * deleted after the event is processed.
     *
     * @ingroup api_eventq
     */
    bool isAutoDelete() const { return isManaged(); }

    /**
     * Get the time that the event is scheduled
     *
     * @ingroup api_eventq
     */
    Tick when() const { return _when; }

    /**
     * Get the event priority
     *
     * @ingroup api_eventq
     */
    Priority priority() const { return _priority; }

    //! If this is part of a GlobalEvent, return the pointer to the
    //! Global Event.  By default, there is no GlobalEvent, so return
    //! NULL.  (Overridden in GlobalEvent::BarrierEvent.)
    virtual BaseGlobalEvent *globalEvent() { return NULL; }

    void serialize(CheckpointOut &cp) const override;
    void unserialize(CheckpointIn &cp) override;
};

/**
 * @ingroup api_eventq
 */
inline bool
operator<(const Event &l, const Event &r)
{
    return l.when() < r.when() ||
        (l.when() == r.when() && l.priority() < r.priority());
}

/**
 * @ingroup api_eventq
 */
inline bool
operator>(const Event &l, const Event &r)
{
    return l.when() > r.when() ||
        (l.when() == r.when() && l.priority() > r.priority());
}

/**
 * @ingroup api_eventq
 */
inline bool
operator<=(const Event &l, const Event &r)
{
    return l.when() < r.when() ||
        (l.when() == r.when() && l.priority() <= r.priority());
}

/**
 * @ingroup api_eventq
 */
inline bool
operator>=(const Event &l, const Event &r)
{
    return l.when() > r.when() ||
        (l.when() == r.when() && l.priority() >= r.priority());
}

/**
 * @ingroup api_eventq
 */
inline bool
operator==(const Event &l, const Event &r)
{
    return l.when() == r.when() && l.priority() == r.priority();
}

/**
 * @ingroup api_eventq
 */
inline bool
operator!=(const Event &l, const Event &r)
{
    return l.when() != r.when() || l.priority() != r.priority();
}

/**
 * Queue of events sorted in time order
 *
 * Events are scheduled (inserted into the event queue) using the
 * schedule() method. This method either inserts a <i>synchronous</i>
 * or <i>asynchronous</i> event.
 *
 * Synchronous events are scheduled using schedule() method with the
 * argument 'global' set to false (default). This should only be done
 * from a thread holding the event queue lock
 * (EventQueue::service_mutex). The lock is always held when an event
 * handler is called, it can therefore always insert events into its
 * own event queue unless it voluntarily releases the lock.
 *
 * Events can be scheduled across thread (and event queue borders) by
 * either scheduling asynchronous events or taking the target event
 * queue's lock. However, the lock should <i>never</i> be taken
 * directly since this is likely to cause deadlocks. Instead, code
 * that needs to schedule events in other event queues should
 * temporarily release its own queue and lock the new queue. This
 * prevents deadlocks since a single thread never owns more than one
 * event queue lock. This functionality is provided by the
 * ScopedMigration helper class. Note that temporarily migrating
 * between event queues can make the simulation non-deterministic, it
 * should therefore be limited to cases where that can be tolerated
 * (e.g., handling asynchronous IO or fast-forwarding in KVM).
 *
 * Asynchronous events can also be scheduled using the normal
 * schedule() method with the 'global' parameter set to true. Unlike
 * the previous queue migration strategy, this strategy is fully
 * deterministic. This causes the event to be inserted in a separate
 * queue of asynchronous events (async_queue), which is merged main
 * event queue at the end of each simulation quantum (by calling the
 * handleAsyncInsertions() method). Note that this implies that such
 * events must happen at least one simulation quantum into the future,
 * otherwise they risk being scheduled in the past by
 * handleAsyncInsertions().
 */
class EventQueue
{
  private:
    std::string objName;
    Event *head;
    Tick _curTick;

    //! Mutex to protect async queue.
    std::mutex async_queue_mutex;

    //! List of events added by other threads to this event queue.
    std::list<Event*> async_queue;

    /**
     * Lock protecting event handling.
     *
     * This lock is always taken when servicing events. It is assumed
     * that the thread scheduling new events (not asynchronous events
     * though) have taken this lock. This is normally done by
     * serviceOne() since new events are typically scheduled as a
     * response to an earlier event.
     *
     * This lock is intended to be used to temporarily steal an event
     * queue to support inter-thread communication when some
     * deterministic timing can be sacrificed for speed. For example,
     * the KVM CPU can use this support to access devices running in a
     * different thread.
     *
     * @see EventQueue::ScopedMigration.
     * @see EventQueue::ScopedRelease
     * @see EventQueue::lock()
     * @see EventQueue::unlock()
     */
    std::mutex service_mutex;

    //! Insert / remove event from the queue. Should only be called
    //! by thread operating this queue.
    void insert(Event *event);
    void remove(Event *event);

    //! Function for adding events to the async queue. The added events
    //! are added to main event queue later. Threads, other than the
    //! owning thread, should call this function instead of insert().
    void asyncInsert(Event *event);

    EventQueue(const EventQueue &);

  public:
    class ScopedMigration
    {
      public:
         /**
         * Temporarily migrate execution to a different event queue.
         *
         * An instance of this class temporarily migrates execution to
         * different event queue by releasing the current queue, locking
         * the new queue, and updating curEventQueue(). This can, for
         * example, be useful when performing IO across thread event
         * queues when timing is not crucial (e.g., during fast
         * forwarding).
         *
         * ScopedMigration does nothing if both eqs are the same
         *
         * @ingroup api_eventq
         */
        ScopedMigration(EventQueue *_new_eq, bool _doMigrate = true)
            :new_eq(*_new_eq), old_eq(*curEventQueue()),
             doMigrate((&new_eq != &old_eq)&&_doMigrate)
        {
            if (doMigrate){
                old_eq.unlock();
                new_eq.lock();
                curEventQueue(&new_eq);
            }
        }

        ~ScopedMigration()
        {
            if (doMigrate){
                new_eq.unlock();
                old_eq.lock();
                curEventQueue(&old_eq);
            }
        }

      private:
        EventQueue &new_eq;
        EventQueue &old_eq;
        bool doMigrate;
    };


    class ScopedRelease
    {
      public:
        /**
         * Temporarily release the event queue service lock.
         *
         * There are cases where it is desirable to temporarily release
         * the event queue lock to prevent deadlocks. For example, when
         * waiting on the global barrier, we need to release the lock to
         * prevent deadlocks from happening when another thread tries to
         * temporarily take over the event queue waiting on the barrier.
         *
         * @group api_eventq
         */
        ScopedRelease(EventQueue *_eq)
            :  eq(*_eq)
        {
            eq.unlock();
        }

        ~ScopedRelease()
        {
            eq.lock();
        }

      private:
        EventQueue &eq;
    };

    /**
     * @ingroup api_eventq
     */
    EventQueue(const std::string &n);

    /**
     * @ingroup api_eventq
     * @{
     */
    virtual const std::string name() const { return objName; }
    void name(const std::string &st) { objName = st; }
    /** @}*/ //end of api_eventq group

    /**
     * Schedule the given event on this queue. Safe to call from any thread.
     *
     * @ingroup api_eventq
     */
    void
    schedule(Event *event, Tick when, bool global=false)
    {
        assert(when >= getCurTick());
        assert(!event->scheduled());
        assert(event->initialized());

        event->setWhen(when, this);

        // The check below is to make sure of two things
        // a. A thread schedules local events on other queues through the
        //    asyncq.
        // b. A thread schedules global events on the asyncq, whether or not
        //    this event belongs to this eventq. This is required to maintain
        //    a total order amongst the global events. See global_event.{cc,hh}
        //    for more explanation.
        if (inParallelMode && (this != curEventQueue() || global)) {
            asyncInsert(event);
        } else {
            insert(event);
        }
        event->flags.set(Event::Scheduled);
        event->acquire();

        if (DTRACE(Event))
            event->trace("scheduled");
    }

    /**
     * Deschedule the specified event. Should be called only from the owning
     * thread.
     * @ingroup api_eventq
     */
    void
    deschedule(Event *event)
    {
        assert(event->scheduled());
        assert(event->initialized());
        assert(!inParallelMode || this == curEventQueue());

        remove(event);

        event->flags.clear(Event::Squashed);
        event->flags.clear(Event::Scheduled);

        if (DTRACE(Event))
            event->trace("descheduled");

        event->release();
    }

    /**
     * Reschedule the specified event. Should be called only from the owning
     * thread.
     *
     * @ingroup api_eventq
     */
    void
    reschedule(Event *event, Tick when, bool always=false)
    {
        assert(when >= getCurTick());
        assert(always || event->scheduled());
        assert(event->initialized());
        assert(!inParallelMode || this == curEventQueue());

        if (event->scheduled()) {
            remove(event);
        } else {
            event->acquire();
        }

        event->setWhen(when, this);
        insert(event);
        event->flags.clear(Event::Squashed);
        event->flags.set(Event::Scheduled);

        if (DTRACE(Event))
            event->trace("rescheduled");
    }

    Tick nextTick() const { return head->when(); }
    void setCurTick(Tick newVal) { _curTick = newVal; }

    /**
     * While curTick() is useful for any object assigned to this event queue,
     * if an object that is assigned to another event queue (or a non-event
     * object) need to access the current tick of this event queue, this
     * function is used.
     *
     * Tick is the unit of time used in gem5.
     *
     * @return Tick The current tick of this event queue.
     * @ingroup api_eventq
     */
    Tick getCurTick() const { return _curTick; }
    Event *getHead() const { return head; }

    Event *serviceOne();

    /**
     * process all events up to the given timestamp.  we inline a quick test
     * to see if there are any events to process; if so, call the internal
     * out-of-line version to process them all.
     *
     * Notes:
     *  - This is only used for "instruction" event queues. Instead of counting
     *    ticks, this is actually counting instructions.
     *  - This updates the current tick value to the value of the entry at the
     *    head of the queue.
     *
     * @ingroup api_eventq
     */
    void
    serviceEvents(Tick when)
    {
        while (!empty()) {
            if (nextTick() > when)
                break;

            /**
             * @todo this assert is a good bug catcher.  I need to
             * make it true again.
             */
            //assert(head->when() >= when && "event scheduled in the past");
            serviceOne();
        }

        setCurTick(when);
    }

    /**
     * Returns true if no events are queued
     *
     * @ingroup api_eventq
     */
    bool empty() const { return head == NULL; }

    /**
     * This is a debugging function which will print everything on the event
     * queue.
     *
     * @ingroup api_eventq
     */
    void dump() const;

    bool debugVerify() const;

    /**
     * Function for moving events from the async_queue to the main queue.
     */
    void handleAsyncInsertions();

    /**
     *  Function to signal that the event loop should be woken up because
     *  an event has been scheduled by an agent outside the gem5 event
     *  loop(s) whose event insertion may not have been noticed by gem5.
     *  This function isn't needed by the usual gem5 event loop but may
     *  be necessary in derived EventQueues which host gem5 onto other
     *  schedulers.
     *
     *  @param when Time of a delayed wakeup (if known). This parameter
     *  can be used by an implementation to schedule a wakeup in the
     *  future if it is sure it will remain active until then.
     *  Or it can be ignored and the event queue can be woken up now.
     *
     *  @ingroup api_eventq
     */
    virtual void wakeup(Tick when = (Tick)-1) { }

    /**
     *  function for replacing the head of the event queue, so that a
     *  different set of events can run without disturbing events that have
     *  already been scheduled. Already scheduled events can be processed
     *  by replacing the original head back.
     *  USING THIS FUNCTION CAN BE DANGEROUS TO THE HEALTH OF THE SIMULATOR.
     *  NOT RECOMMENDED FOR USE.
     */
    Event* replaceHead(Event* s);

    /**@{*/
    /**
     * Provide an interface for locking/unlocking the event queue.
     *
     * @warn Do NOT use these methods directly unless you really know
     * what you are doing. Incorrect use can easily lead to simulator
     * deadlocks.
     *
     * @see EventQueue::ScopedMigration.
     * @see EventQueue::ScopedRelease
     * @see EventQueue
     */
    void lock() { service_mutex.lock(); }
    void unlock() { service_mutex.unlock(); }
    /**@}*/

    /**
     * Reschedule an event after a checkpoint.
     *
     * Since events don't know which event queue they belong to,
     * parent objects need to reschedule events themselves. This
     * method conditionally schedules an event that has the Scheduled
     * flag set. It should be called by parent objects after
     * unserializing an object.
     *
     * @warn Only use this method after unserializing an Event.
     */
    void checkpointReschedule(Event *event);

    virtual ~EventQueue()
    {
        while (!empty())
            deschedule(getHead());
    }
};

void dumpMainQueue();

class EventManager
{
  protected:
    /** A pointer to this object's event queue */
    EventQueue *eventq;

  public:
    /**
     * Event manger manages events in the event queue. Where
     * you can schedule and deschedule different events.
     *
     * @ingroup api_eventq
     * @{
     */
    EventManager(EventManager &em) : eventq(em.eventq) {}
    EventManager(EventManager *em) : eventq(em->eventq) {}
    EventManager(EventQueue *eq) : eventq(eq) {}
    /** @}*/ //end of api_eventq group

    /**
     * @ingroup api_eventq
     */
    EventQueue *
    eventQueue() const
    {
        return eventq;
    }

    /**
     * @ingroup api_eventq
     */
    void
    schedule(Event &event, Tick when)
    {
        eventq->schedule(&event, when);
    }

    /**
     * @ingroup api_eventq
     */
    void
    deschedule(Event &event)
    {
        eventq->deschedule(&event);
    }

    /**
     * @ingroup api_eventq
     */
    void
    reschedule(Event &event, Tick when, bool always = false)
    {
        eventq->reschedule(&event, when, always);
    }

    /**
     * @ingroup api_eventq
     */
    void
    schedule(Event *event, Tick when)
    {
        eventq->schedule(event, when);
    }

    /**
     * @ingroup api_eventq
     */
    void
    deschedule(Event *event)
    {
        eventq->deschedule(event);
    }

    /**
     * @ingroup api_eventq
     */
    void
    reschedule(Event *event, Tick when, bool always = false)
    {
        eventq->reschedule(event, when, always);
    }

    /**
     * This function is not needed by the usual gem5 event loop
     * but may be necessary in derived EventQueues which host gem5
     * on other schedulers.
     * @ingroup api_eventq
     */
    void wakeupEventQueue(Tick when = (Tick)-1)
    {
        eventq->wakeup(when);
    }

    void setCurTick(Tick newVal) { eventq->setCurTick(newVal); }
};

template <class T, void (T::* F)()>
class EventWrapper : public Event
{
  private:
    T *object;

  public:
    EventWrapper(T *obj, bool del = false, Priority p = Default_Pri)
        : Event(p), object(obj)
    {
        if (del)
            setFlags(AutoDelete);
    }

    EventWrapper(T &obj, bool del = false, Priority p = Default_Pri)
        : Event(p), object(&obj)
    {
        if (del)
            setFlags(AutoDelete);
    }

    void process() { (object->*F)(); }

    const std::string
    name() const
    {
        return object->name() + ".wrapped_event";
    }

    const char *description() const { return "EventWrapped"; }
};

class EventFunctionWrapper : public Event
{
  private:
      std::function<void(void)> callback;
      std::string _name;

  public:
    /**
     * This function wraps a function into an event, to be
     * executed later.
     *
     * @ingroup api_eventq
     */
    EventFunctionWrapper(const std::function<void(void)> &callback,
                         const std::string &name,
                         bool del = false,
                         Priority p = Default_Pri)
        : Event(p), callback(callback), _name(name)
    {
        if (del)
            setFlags(AutoDelete);
    }

   /**
    * @ingroup api_eventq
    */
    void process() { callback(); }

    /**
     * @ingroup api_eventq
     */
    const std::string
    name() const
    {
        return _name + ".wrapped_function_event";
    }

    /**
     * @ingroup api_eventq
     */
    const char *description() const { return "EventFunctionWrapped"; }
};

#endif // __SIM_EVENTQ_HH__
