eventq.hh revision 7066
11689SN/A/* 22329SN/A * Copyright (c) 2000-2005 The Regents of The University of Michigan 31689SN/A * All rights reserved. 41689SN/A * 51689SN/A * Redistribution and use in source and binary forms, with or without 61689SN/A * modification, are permitted provided that the following conditions are 71689SN/A * met: redistributions of source code must retain the above copyright 81689SN/A * notice, this list of conditions and the following disclaimer; 91689SN/A * redistributions in binary form must reproduce the above copyright 101689SN/A * notice, this list of conditions and the following disclaimer in the 111689SN/A * documentation and/or other materials provided with the distribution; 121689SN/A * neither the name of the copyright holders nor the names of its 131689SN/A * contributors may be used to endorse or promote products derived from 141689SN/A * this software without specific prior written permission. 151689SN/A * 161689SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 171689SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 181689SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 191689SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 201689SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 211689SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 221689SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 231689SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 241689SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 251689SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 261689SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272665Ssaidi@eecs.umich.edu * 282665Ssaidi@eecs.umich.edu * Authors: Steve Reinhardt 292935Sksewell@umich.edu * Nathan Binkert 301689SN/A */ 311689SN/A 321060SN/A/* @file 331060SN/A * EventQueue interfaces 343773Sgblack@eecs.umich.edu */ 356329Sgblack@eecs.umich.edu 361858SN/A#ifndef __SIM_EVENTQ_HH__ 376658Snate@binkert.org#define __SIM_EVENTQ_HH__ 381717SN/A 395529Snate@binkert.org#include <algorithm> 401060SN/A#include <cassert> 416221Snate@binkert.org#include <climits> 426221Snate@binkert.org#include <iosfwd> 431061SN/A#include <string> 445529Snate@binkert.org 454329Sktlim@umich.edu#include "base/fast_alloc.hh" 464329Sktlim@umich.edu#include "base/flags.hh" 472292SN/A#include "base/misc.hh" 482292SN/A#include "base/trace.hh" 492292SN/A#include "base/types.hh" 502292SN/A#include "sim/serialize.hh" 513788Sgblack@eecs.umich.edu 523798Sgblack@eecs.umich.educlass EventQueue; // forward declaration 535529Snate@binkert.org 542361SN/Aextern EventQueue mainEventQueue; 551060SN/A 562292SN/A/* 572292SN/A * An item on an event queue. The action caused by a given 586221Snate@binkert.org * event is specified by deriving a subclass and overriding the 596221Snate@binkert.org * process() member function. 602292SN/A * 616221Snate@binkert.org * Caution, the order of members is chosen to maximize data packing. 626221Snate@binkert.org */ 636221Snate@binkert.orgclass Event : public Serializable, public FastAlloc 642292SN/A{ 656221Snate@binkert.org friend class EventQueue; 666221Snate@binkert.org 676221Snate@binkert.org protected: 682292SN/A typedef short FlagsType; 696221Snate@binkert.org typedef ::Flags<FlagsType> Flags; 702292SN/A 716221Snate@binkert.org static const FlagsType PublicRead = 0x003f; // public readable flags 722292SN/A static const FlagsType PublicWrite = 0x001d; // public writable flags 736221Snate@binkert.org static const FlagsType Squashed = 0x0001; // has been squashed 742292SN/A static const FlagsType Scheduled = 0x0002; // has been scheduled 752292SN/A static const FlagsType AutoDelete = 0x0004; // delete after dispatch 762292SN/A static const FlagsType AutoSerialize = 0x0008; // must be serialized 772292SN/A static const FlagsType IsExitEvent = 0x0010; // special exit event 782292SN/A static const FlagsType IsMainQueue = 0x0020; // on main event queue 792292SN/A static const FlagsType Initialized = 0x7a40; // somewhat random bits 802292SN/A static const FlagsType InitMask = 0xffc0; // mask for init bits 812292SN/A 822292SN/A bool 832292SN/A initialized() const 842292SN/A { 851060SN/A return this && (flags & InitMask) == Initialized; 861060SN/A } 871061SN/A 881060SN/A public: 892292SN/A typedef int8_t Priority; 901062SN/A 911062SN/A private: 922301SN/A // The event queue is now a linked list of linked lists. The 931062SN/A // 'nextBin' pointer is to find the bin, where a bin is defined as 941062SN/A // when+priority. All events in the same bin will be stored in a 951062SN/A // second linked list (a stack) maintained by the 'nextInBin' 962301SN/A // pointer. The list will be accessed in LIFO order. The end 971062SN/A // result is that the insert/removal in 'nextBin' is 981062SN/A // linear/constant, and the lookup/removal in 'nextInBin' is 991062SN/A // constant/constant. Hopefully this is a significant improvement 1002301SN/A // over the current fully linear insertion. 1011062SN/A Event *nextBin; 1021062SN/A Event *nextInBin; 1032301SN/A 1042301SN/A static Event *insertBefore(Event *event, Event *curr); 1052301SN/A static Event *removeItem(Event *event, Event *last); 1062301SN/A 1072292SN/A Tick _when; //!< timestamp when event should be processed 1082301SN/A Priority _priority; //!< event priority 1092292SN/A Flags flags; 1102292SN/A 1111062SN/A#ifndef NDEBUG 1122301SN/A /// Global counter to generate unique IDs for Event instances 1131062SN/A static Counter instanceCounter; 1141062SN/A 1151062SN/A /// This event's unique ID. We can also use pointer values for 1162301SN/A /// this but they're not consistent across runs making debugging 1171062SN/A /// more difficult. Thus we use a global counter value when 1181062SN/A /// debugging. 1191062SN/A Counter instance; 1202301SN/A 1211062SN/A /// queue to which this event belongs (though it may or may not be 1221062SN/A /// scheduled on this queue yet) 1231062SN/A EventQueue *queue; 1242301SN/A#endif 1252292SN/A 1261062SN/A#ifdef EVENTQ_DEBUG 1271062SN/A Tick whenCreated; //!< time created 1282301SN/A Tick whenScheduled; //!< time scheduled 1292292SN/A#endif 1301062SN/A 1312292SN/A void 1322301SN/A setWhen(Tick when, EventQueue *q) 1332292SN/A { 1342292SN/A _when = when; 1351062SN/A#ifndef NDEBUG 1362301SN/A queue = q; 1371062SN/A#endif 1381062SN/A#ifdef EVENTQ_DEBUG 1391062SN/A whenScheduled = curTick; 1402301SN/A#endif 1411062SN/A } 1421062SN/A 1431062SN/A protected: 1442301SN/A /// Accessor for flags. 1451062SN/A Flags 1461062SN/A getFlags() const 1471062SN/A { 1482301SN/A return flags & PublicRead; 1491062SN/A } 1501062SN/A 1511062SN/A Flags 1522301SN/A getFlags(Flags _flags) const 1531062SN/A { 1541062SN/A assert(_flags.noneSet(~PublicRead)); 1552301SN/A return flags.isSet(_flags); 1562301SN/A } 1572301SN/A 1582301SN/A Flags 1592301SN/A allFlags(Flags _flags) const 1602301SN/A { 1612301SN/A assert(_flags.noneSet(~PublicRead)); 1622301SN/A return flags.allSet(_flags); 1632301SN/A } 1642301SN/A 1652307SN/A /// Accessor for flags. 1662307SN/A void 1672307SN/A setFlags(Flags _flags) 1682307SN/A { 1692307SN/A assert(_flags.noneSet(~PublicWrite)); 1701062SN/A flags.set(_flags); 1711062SN/A } 1721062SN/A 1731062SN/A void 1742292SN/A clearFlags(Flags _flags) 1751060SN/A { 1761060SN/A assert(_flags.noneSet(~PublicWrite)); 1771060SN/A flags.clear(_flags); 1781060SN/A } 1791060SN/A 1801060SN/A void 1811060SN/A clearFlags() 1821060SN/A { 1831060SN/A flags.clear(PublicWrite); 1841060SN/A } 1851060SN/A 1861060SN/A // This function isn't really useful if TRACING_ON is not defined 1871060SN/A virtual void trace(const char *action); //!< trace event activity 1881061SN/A 1891060SN/A public: 1902292SN/A /// Event priorities, to provide tie-breakers for events scheduled 1911060SN/A /// at the same cycle. Most events are scheduled at the default 1921060SN/A /// priority; these values are used to control events that need to 1931060SN/A /// be ordered within a cycle. 1941060SN/A 1951060SN/A /// Minimum priority 1961060SN/A static const Priority Minimum_Pri = SCHAR_MIN; 1971060SN/A 1981061SN/A /// If we enable tracing on a particular cycle, do that as the 1991060SN/A /// very first thing so we don't miss any of the events on 2002292SN/A /// that cycle (even if we enter the debugger). 2011060SN/A static const Priority Trace_Enable_Pri = -101; 2021060SN/A 2031060SN/A /// Breakpoints should happen before anything else (except 2041060SN/A /// enabling trace output), so we don't miss any action when 2051060SN/A /// debugging. 2061060SN/A static const Priority Debug_Break_Pri = -100; 2071060SN/A 2081061SN/A /// CPU switches schedule the new CPU's tick event for the 2091060SN/A /// same cycle (after unscheduling the old CPU's tick event). 2102292SN/A /// The switch needs to come before any tick events to make 2111060SN/A /// sure we don't tick both CPUs in the same cycle. 2122329SN/A static const Priority CPU_Switch_Pri = -31; 2136221Snate@binkert.org 2142292SN/A /// For some reason "delayed" inter-cluster writebacks are 2152292SN/A /// scheduled before regular writebacks (which have default 2162292SN/A /// priority). Steve? 2172292SN/A static const Priority Delayed_Writeback_Pri = -1; 2182292SN/A 2191060SN/A /// Default is zero for historical reasons. 2201060SN/A static const Priority Default_Pri = 0; 2212292SN/A 2222292SN/A /// Serailization needs to occur before tick events also, so 2236221Snate@binkert.org /// that a serialize/unserialize is identical to an on-line 2242292SN/A /// CPU switch. 2252292SN/A static const Priority Serialize_Pri = 32; 2262292SN/A 2272292SN/A /// CPU ticks must come after other associated CPU events 2282292SN/A /// (such as writebacks). 2291061SN/A static const Priority CPU_Tick_Pri = 50; 2301060SN/A 2312292SN/A /// Statistics events (dump, reset, etc.) come after 2321060SN/A /// everything else, but before exit. 2336221Snate@binkert.org static const Priority Stat_Event_Pri = 90; 2346221Snate@binkert.org 2351060SN/A /// Progress events come at the end. 2361060SN/A static const Priority Progress_Event_Pri = 95; 2371061SN/A 2381060SN/A /// If we want to exit on this cycle, it's the very last thing 2392292SN/A /// we do. 2401060SN/A static const Priority Sim_Exit_Pri = 100; 2412292SN/A 2422292SN/A /// Maximum priority 2431060SN/A static const Priority Maximum_Pri = SCHAR_MAX; 2442292SN/A 2452292SN/A /* 2462292SN/A * Event constructor 2472292SN/A * @param queue that the event gets scheduled on 2482292SN/A */ 2491060SN/A Event(Priority p = Default_Pri) 2501060SN/A : nextBin(NULL), nextInBin(NULL), _priority(p), flags(Initialized) 2511061SN/A { 2522863Sktlim@umich.edu#ifndef NDEBUG 2532843Sktlim@umich.edu instance = ++instanceCounter; 2541060SN/A queue = NULL; 2552348SN/A#endif 2562843Sktlim@umich.edu#ifdef EVENTQ_DEBUG 2572863Sktlim@umich.edu whenCreated = curTick; 2582316SN/A whenScheduled = 0; 2591060SN/A#endif 2602316SN/A } 2612316SN/A 2622843Sktlim@umich.edu virtual ~Event(); 2632316SN/A virtual const std::string name() const; 2642348SN/A 2656221Snate@binkert.org /// Return a C string describing the event. This string should 2662980Sgblack@eecs.umich.edu /// *not* be dynamically allocated; just a const char array 2676221Snate@binkert.org /// describing the event class. 2682307SN/A virtual const char *description() const; 2696221Snate@binkert.org 2706221Snate@binkert.org /// Dump the current event data 2712307SN/A void dump() const; 2722307SN/A 2736221Snate@binkert.org public: 2742307SN/A /* 2752307SN/A * This member function is invoked when the event is processed 2762307SN/A * (occurs). There is no default implementation; each subclass 2776221Snate@binkert.org * must provide its own implementation. The event is not 2782307SN/A * automatically deleted after it is processed (to allow for 2792307SN/A * statically allocated event objects). 2802307SN/A * 2812307SN/A * If the AutoDestroy flag is set, the object is deleted once it 2822361SN/A * is processed. 2832361SN/A */ 2842361SN/A virtual void process() = 0; 2852361SN/A 2862361SN/A /// Determine if the current event is scheduled 2876221Snate@binkert.org bool scheduled() const { return flags.isSet(Scheduled); } 2882307SN/A 2896221Snate@binkert.org /// Squash the current event 2906221Snate@binkert.org void squash() { flags.set(Squashed); } 2911060SN/A 2921060SN/A /// Check whether the event is squashed 2931060SN/A bool squashed() const { return flags.isSet(Squashed); } 2941061SN/A 2951060SN/A /// See if this is a SimExitEvent (without resorting to RTTI) 2962307SN/A bool isExitEvent() const { return flags.isSet(IsExitEvent); } 2971060SN/A 2982307SN/A /// Get the time that the event is scheduled 2992307SN/A Tick when() const { return _when; } 3001060SN/A 3012329SN/A /// Get the event priority 3026221Snate@binkert.org Priority priority() const { return _priority; } 3036221Snate@binkert.org 3041060SN/A#ifndef SWIG 3056221Snate@binkert.org struct priority_compare 3066221Snate@binkert.org : public std::binary_function<Event *, Event *, bool> 3076221Snate@binkert.org { 3082307SN/A bool 3096221Snate@binkert.org operator()(const Event *l, const Event *r) const 3102307SN/A { 3116221Snate@binkert.org return l->when() >= r->when() || l->priority() >= r->priority(); 3122307SN/A } 3136221Snate@binkert.org }; 3142307SN/A 3152307SN/A virtual void serialize(std::ostream &os); 3162307SN/A virtual void unserialize(Checkpoint *cp, const std::string §ion); 3172307SN/A#endif 3182307SN/A}; 3196221Snate@binkert.org 3201858SN/A#ifndef SWIG 3212292SN/Ainline bool 3221858SN/Aoperator<(const Event &l, const Event &r) 3232292SN/A{ 3242292SN/A return l.when() < r.when() || 3252292SN/A (l.when() == r.when() && l.priority() < r.priority()); 3262292SN/A} 3273788Sgblack@eecs.umich.edu 3282292SN/Ainline bool 3292698Sktlim@umich.eduoperator>(const Event &l, const Event &r) 3303788Sgblack@eecs.umich.edu{ 3312301SN/A return l.when() > r.when() || 3323788Sgblack@eecs.umich.edu (l.when() == r.when() && l.priority() > r.priority()); 3333788Sgblack@eecs.umich.edu} 3343788Sgblack@eecs.umich.edu 3353788Sgblack@eecs.umich.eduinline bool 3363788Sgblack@eecs.umich.eduoperator<=(const Event &l, const Event &r) 3373788Sgblack@eecs.umich.edu{ 3383788Sgblack@eecs.umich.edu return l.when() < r.when() || 3393788Sgblack@eecs.umich.edu (l.when() == r.when() && l.priority() <= r.priority()); 3403788Sgblack@eecs.umich.edu} 3413788Sgblack@eecs.umich.eduinline bool 3423788Sgblack@eecs.umich.eduoperator>=(const Event &l, const Event &r) 3432292SN/A{ 3442292SN/A return l.when() > r.when() || 3452292SN/A (l.when() == r.when() && l.priority() >= r.priority()); 3462292SN/A} 3472292SN/A 3482329SN/Ainline bool 3492292SN/Aoperator==(const Event &l, const Event &r) 3502292SN/A{ 3512292SN/A return l.when() == r.when() && l.priority() == r.priority(); 3522935Sksewell@umich.edu} 3532935Sksewell@umich.edu 3542731Sktlim@umich.eduinline bool 3552292SN/Aoperator!=(const Event &l, const Event &r) 3562292SN/A{ 3572292SN/A return l.when() != r.when() || l.priority() != r.priority(); 3582935Sksewell@umich.edu} 3592292SN/A#endif 3602292SN/A 3612935Sksewell@umich.edu/* 3624632Sgblack@eecs.umich.edu * Queue of events sorted in time order 3633093Sksewell@umich.edu */ 3642292SN/Aclass EventQueue : public Serializable 3652292SN/A{ 3663093Sksewell@umich.edu private: 3674632Sgblack@eecs.umich.edu std::string objName; 3682935Sksewell@umich.edu Event *head; 3692292SN/A 3702292SN/A void insert(Event *event); 3712292SN/A void remove(Event *event); 3722292SN/A 3732292SN/A EventQueue(const EventQueue &); 3742292SN/A const EventQueue &operator=(const EventQueue &); 3752292SN/A 3762292SN/A public: 3772292SN/A EventQueue(const std::string &n); 3782292SN/A 3792292SN/A virtual const std::string name() const { return objName; } 3802292SN/A 3812292SN/A // schedule the given event on this queue 3822292SN/A void schedule(Event *event, Tick when); 3832292SN/A void deschedule(Event *event); 3842292SN/A void reschedule(Event *event, Tick when, bool always = false); 3856221Snate@binkert.org 3866221Snate@binkert.org Tick nextTick() const { return head->when(); } 3872292SN/A Event *serviceOne(); 3882292SN/A 3893867Sbinkertn@umich.edu // process all events up to the given timestamp. we inline a 3906221Snate@binkert.org // quick test to see if there are any events to process; if so, 3912292SN/A // call the internal out-of-line version to process them all. 3922292SN/A void 3932292SN/A serviceEvents(Tick when) 3942292SN/A { 3952292SN/A while (!empty()) { 3962292SN/A if (nextTick() > when) 3972292SN/A break; 3982292SN/A 3992292SN/A /** 4002292SN/A * @todo this assert is a good bug catcher. I need to 4012292SN/A * make it true again. 4022292SN/A */ 4032292SN/A //assert(head->when() >= when && "event scheduled in the past"); 4042292SN/A serviceOne(); 4052292SN/A } 4062292SN/A } 4072292SN/A 4083867Sbinkertn@umich.edu // default: process all events up to 'now' (curTick) 4092292SN/A void serviceEvents() { serviceEvents(curTick); } 4103867Sbinkertn@umich.edu 4116221Snate@binkert.org // return true if no events are queued 4122292SN/A bool empty() const { return head == NULL; } 4132292SN/A 4142292SN/A void dump() const; 4152292SN/A 4162292SN/A Tick nextEventTime() { return empty() ? curTick : head->when(); } 4172292SN/A 4182292SN/A bool debugVerify() const; 4192292SN/A 4202292SN/A#ifndef SWIG 4212292SN/A virtual void serialize(std::ostream &os); 4222292SN/A virtual void unserialize(Checkpoint *cp, const std::string §ion); 4232292SN/A#endif 4246221Snate@binkert.org}; 4252292SN/A 4262292SN/A#ifndef SWIG 4272292SN/Aclass EventManager 4282292SN/A{ 4292292SN/A protected: 4302292SN/A /** A pointer to this object's event queue */ 4312292SN/A EventQueue *eventq; 4322292SN/A 4332292SN/A public: 4346221Snate@binkert.org EventManager(EventManager &em) : eventq(em.queue()) {} 4352292SN/A EventManager(EventManager *em) : eventq(em ? em->queue() : NULL) {} 4362292SN/A EventManager(EventQueue *eq) : eventq(eq) {} 4372292SN/A 4382292SN/A EventQueue * 4392292SN/A queue() const 4402292SN/A { 4412292SN/A return eventq; 4422292SN/A } 4432292SN/A 4442292SN/A operator EventQueue *() const 4452292SN/A { 4462292SN/A return eventq; 4472301SN/A } 4482301SN/A 4493788Sgblack@eecs.umich.edu void 4503788Sgblack@eecs.umich.edu schedule(Event &event, Tick when) 4513788Sgblack@eecs.umich.edu { 4523788Sgblack@eecs.umich.edu eventq->schedule(&event, when); 4533788Sgblack@eecs.umich.edu } 4543788Sgblack@eecs.umich.edu 4553788Sgblack@eecs.umich.edu void 4563788Sgblack@eecs.umich.edu deschedule(Event &event) 4573798Sgblack@eecs.umich.edu { 4583798Sgblack@eecs.umich.edu eventq->deschedule(&event); 4593798Sgblack@eecs.umich.edu } 4603798Sgblack@eecs.umich.edu 4613798Sgblack@eecs.umich.edu void 4623798Sgblack@eecs.umich.edu reschedule(Event &event, Tick when, bool always = false) 4632292SN/A { 4642292SN/A eventq->reschedule(&event, when, always); 4652292SN/A } 4662292SN/A 4672292SN/A void 4682292SN/A schedule(Event *event, Tick when) 4692292SN/A { 4702292SN/A eventq->schedule(event, when); 4712292SN/A } 4722292SN/A 4732292SN/A void 4742292SN/A deschedule(Event *event) 4752292SN/A { 4762292SN/A eventq->deschedule(event); 4772292SN/A } 4782292SN/A 4792292SN/A void 4802292SN/A reschedule(Event *event, Tick when, bool always = false) 4812292SN/A { 4822292SN/A eventq->reschedule(event, when, always); 4831858SN/A } 4841858SN/A}; 4851858SN/A 4861858SN/Ainline void 4871858SN/AEventQueue::schedule(Event *event, Tick when) 4886221Snate@binkert.org{ 4891858SN/A assert((UTick)when >= (UTick)curTick); 4902292SN/A assert(!event->scheduled()); 4912292SN/A assert(event->initialized()); 4922292SN/A 4932292SN/A event->setWhen(when, this); 4941858SN/A insert(event); 4952292SN/A event->flags.set(Event::Scheduled); 4962292SN/A if (this == &mainEventQueue) 4972292SN/A event->flags.set(Event::IsMainQueue); 4982292SN/A else 4992292SN/A event->flags.clear(Event::IsMainQueue); 5002292SN/A 5012292SN/A if (DTRACE(Event)) 5022292SN/A event->trace("scheduled"); 5032292SN/A} 5042292SN/A 5052292SN/Ainline void 5062292SN/AEventQueue::deschedule(Event *event) 5072292SN/A{ 5081858SN/A assert(event->scheduled()); 5092292SN/A assert(event->initialized()); 5102292SN/A 5112292SN/A remove(event); 5122292SN/A 5132292SN/A event->flags.clear(Event::Squashed); 5142292SN/A event->flags.clear(Event::Scheduled); 5152292SN/A 5162292SN/A if (event->flags.isSet(Event::AutoDelete)) 5172292SN/A delete event; 5182292SN/A 5192292SN/A if (DTRACE(Event)) 5202292SN/A event->trace("descheduled"); 5212292SN/A} 5222292SN/A 5232292SN/Ainline void 5242292SN/AEventQueue::reschedule(Event *event, Tick when, bool always) 5252292SN/A{ 5262292SN/A assert(when >= curTick); 5272292SN/A assert(always || event->scheduled()); 5282292SN/A assert(event->initialized()); 5292292SN/A 5302292SN/A if (event->scheduled()) 5312292SN/A remove(event); 5322292SN/A 5332292SN/A event->setWhen(when, this); 5342292SN/A insert(event); 5352292SN/A event->flags.clear(Event::Squashed); 5362292SN/A event->flags.set(Event::Scheduled); 5372292SN/A if (this == &mainEventQueue) 5382292SN/A event->flags.set(Event::IsMainQueue); 5392292SN/A else 5402292SN/A event->flags.clear(Event::IsMainQueue); 5412292SN/A 5422292SN/A if (DTRACE(Event)) 5432292SN/A event->trace("rescheduled"); 5442292SN/A} 5452292SN/A 5462292SN/Atemplate <class T, void (T::* F)()> 5472292SN/Avoid 5482292SN/ADelayFunction(EventQueue *eventq, Tick when, T *object) 5492292SN/A{ 5502292SN/A class DelayEvent : public Event 5512292SN/A { 5522292SN/A private: 5532292SN/A T *object; 5542292SN/A 5552292SN/A public: 5562292SN/A DelayEvent(T *o) 5572292SN/A : object(o) 5582292SN/A { this->setFlags(AutoDelete); } 5592292SN/A void process() { (object->*F)(); } 5602292SN/A const char *description() const { return "delay"; } 5612292SN/A }; 5622292SN/A 5632292SN/A eventq->schedule(new DelayEvent(object), when); 5642292SN/A} 5652292SN/A 5662292SN/Atemplate <class T, void (T::* F)()> 5672292SN/Aclass EventWrapper : public Event 5682292SN/A{ 5692292SN/A private: 5702292SN/A T *object; 5712292SN/A 5722292SN/A public: 5732292SN/A EventWrapper(T *obj, bool del = false, Priority p = Default_Pri) 5742292SN/A : Event(p), object(obj) 5752292SN/A { 5762292SN/A if (del) 5772292SN/A setFlags(AutoDelete); 5782292SN/A } 5792292SN/A 5802292SN/A EventWrapper(T &obj, bool del = false, Priority p = Default_Pri) 5812292SN/A : Event(p), object(&obj) 5822292SN/A { 5832292SN/A if (del) 5842292SN/A setFlags(AutoDelete); 5852292SN/A } 5862292SN/A 5872292SN/A void process() { (object->*F)(); } 5882292SN/A 5892292SN/A const std::string 5902292SN/A name() const 5912292SN/A { 5922292SN/A return object->name() + ".wrapped_event"; 5932292SN/A } 5942292SN/A 5952292SN/A const char *description() const { return "EventWrapped"; } 5962292SN/A}; 5972292SN/A#endif 5982292SN/A 5992292SN/A#endif // __SIM_EVENTQ_HH__ 6002292SN/A