From 127a25707f69c3c6f233df2c899be8bf74d1582f Mon Sep 17 00:00:00 2001 From: adrian Date: Wed, 20 Jun 2012 08:42:58 +0000 Subject: [PATCH] coding-style improved. git-svn-id: https://www4.informatik.uni-erlangen.de/i4svn/danceos/trunk/devel/fail@1364 8c4709b5-6ec9-48aa-a5cd-a96041d1645a --- src/core/sal/Event.hpp | 987 +++++++++++++-------------- src/core/sal/SimulatorController.hpp | 465 +++++++------ 2 files changed, 718 insertions(+), 734 deletions(-) diff --git a/src/core/sal/Event.hpp b/src/core/sal/Event.hpp index 053b0f2e..a45137f2 100644 --- a/src/core/sal/Event.hpp +++ b/src/core/sal/Event.hpp @@ -31,68 +31,67 @@ const unsigned ANY_INTERRUPT = static_cast(-1); * \class BaseEvent * This is the base class for all event types. */ -class BaseEvent -{ - private: - //! current class-scoped id counter to provide \a unique id's - static EventId m_Counter; - protected: - EventId m_Id; //!< unique id of this event - time_t m_tStamp; //!< time stamp of event - unsigned int m_OccCounter; //!< event fires when 0 is reached - unsigned int m_OccCounterInit; //!< initial value for m_OccCounter - ExperimentFlow* m_Parent; //!< this event belongs to experiment m_Parent - public: - BaseEvent() : m_Id(++m_Counter), m_OccCounter(1), m_OccCounterInit(1), m_Parent(NULL) - { updateTime(); } - virtual ~BaseEvent() { } - /** - * Retrieves the unique event id for this event. - * @return the unique id - */ - EventId getId() const { return (m_Id); } - /** - * Retrieves the time stamp of this event. The time stamp is set when - * the event gets created, id est the constructor is called. The meaning - * of this value depends on the actual event type. - * @return the time stamp - */ - std::time_t getTime() const { return (m_tStamp); } - /** - * Decreases the event counter by one. When this counter reaches zero, the - * event will be triggered. - */ - void decreaseCounter() { --m_OccCounter; } - /** - * Sets the event counter to the specified value (default is one). - * @param val the new counter value - */ - void setCounter(unsigned int val = 1) { m_OccCounter = m_OccCounterInit = val; } - /** - * Returns the current counter value. - * @return the counter value - */ - unsigned int getCounter() const { return (m_OccCounter); } - /** - * Resets the event counter to its default value, or the last - * value that was set through setCounter(). - */ - void resetCounter() { m_OccCounter = m_OccCounterInit; } - /** - * Sets the time stamp for this event to the current system time. - */ - void updateTime() { time(&m_tStamp); } - /** - * Returns the parent experiment of this event (context). - * If the event was created temporarily or wasn't linked to a context, - * the return value is \c NULL (unknown identity). - */ - ExperimentFlow* getParent() const { return (m_Parent); } - /** - * Sets the parent (context) of this event. The default context - * is \c NULL (unknown identity). - */ - void setParent(ExperimentFlow* pFlow) { m_Parent = pFlow; } +class BaseEvent { +private: + //! current class-scoped id counter to provide \a unique id's + static EventId m_Counter; +protected: + EventId m_Id; //!< unique id of this event + time_t m_tStamp; //!< time stamp of event + unsigned int m_OccCounter; //!< event fires when 0 is reached + unsigned int m_OccCounterInit; //!< initial value for m_OccCounter + ExperimentFlow* m_Parent; //!< this event belongs to experiment m_Parent +public: + BaseEvent() : m_Id(++m_Counter), m_OccCounter(1), m_OccCounterInit(1), m_Parent(NULL) + { updateTime(); } + virtual ~BaseEvent() { } + /** + * Retrieves the unique event id for this event. + * @return the unique id + */ + EventId getId() const { return (m_Id); } + /** + * Retrieves the time stamp of this event. The time stamp is set when + * the event gets created, id est the constructor is called. The meaning + * of this value depends on the actual event type. + * @return the time stamp + */ + std::time_t getTime() const { return (m_tStamp); } + /** + * Decreases the event counter by one. When this counter reaches zero, the + * event will be triggered. + */ + void decreaseCounter() { --m_OccCounter; } + /** + * Sets the event counter to the specified value (default is one). + * @param val the new counter value + */ + void setCounter(unsigned int val = 1) { m_OccCounter = m_OccCounterInit = val; } + /** + * Returns the current counter value. + * @return the counter value + */ + unsigned int getCounter() const { return (m_OccCounter); } + /** + * Resets the event counter to its default value, or the last + * value that was set through setCounter(). + */ + void resetCounter() { m_OccCounter = m_OccCounterInit; } + /** + * Sets the time stamp for this event to the current system time. + */ + void updateTime() { time(&m_tStamp); } + /** + * Returns the parent experiment of this event (context). + * If the event was created temporarily or wasn't linked to a context, + * the return value is \c NULL (unknown identity). + */ + ExperimentFlow* getParent() const { return (m_Parent); } + /** + * Sets the parent (context) of this event. The default context + * is \c NULL (unknown identity). + */ + void setParent(ExperimentFlow* pFlow) { m_Parent = pFlow; } }; // ---------------------------------------------------------------------------- // Specialized events: @@ -102,128 +101,125 @@ class BaseEvent * \class BEvent * A Breakpoint event to observe instruction changes within a given address space. */ -class BPEvent : virtual public BaseEvent -{ - private: - address_t m_CR3; - address_t m_TriggerInstrPtr; - public: - /** - * Creates a new breakpoint event. The range information is specific to - * the subclasses. - * @param address_space the address space to be oberserved, given as the - * content of a CR3 register. The event will not be triggered unless - * \a ip is part of the given address space. - * ANY_ADDR can be used as a placeholder to allow debugging - * in a random address space. - */ - BPEvent(address_t address_space = ANY_ADDR) - : m_CR3(address_space), m_TriggerInstrPtr(ANY_ADDR) - {} - /** - * Returns the address space register of this event. - */ - address_t getCR3() const - { return m_CR3; } - /** - * Sets the address space register for this event. - */ - void setCR3(address_t iptr) - { m_CR3 = iptr; } - /** - * Checks whether a given address space is matching. - */ - bool aspaceIsMatching(address_t address_space = ANY_ADDR) const; - /** - * Checks whether a given address is matching. - */ - virtual bool isMatching(address_t addr = 0, address_t address_space = ANY_ADDR) const = 0; - /** - * Returns the instruction pointer that triggered this event. - */ - address_t getTriggerInstructionPointer() const - { return m_TriggerInstrPtr; } - /** - * Sets the instruction pointer that triggered this event. Should not - * be used by experiment code. - */ - void setTriggerInstructionPointer(address_t iptr) - { m_TriggerInstrPtr = iptr; } +class BPEvent : virtual public BaseEvent { +private: + address_t m_CR3; + address_t m_TriggerInstrPtr; +public: + /** + * Creates a new breakpoint event. The range information is specific to + * the subclasses. + * @param address_space the address space to be oberserved, given as the + * content of a CR3 register. The event will not be triggered unless + * \a ip is part of the given address space. + * ANY_ADDR can be used as a placeholder to allow debugging + * in a random address space. + */ + BPEvent(address_t address_space = ANY_ADDR) + : m_CR3(address_space), m_TriggerInstrPtr(ANY_ADDR) + {} + /** + * Returns the address space register of this event. + */ + address_t getCR3() const + { return m_CR3; } + /** + * Sets the address space register for this event. + */ + void setCR3(address_t iptr) + { m_CR3 = iptr; } + /** + * Checks whether a given address space is matching. + */ + bool aspaceIsMatching(address_t address_space = ANY_ADDR) const; + /** + * Checks whether a given address is matching. + */ + virtual bool isMatching(address_t addr = 0, address_t address_space = ANY_ADDR) const = 0; + /** + * Returns the instruction pointer that triggered this event. + */ + address_t getTriggerInstructionPointer() const + { return m_TriggerInstrPtr; } + /** + * Sets the instruction pointer that triggered this event. Should not + * be used by experiment code. + */ + void setTriggerInstructionPointer(address_t iptr) + { m_TriggerInstrPtr = iptr; } }; /** * \class BPSingleEvent * A Breakpoint event to observe specific instruction pointers. */ -class BPSingleEvent : virtual public BPEvent -{ - private: - address_t m_WatchInstrPtr; - public: - /** - * Creates a new breakpoint event. - * @param ip the instruction pointer of the breakpoint. If the control - * flow reaches this address and its counter value is zero, the - * event will be triggered. \a eip can be set to the ANY_ADDR - * wildcard to allow arbitrary addresses. - * @param address_space the address space to be oberserved, given as the - * content of a CR3 register. The event will not be triggered unless - * \a ip is part of the given address space. - * Here, too, ANY_ADDR is a placeholder to allow debugging - * in a random address space. - */ - BPSingleEvent(address_t ip = 0, address_t address_space = ANY_ADDR) - : BPEvent(address_space), m_WatchInstrPtr(ip) { } - /** - * Returns the instruction pointer this event waits for. - */ - address_t getWatchInstructionPointer() const - { return m_WatchInstrPtr; } - /** - * Sets the instruction pointer this event waits for. - */ - void setWatchInstructionPointer(address_t iptr) - { m_WatchInstrPtr = iptr; } - /** - * Checks whether a given address is matching. - */ - bool isMatching(address_t addr, address_t address_space) const; +class BPSingleEvent : virtual public BPEvent { +private: + address_t m_WatchInstrPtr; +public: + /** + * Creates a new breakpoint event. + * @param ip the instruction pointer of the breakpoint. If the control + * flow reaches this address and its counter value is zero, the + * event will be triggered. \a eip can be set to the ANY_ADDR + * wildcard to allow arbitrary addresses. + * @param address_space the address space to be oberserved, given as the + * content of a CR3 register. The event will not be triggered unless + * \a ip is part of the given address space. + * Here, too, ANY_ADDR is a placeholder to allow debugging + * in a random address space. + */ + BPSingleEvent(address_t ip = 0, address_t address_space = ANY_ADDR) + : BPEvent(address_space), m_WatchInstrPtr(ip) { } + /** + * Returns the instruction pointer this event waits for. + */ + address_t getWatchInstructionPointer() const + { return m_WatchInstrPtr; } + /** + * Sets the instruction pointer this event waits for. + */ + void setWatchInstructionPointer(address_t iptr) + { m_WatchInstrPtr = iptr; } + /** + * Checks whether a given address is matching. + */ + bool isMatching(address_t addr, address_t address_space) const; }; /** * \class BPRangeEvent * A event type to observe ranges of instruction pointers. */ -class BPRangeEvent : virtual public BPEvent -{ - private: - address_t m_WatchStartAddr; - address_t m_WatchEndAddr; - public: - /** - * Creates a new breakpoint-range event. The range's ends are both - * inclusive, i.e. an address matches if start <= addr <= end. - * ANY_ADDR denotes the lower respectively the upper end of the address - * space. - */ - BPRangeEvent(address_t start = 0, address_t end = 0, address_t address_space = ANY_ADDR) - : BPEvent(address_space), m_WatchStartAddr(start), m_WatchEndAddr(end) - { } - /** - * Returns the instruction pointer watch range of this event. - */ - std::pair getWatchInstructionPointerRange() const - { return std::make_pair(m_WatchStartAddr, m_WatchEndAddr); } - /** - * Sets the instruction pointer watch range. Both ends of the range - * may be ANY_ADDR (cf. constructor). - */ - void setWatchInstructionPointerRange(address_t start, - address_t end); - /** - * Checks whether a given address is within the range. - */ - bool isMatching(address_t addr, address_t address_space) const; +class BPRangeEvent : virtual public BPEvent { +private: + address_t m_WatchStartAddr; + address_t m_WatchEndAddr; +public: + /** + * Creates a new breakpoint-range event. The range's ends are both + * inclusive, i.e. an address matches if start <= addr <= end. + * ANY_ADDR denotes the lower respectively the upper end of the address + * space. + */ + BPRangeEvent(address_t start = 0, address_t end = 0, address_t address_space = ANY_ADDR) + : BPEvent(address_space), m_WatchStartAddr(start), m_WatchEndAddr(end) + { } + /** + * Returns the instruction pointer watch range of this event. + */ + std::pair getWatchInstructionPointerRange() const + { return std::make_pair(m_WatchStartAddr, m_WatchEndAddr); } + /** + * Sets the instruction pointer watch range. Both ends of the range + * may be ANY_ADDR (cf. constructor). + */ + void setWatchInstructionPointerRange(address_t start, + address_t end); + /** + * Checks whether a given address is within the range. + */ + bool isMatching(address_t addr, address_t address_space) const; }; /** @@ -232,389 +228,378 @@ class BPRangeEvent : virtual public BPEvent * FIXME? currently >8-bit accesses only match if their lowest address is being watched * (e.g., a 32-bit write to 0x4 also accesses 0x7, but this cannot be matched) */ -class MemAccessEvent : virtual public BaseEvent -{ - public: - enum accessType_t - { - MEM_UNKNOWN = 0x0, - MEM_READ = 0x1, - MEM_WRITE = 0x2, - MEM_READWRITE = 0x3 - }; - private: - //! Specific guest system address to watch, or ANY_ADDR. - address_t m_WatchAddr; - /** - * Memory access type we want to watch - * (MEM_READ || MEM_WRITE || MEM_READWRITE). - */ - accessType_t m_WatchType; - //! Specific guest system address that actually triggered the event. - address_t m_TriggerAddr; - //! Width of the memory access (# bytes). - size_t m_TriggerWidth; - //! Address of the instruction that caused the memory access. - address_t m_TriggerIP; - //! Memory access type at m_TriggerAddr. - accessType_t m_AccessType; - public: - MemAccessEvent(accessType_t watchtype = MEM_READWRITE) - : m_WatchAddr(ANY_ADDR), m_WatchType(watchtype), - m_TriggerAddr(ANY_ADDR), m_TriggerIP(ANY_ADDR), - m_AccessType(MEM_UNKNOWN) { } - MemAccessEvent(address_t addr, - accessType_t watchtype = MEM_READWRITE) - : m_WatchAddr(addr), m_WatchType(watchtype), - m_TriggerAddr(ANY_ADDR), m_TriggerIP(ANY_ADDR), - m_AccessType(MEM_UNKNOWN) { } - /** - * Returns the memory address to be observed. - */ - address_t getWatchAddress() const { return m_WatchAddr; } - /** - * Sets the memory address to be observed. (Wildcard: ANY_ADDR) - */ - void setWatchAddress(address_t addr) { m_WatchAddr = addr; } - /** - * Checks whether a given address is matching. - */ - bool isMatching(address_t addr, accessType_t accesstype) const; - /** - * Returns the specific memory address that actually triggered the - * event. - */ - address_t getTriggerAddress() const { return (m_TriggerAddr); } - /** - * Sets the specific memory address that actually triggered the event. - * Should not be used by experiment code. - */ - void setTriggerAddress(address_t addr) { m_TriggerAddr = addr; } - /** - * Returns the specific memory address that actually triggered the - * event. - */ - size_t getTriggerWidth() const { return (m_TriggerWidth); } - /** - * Sets the specific memory address that actually triggered the event. - * Should not be used by experiment code. - */ - void setTriggerWidth(size_t width) { m_TriggerWidth = width; } - /** - * Returns the address of the instruction causing this memory - * access. - */ - address_t getTriggerInstructionPointer() const - { return (m_TriggerIP); } - /** - * Sets the address of the instruction causing this memory - * access. Should not be used by experiment code. - */ - void setTriggerInstructionPointer(address_t addr) - { m_TriggerIP = addr; } - /** - * Returns type (MEM_READ || MEM_WRITE) of the memory access that - * triggered this event. - */ - accessType_t getTriggerAccessType() const { return (m_AccessType); } - /** - * Sets type of the memory access that triggered this event. Should - * not be used by experiment code. - */ - void setTriggerAccessType(accessType_t type) { m_AccessType = type; } - /** - * Returns memory access types (MEM_READ || MEM_WRITE || MEM_READWRITE) - * this event watches. Should not be used by experiment code. - */ - accessType_t getWatchAccessType() const { return (m_WatchType); } +class MemAccessEvent : virtual public BaseEvent { +public: + enum accessType_t { + MEM_UNKNOWN = 0x0, + MEM_READ = 0x1, + MEM_WRITE = 0x2, + MEM_READWRITE = 0x3 + }; +private: + //! Specific guest system address to watch, or ANY_ADDR. + address_t m_WatchAddr; + /** + * Memory access type we want to watch + * (MEM_READ || MEM_WRITE || MEM_READWRITE). + */ + accessType_t m_WatchType; + //! Specific guest system address that actually triggered the event. + address_t m_TriggerAddr; + //! Width of the memory access (# bytes). + size_t m_TriggerWidth; + //! Address of the instruction that caused the memory access. + address_t m_TriggerIP; + //! Memory access type at m_TriggerAddr. + accessType_t m_AccessType; +public: + MemAccessEvent(accessType_t watchtype = MEM_READWRITE) + : m_WatchAddr(ANY_ADDR), m_WatchType(watchtype), + m_TriggerAddr(ANY_ADDR), m_TriggerIP(ANY_ADDR), + m_AccessType(MEM_UNKNOWN) { } + MemAccessEvent(address_t addr, + accessType_t watchtype = MEM_READWRITE) + : m_WatchAddr(addr), m_WatchType(watchtype), + m_TriggerAddr(ANY_ADDR), m_TriggerIP(ANY_ADDR), + m_AccessType(MEM_UNKNOWN) { } + /** + * Returns the memory address to be observed. + */ + address_t getWatchAddress() const { return m_WatchAddr; } + /** + * Sets the memory address to be observed. (Wildcard: ANY_ADDR) + */ + void setWatchAddress(address_t addr) { m_WatchAddr = addr; } + /** + * Checks whether a given address is matching. + */ + bool isMatching(address_t addr, accessType_t accesstype) const; + /** + * Returns the specific memory address that actually triggered the + * event. + */ + address_t getTriggerAddress() const { return (m_TriggerAddr); } + /** + * Sets the specific memory address that actually triggered the event. + * Should not be used by experiment code. + */ + void setTriggerAddress(address_t addr) { m_TriggerAddr = addr; } + /** + * Returns the specific memory address that actually triggered the + * event. + */ + size_t getTriggerWidth() const { return (m_TriggerWidth); } + /** + * Sets the specific memory address that actually triggered the event. + * Should not be used by experiment code. + */ + void setTriggerWidth(size_t width) { m_TriggerWidth = width; } + /** + * Returns the address of the instruction causing this memory + * access. + */ + address_t getTriggerInstructionPointer() const + { return (m_TriggerIP); } + /** + * Sets the address of the instruction causing this memory + * access. Should not be used by experiment code. + */ + void setTriggerInstructionPointer(address_t addr) + { m_TriggerIP = addr; } + /** + * Returns type (MEM_READ || MEM_WRITE) of the memory access that + * triggered this event. + */ + accessType_t getTriggerAccessType() const { return (m_AccessType); } + /** + * Sets type of the memory access that triggered this event. Should + * not be used by experiment code. + */ + void setTriggerAccessType(accessType_t type) { m_AccessType = type; } + /** + * Returns memory access types (MEM_READ || MEM_WRITE || MEM_READWRITE) + * this event watches. Should not be used by experiment code. + */ + accessType_t getWatchAccessType() const { return (m_WatchType); } }; /** * \class MemReadEvent * Observes memory read accesses. */ -class MemReadEvent : virtual public MemAccessEvent -{ - public: - MemReadEvent() - : MemAccessEvent(MEM_READ) { } - MemReadEvent(address_t addr) - : MemAccessEvent(addr, MEM_READ) { } +class MemReadEvent : virtual public MemAccessEvent { +public: + MemReadEvent() + : MemAccessEvent(MEM_READ) { } + MemReadEvent(address_t addr) + : MemAccessEvent(addr, MEM_READ) { } }; /** * \class MemWriteEvent * Observes memory write accesses. */ -class MemWriteEvent : virtual public MemAccessEvent -{ - public: - MemWriteEvent() - : MemAccessEvent(MEM_READ) { } - MemWriteEvent(address_t addr) - : MemAccessEvent(addr, MEM_WRITE) { } +class MemWriteEvent : virtual public MemAccessEvent { +public: + MemWriteEvent() + : MemAccessEvent(MEM_READ) { } + MemWriteEvent(address_t addr) + : MemAccessEvent(addr, MEM_WRITE) { } }; /** * \class TroubleEvent * Observes interrupt/trap activties. */ -class TroubleEvent : virtual public BaseEvent -{ - private: - /** - * Specific guest system interrupt/trap number that actually - * trigger the event. - */ - int m_TriggerNumber; - /** - * Specific guest system interrupt/trap numbers to watch, - * or ANY_INTERRUPT/ANY_TRAP. - */ - std::vector m_WatchNumbers; - public: - TroubleEvent() : m_TriggerNumber (-1) { } - TroubleEvent(unsigned troubleNumber) - : m_TriggerNumber(-1) - { addWatchNumber(troubleNumber); } - /** - * Add an interrupt/trap-number which should be observed - * @param troubleNumber number of an interrupt or trap - * @return \c true if number is added to the list \c false if the number - * was already in the list - */ - bool addWatchNumber(unsigned troubleNumber); - /** - * Remove an interrupt/trap-number which is in the list of observed - * numbers - * @param troubleNumber number of an interrupt or trap - * @return \c true if the number was found and removed \c false if the - * number was not in the list - */ - bool removeWatchNumber(unsigned troubleNum); - /** - * Returns the list of observed numbers - * @return a copy of the list which contains all observed numbers - */ - std::vector getWatchNumbers() { return (m_WatchNumbers); } - /** - * Checks whether a given interrupt-/trap-number is matching. - */ - bool isMatching(unsigned troubleNum) const; - /** - * Sets the specific interrupt-/trap-number that actually triggered - * the event. Should not be used by experiment code. - */ - void setTriggerNumber(unsigned troubleNum) - { m_TriggerNumber = troubleNum; } - /** - * Returns the specific interrupt-/trap-number that actually triggered - * the event. - */ - unsigned getTriggerNumber() { return (m_TriggerNumber); } +class TroubleEvent : virtual public BaseEvent { +private: + /** + * Specific guest system interrupt/trap number that actually + * trigger the event. + */ + int m_TriggerNumber; + /** + * Specific guest system interrupt/trap numbers to watch, + * or ANY_INTERRUPT/ANY_TRAP. + */ + std::vector m_WatchNumbers; +public: + TroubleEvent() : m_TriggerNumber (-1) { } + TroubleEvent(unsigned troubleNumber) + : m_TriggerNumber(-1) + { addWatchNumber(troubleNumber); } + /** + * Add an interrupt/trap-number which should be observed + * @param troubleNumber number of an interrupt or trap + * @return \c true if number is added to the list \c false if the number + * was already in the list + */ + bool addWatchNumber(unsigned troubleNumber); + /** + * Remove an interrupt/trap-number which is in the list of observed + * numbers + * @param troubleNumber number of an interrupt or trap + * @return \c true if the number was found and removed \c false if the + * number was not in the list + */ + bool removeWatchNumber(unsigned troubleNum); + /** + * Returns the list of observed numbers + * @return a copy of the list which contains all observed numbers + */ + std::vector getWatchNumbers() { return (m_WatchNumbers); } + /** + * Checks whether a given interrupt-/trap-number is matching. + */ + bool isMatching(unsigned troubleNum) const; + /** + * Sets the specific interrupt-/trap-number that actually triggered + * the event. Should not be used by experiment code. + */ + void setTriggerNumber(unsigned troubleNum) + { m_TriggerNumber = troubleNum; } + /** + * Returns the specific interrupt-/trap-number that actually triggered + * the event. + */ + unsigned getTriggerNumber() { return (m_TriggerNumber); } }; /** * \class InterruptEvent * Observes interrupts of the guest system. */ -class InterruptEvent : virtual public TroubleEvent -{ - private: - bool m_IsNMI; //!< non maskable interrupt flag - public: - InterruptEvent() : m_IsNMI(false) { } - InterruptEvent(unsigned interrupt) : m_IsNMI(false) - { addWatchNumber(interrupt); } - /** - * Returns \c true if the interrupt is non maskable, \c false otherwise. - */ - bool isNMI() { return (m_IsNMI); } - /** - * Sets the interrupt type (non maskable or not). - */ - void setNMI(bool enabled) { m_IsNMI = enabled; } +class InterruptEvent : virtual public TroubleEvent { +private: + bool m_IsNMI; //!< non maskable interrupt flag +public: + InterruptEvent() : m_IsNMI(false) { } + InterruptEvent(unsigned interrupt) : m_IsNMI(false) + { addWatchNumber(interrupt); } + /** + * Returns \c true if the interrupt is non maskable, \c false otherwise. + */ + bool isNMI() { return (m_IsNMI); } + /** + * Sets the interrupt type (non maskable or not). + */ + void setNMI(bool enabled) { m_IsNMI = enabled; } }; /** * \class TrapEvent * Observes traps of the guest system. */ -class TrapEvent : virtual public TroubleEvent -{ - public: - TrapEvent() { } - TrapEvent(unsigned trap) { addWatchNumber(trap); } +class TrapEvent : virtual public TroubleEvent { +public: + TrapEvent() { } + TrapEvent(unsigned trap) { addWatchNumber(trap); } }; /** * \class GuestEvent * Used to receive data from the guest system. */ -class GuestEvent : virtual public BaseEvent -{ - private: - char m_Data; - unsigned m_Port; - public: - GuestEvent() : m_Data(0), m_Port(0) { } - /** - * Returns the data, transmitted by the guest system. - */ - char getData() const { return (m_Data); } - /** - * Sets the data which had been transmitted by the guest system. - */ - void setData(char data) { m_Data = data; } - /** - * Returns the data length, transmitted by the guest system. - */ - unsigned getPort() const { return (m_Port); } - /** - * Sets the data length which had been transmitted by the guest system. - */ - void setPort(unsigned port) { m_Port = port; } +class GuestEvent : virtual public BaseEvent { +private: + char m_Data; + unsigned m_Port; +public: + GuestEvent() : m_Data(0), m_Port(0) { } + /** + * Returns the data, transmitted by the guest system. + */ + char getData() const { return (m_Data); } + /** + * Sets the data which had been transmitted by the guest system. + */ + void setData(char data) { m_Data = data; } + /** + * Returns the data length, transmitted by the guest system. + */ + unsigned getPort() const { return (m_Port); } + /** + * Sets the data length which had been transmitted by the guest system. + */ + void setPort(unsigned port) { m_Port = port; } }; /** * \class IOPortEvent * Observes I/O access on architectures with a separate I/O access mechanism (e.g. IA-32) */ -class IOPortEvent : virtual public BaseEvent -{ - private: - unsigned char m_Data; - unsigned m_Port; - bool m_Out; - public: - /** - * Initialises an IOPortEvent - * - * @param port the port the event ist listening on - * @param out Defines the direction of the event. - * \arg \c true Output on the given port is captured. - * \arg \c false Input on the given port is captured. - */ - IOPortEvent(unsigned port, bool out) : m_Data(0), m_Port(port), m_Out(out) { } - /** - * Returns the data sent to the specified port - */ - unsigned char getData() const { return (m_Data); } - /** - * Sets the data which had been transmitted. - */ - void setData(unsigned char data) { m_Data = data; } - /** - * Retrieves the port which this event is bound to. - */ - unsigned getPort() const { return (m_Port); } - /** - * Sets the port which this event is bound to. - */ - void setPort(unsigned port) { m_Port = port; } - /** - * Checks whether a given port number is matching. - * @param p The port number an I/O event occured on - * @param out True if the communication was outbound, false otherwise - */ - bool isMatching(unsigned p, bool out) const { return ( out = isOutEvent() && p == getPort()); } - /** - * Tells you if this event is capturing outbound communication (inbound if false) - */ - bool isOutEvent() const { return m_Out; } - /** - * Change the event direction. - * \arg \c true Output on the given port is captured. - * \arg \c false Input on the given port is captured. - */ - void setOut(bool out) { m_Out = out; } +class IOPortEvent : virtual public BaseEvent { +private: + unsigned char m_Data; + unsigned m_Port; + bool m_Out; +public: + /** + * Initialises an IOPortEvent + * + * @param port the port the event ist listening on + * @param out Defines the direction of the event. + * \arg \c true Output on the given port is captured. + * \arg \c false Input on the given port is captured. + */ + IOPortEvent(unsigned port, bool out) : m_Data(0), m_Port(port), m_Out(out) { } + /** + * Returns the data sent to the specified port + */ + unsigned char getData() const { return (m_Data); } + /** + * Sets the data which had been transmitted. + */ + void setData(unsigned char data) { m_Data = data; } + /** + * Retrieves the port which this event is bound to. + */ + unsigned getPort() const { return (m_Port); } + /** + * Sets the port which this event is bound to. + */ + void setPort(unsigned port) { m_Port = port; } + /** + * Checks whether a given port number is matching. + * @param p The port number an I/O event occured on + * @param out True if the communication was outbound, false otherwise + */ + bool isMatching(unsigned p, bool out) const { return ( out = isOutEvent() && p == getPort()); } + /** + * Tells you if this event is capturing outbound communication (inbound if false) + */ + bool isOutEvent() const { return m_Out; } + /** + * Change the event direction. + * \arg \c true Output on the given port is captured. + * \arg \c false Input on the given port is captured. + */ + void setOut(bool out) { m_Out = out; } }; /** * \class JumpEvent * JumpEvents are used to observe conditional jumps (if...else if...else). */ -class JumpEvent : virtual public BaseEvent -{ - private: - unsigned m_Opcode; - bool m_FlagTriggered; - public: - /** - * Constructs a new event object. - * @param parent the parent object - * @param opcode the opcode of the jump-instruction to be observed - * or ANY_INSTR to match all jump-instructions - */ - JumpEvent(unsigned opcode = ANY_INSTR) - : m_Opcode(opcode), m_FlagTriggered(false) { } - /** - * Retrieves the opcode of the jump-instruction. - */ - unsigned getOpcode() const { return (m_Opcode); } - /** - * Returns \c true, of the event was triggered due to specific register - * content, \c false otherwise. - */ - bool isRegisterTriggered() { return (!m_FlagTriggered); } - /** - * Returns \c true, of the event was triggered due to specific FLAG - * state, \c false otherwise. This is the common case. - */ - bool isFlagTriggered() { return (m_FlagTriggered); } - /** - * Sets the requestet jump-instruction opcode. - */ - void setOpcode(unsigned oc) { oc = m_Opcode; } - /** - * Sets the trigger flag. - */ - void setFlagTriggered(bool flagTriggered) - { m_FlagTriggered = flagTriggered; } +class JumpEvent : virtual public BaseEvent { +private: + unsigned m_Opcode; + bool m_FlagTriggered; +public: + /** + * Constructs a new event object. + * @param parent the parent object + * @param opcode the opcode of the jump-instruction to be observed + * or ANY_INSTR to match all jump-instructions + */ + JumpEvent(unsigned opcode = ANY_INSTR) + : m_Opcode(opcode), m_FlagTriggered(false) { } + /** + * Retrieves the opcode of the jump-instruction. + */ + unsigned getOpcode() const { return (m_Opcode); } + /** + * Returns \c true, of the event was triggered due to specific register + * content, \c false otherwise. + */ + bool isRegisterTriggered() { return (!m_FlagTriggered); } + /** + * Returns \c true, of the event was triggered due to specific FLAG + * state, \c false otherwise. This is the common case. + */ + bool isFlagTriggered() { return (m_FlagTriggered); } + /** + * Sets the requestet jump-instruction opcode. + */ + void setOpcode(unsigned oc) { oc = m_Opcode; } + /** + * Sets the trigger flag. + */ + void setFlagTriggered(bool flagTriggered) + { m_FlagTriggered = flagTriggered; } }; /** * \class TimerEvent * This event type is used to create timeouts/timers within in an experiment. */ -class TimerEvent : public BaseEvent -{ - private: - unsigned m_Timeout; //!< timeout interval in milliseconds - timer_id_t m_Id; //!< internal timer id (sim-specific) - bool m_Once; //!< true, if the timer should be triggered only once - public: - /** - * Creates a new timer event. This can be used to implement a timeout- - * mechanism in the experiment-flow. The timer starts automatically when - * added to the simulator backend (@see SimulatorController::addEvent) - * @param timeout the time intervall in milliseconds (ms) - * @param once \c true, if the TimerEvent should be triggered once, - * \c false if it should occur regularly - */ - TimerEvent(unsigned timeout, bool once) - : m_Timeout(timeout), m_Id(-1), m_Once(once) { } - ~TimerEvent() { } - /** - * Retrieves the internal timer id. Maybe useful for debug output. - * @return the timer id - */ - timer_id_t getId() const { return m_Id; } - /** - * Sets the internal timer id. This should not be used by the experiment. - * @param id the new timer id, given by the underlying simulator-backend - */ - void setId(timer_id_t id) { m_Id = id; } - /** - * Retrieves the timer's timeout value. - * @return the timout in milliseconds - */ - unsigned getTimeout() const { return m_Timeout; } - /** - * Checks whether the timer occurs once or repetitive. - * @return \c true if timer triggers once, \c false if repetitive - */ - bool getOnceFlag() const { return m_Once; } +class TimerEvent : public BaseEvent { +private: + unsigned m_Timeout; //!< timeout interval in milliseconds + timer_id_t m_Id; //!< internal timer id (sim-specific) + bool m_Once; //!< true, if the timer should be triggered only once +public: + /** + * Creates a new timer event. This can be used to implement a timeout- + * mechanism in the experiment-flow. The timer starts automatically when + * added to the simulator backend (@see SimulatorController::addEvent) + * @param timeout the time intervall in milliseconds (ms) + * @param once \c true, if the TimerEvent should be triggered once, + * \c false if it should occur regularly + */ + TimerEvent(unsigned timeout, bool once) + : m_Timeout(timeout), m_Id(-1), m_Once(once) { } + ~TimerEvent() { } + /** + * Retrieves the internal timer id. Maybe useful for debug output. + * @return the timer id + */ + timer_id_t getId() const { return m_Id; } + /** + * Sets the internal timer id. This should not be used by the experiment. + * @param id the new timer id, given by the underlying simulator-backend + */ + void setId(timer_id_t id) { m_Id = id; } + /** + * Retrieves the timer's timeout value. + * @return the timout in milliseconds + */ + unsigned getTimeout() const { return m_Timeout; } + /** + * Checks whether the timer occurs once or repetitive. + * @return \c true if timer triggers once, \c false if repetitive + */ + bool getOnceFlag() const { return m_Once; } }; } // end-of-namespace: fail diff --git a/src/core/sal/SimulatorController.hpp b/src/core/sal/SimulatorController.hpp index bf7a2fa1..51ce0ac5 100644 --- a/src/core/sal/SimulatorController.hpp +++ b/src/core/sal/SimulatorController.hpp @@ -31,239 +31,238 @@ class MemoryManager; * activates the specific experiment There are further methods to read/write * registers and memory, and control the SUT (save/restore/reset). */ -class SimulatorController -{ - protected: - EventList m_EvList; //!< storage where events are being buffered - CoroutineManager m_Flows; //!< managed experiment flows - RegisterManager *m_Regs; //!< access to cpu register - MemoryManager *m_Mem; //!< access to memory pool - //! list of suppressed interrupts - std::vector m_SuppressedInterrupts; - friend class EventList; //!< "outsources" the event management - public: - SimulatorController() - : m_Regs(NULL), m_Mem(NULL) { } - SimulatorController(RegisterManager* regs, MemoryManager* mem) - : m_Regs(regs), m_Mem(mem) { } - virtual ~SimulatorController() { } - /** - * @brief Initialization function each implementation needs to call on - * startup - * - * This function needs to be invoked once the simulator starts, and - * allows the SimulatorController to instantiate all needed experiment - * components. - */ - void startup(); - /** - * Experiments need to hook here. - */ - void initExperiments(); - /* ******************************************************************** - * Standard Event Handler API - * ********************************************************************/ - /** - * Breakpoint event handler. This routine needs to be called in the - * simulator specific backend each time a breakpoint event occurs. - * @param instrPtr the instruction pointer of the breakpoint event - * @param address_space the address space it should occur in - */ - void onBreakpointEvent(address_t instrPtr, address_t address_space); - /** - * Memory access event handler (read/write). - * @param addr the accessed memory address - * @param len the length of the accessed memory - * @param is_write \c true if memory is written, \c false if read - * @param instrPtr the address of the instruction causing the memory - * access - * - * FIXME: should instrPtr be part of this interface? - */ - void onMemoryAccessEvent(address_t addr, size_t len, - bool is_write, address_t instrPtr); - /** - * Interrupt event handler. - * @param interruptNum the interrupt-type id - * @param nmi nmi-value from guest-system - */ - void onInterruptEvent(unsigned interruptNum, bool nmi); - /** - * Trap event handler. - * @param trapNum the trap-type id - */ - void onTrapEvent(unsigned trapNum); - /** - * Guest system communication handler. - * @param data the "message" from the guest system - * @param port the port of the event - */ - void onGuestSystemEvent(char data, unsigned port); - /** - * (Conditional) Jump-instruction handler. - * @param flagTriggered \c true if the jump was triggered due to a - * specific FLAG (zero/carry/sign/overflow/parity flag) - * @param opcode the opcode of the conrecete jump instruction - */ - void onJumpEvent(bool flagTriggered, unsigned opcode); - /** - * This method is called when an experiment flow adds a new event by - * calling \c simulator.addEvent(pev) or \c simulator.addEventAndWait(pev). - * More specifically, the event will be added to the event-list first - * (buffer-list, to be precise) and then this event handler is called. - * @param pev the event which has been added - * @return You should return \c true to continue and \c false to prevent - * the addition of the event \a pev, yielding an error in the - * experiment flow (i.e. -1 is returned). - */ - virtual bool onEventAddition(BaseEvent* pev) { return true; } - /** - * This method is called when an experiment flow removes an event from - * the event-management by calling \c removeEvent(prev), \c clearEvents() - * or by deleting a complete flow (\c removeFlow). More specifically, this - * event handler will be called *before* the event is actually deleted. - * @param pev the event to be deleted when returning from the event handler - */ - virtual void onEventDeletion(BaseEvent* pev) { } - /** - * This method is called when an previously added event is about to be - * triggered by the simulator-backend. More specifically, this event handler - * will be called *before* the event is actually triggered, i.e. before the - * corresponding coroutine is toggled. - * @param pev the event to be triggered when returning from the event handler - */ - virtual void onEventTrigger(BaseEvent* pev) { } - /* ******************************************************************** - * Simulator Controller & Access API: - * ********************************************************************/ - /** - * Save simulator state. - * @param path Location to store state information - */ - virtual void save(const std::string& path) = 0; - /** - * Restore simulator state. Implicitly discards all previously - * registered events. - * @param path Location to previously saved state information - */ - virtual void restore(const std::string& path) = 0; - /** - * Reboot simulator. - */ - virtual void reboot() = 0; - /** - * Terminate simulator - * @param exCode Individual exit code - */ - void terminate(int exCode = EXIT_SUCCESS) __attribute__ ((noreturn)); - /** - * Check whether the interrupt should be suppressed. - * @param interruptNum the interrupt-type id - * @return \c true if the interrupt is suppressed, \c false oterwise - */ - bool isSuppressedInterrupt(unsigned interruptNum); - /** - * Add a Interrupt to the list of suppressed. - * @param interruptNum the interrupt-type id - * @return \c true if sucessfully added, \c false otherwise (already - * existing) - */ - bool addSuppressedInterrupt(unsigned interruptNum); - /** - * Remove a Interrupt from the list of suppressed. - * @param interruptNum the interrupt-type id - * @return \c true if sucessfully removed, \c false otherwise (not - * found) - */ - bool removeSuppressedInterrupt(unsigned interruptNum); - /** - * Returns the (constant) initialized register manager. - * @return a reference to the register manager - */ - RegisterManager& getRegisterManager() { return (*m_Regs); } - const RegisterManager& getRegisterManager() const { return (*m_Regs); } - /** - * Sets the register manager. - * @param pReg the new register manager (or a concrete derived class of - * RegisterManager) - */ - void setRegisterManager(RegisterManager* pReg) { m_Regs = pReg; } - /** - * Returns the (constant) initialized memory manager. - * @return a reference to the memory manager - */ - MemoryManager& getMemoryManager() { return (*m_Mem); } - const MemoryManager& getMemoryManager() const { return (*m_Mem); } - /** - * Sets the memory manager. - * @param pMem a new concrete memory manager - */ - void setMemoryManager(MemoryManager* pMem) { m_Mem = pMem; } - /* ******************************************************************** - * Experiment-Flow & Event Management API: - * ********************************************************************/ - /** - * Adds the specified experiment or plugin and creates a coroutine to - * run it in. - * @param flow the experiment flow object to be added - */ - void addFlow(ExperimentFlow* flow); - /** - * Removes the specified experiment or plugin and destroys its coroutine - * and all associated events. - * @param flow the experiment flow object to be removed - */ - void removeFlow(ExperimentFlow* flow); - /** - * Add event ev to the event management. This causes the event to be - * active. - * @param ev the event pointer to be added for the current flow - * @return the id of the event used to identify the object on occurrence; - * -1 is returned on errors - */ - EventId addEvent(BaseEvent* ev); - /** - * Removes the event with the specified id. - * @param ev the pointer of the event-object to be removed; if \a ev is - * equal to \c NULL all events (for all experiments) will be - * removed - */ - void removeEvent(BaseEvent* ev) { m_EvList.remove(ev); } - /** - * Removes all previously added events for all experiments. To - * restrict this to a specific experiment flow, pass a pointer to it. - */ - void clearEvents(ExperimentFlow *flow = 0) { m_EvList.remove(flow); } - /** - * Waits on any events which have been added to the event management. If - * one of those events occour, waitAny() will return the id of that event. - * @return the previously occurred event - * - * FIXME: Maybe this should return immediately if there are not events? - * (additional parameter flag?) - */ - BaseEvent* waitAny(); - /** - * Add event \a ev to the global buffer and wait for it (combines - * \c addEvent() and \c waitAny()). - * @param ev the event pointer to be added - * @return the pointer of the occurred event (it is not guaranteed that - * this pointer will be equal to ev) - * - * FIXME: Rename to make clear this returns when *any* event occurs - */ - BaseEvent* addEventAndWait(BaseEvent* ev); - /** - * Checks whether any experiment flow has events in the event-list. - * @return \c true if there are still events, or \c false otherwise - */ - bool hasEvents() const { return getEventCount() > 0; } - /** - * Determines the number of (stored) events in the event-list which have - * not been triggered so far. - * @return the actual number of events - */ - unsigned getEventCount() const { return m_EvList.getEventCount(); } +class SimulatorController { +protected: + EventList m_EvList; //!< storage where events are being buffered + CoroutineManager m_Flows; //!< managed experiment flows + RegisterManager *m_Regs; //!< access to cpu register + MemoryManager *m_Mem; //!< access to memory pool + //! list of suppressed interrupts + std::vector m_SuppressedInterrupts; + friend class EventList; //!< "outsources" the event management +public: + SimulatorController() + : m_Regs(NULL), m_Mem(NULL) { } + SimulatorController(RegisterManager* regs, MemoryManager* mem) + : m_Regs(regs), m_Mem(mem) { } + virtual ~SimulatorController() { } + /** + * @brief Initialization function each implementation needs to call on + * startup + * + * This function needs to be invoked once the simulator starts, and + * allows the SimulatorController to instantiate all needed experiment + * components. + */ + void startup(); + /** + * Experiments need to hook here. + */ + void initExperiments(); + /* ******************************************************************** + * Standard Event Handler API + * ********************************************************************/ + /** + * Breakpoint event handler. This routine needs to be called in the + * simulator specific backend each time a breakpoint event occurs. + * @param instrPtr the instruction pointer of the breakpoint event + * @param address_space the address space it should occur in + */ + void onBreakpointEvent(address_t instrPtr, address_t address_space); + /** + * Memory access event handler (read/write). + * @param addr the accessed memory address + * @param len the length of the accessed memory + * @param is_write \c true if memory is written, \c false if read + * @param instrPtr the address of the instruction causing the memory + * access + * + * FIXME: should instrPtr be part of this interface? + */ + void onMemoryAccessEvent(address_t addr, size_t len, + bool is_write, address_t instrPtr); + /** + * Interrupt event handler. + * @param interruptNum the interrupt-type id + * @param nmi nmi-value from guest-system + */ + void onInterruptEvent(unsigned interruptNum, bool nmi); + /** + * Trap event handler. + * @param trapNum the trap-type id + */ + void onTrapEvent(unsigned trapNum); + /** + * Guest system communication handler. + * @param data the "message" from the guest system + * @param port the port of the event + */ + void onGuestSystemEvent(char data, unsigned port); + /** + * (Conditional) Jump-instruction handler. + * @param flagTriggered \c true if the jump was triggered due to a + * specific FLAG (zero/carry/sign/overflow/parity flag) + * @param opcode the opcode of the conrecete jump instruction + */ + void onJumpEvent(bool flagTriggered, unsigned opcode); + /** + * This method is called when an experiment flow adds a new event by + * calling \c simulator.addEvent(pev) or \c simulator.addEventAndWait(pev). + * More specifically, the event will be added to the event-list first + * (buffer-list, to be precise) and then this event handler is called. + * @param pev the event which has been added + * @return You should return \c true to continue and \c false to prevent + * the addition of the event \a pev, yielding an error in the + * experiment flow (i.e. -1 is returned). + */ + virtual bool onEventAddition(BaseEvent* pev) { return true; } + /** + * This method is called when an experiment flow removes an event from + * the event-management by calling \c removeEvent(prev), \c clearEvents() + * or by deleting a complete flow (\c removeFlow). More specifically, this + * event handler will be called *before* the event is actually deleted. + * @param pev the event to be deleted when returning from the event handler + */ + virtual void onEventDeletion(BaseEvent* pev) { } + /** + * This method is called when an previously added event is about to be + * triggered by the simulator-backend. More specifically, this event handler + * will be called *before* the event is actually triggered, i.e. before the + * corresponding coroutine is toggled. + * @param pev the event to be triggered when returning from the event handler + */ + virtual void onEventTrigger(BaseEvent* pev) { } + /* ******************************************************************** + * Simulator Controller & Access API: + * ********************************************************************/ + /** + * Save simulator state. + * @param path Location to store state information + */ + virtual void save(const std::string& path) = 0; + /** + * Restore simulator state. Implicitly discards all previously + * registered events. + * @param path Location to previously saved state information + */ + virtual void restore(const std::string& path) = 0; + /** + * Reboot simulator. + */ + virtual void reboot() = 0; + /** + * Terminate simulator + * @param exCode Individual exit code + */ + void terminate(int exCode = EXIT_SUCCESS) __attribute__ ((noreturn)); + /** + * Check whether the interrupt should be suppressed. + * @param interruptNum the interrupt-type id + * @return \c true if the interrupt is suppressed, \c false oterwise + */ + bool isSuppressedInterrupt(unsigned interruptNum); + /** + * Add a Interrupt to the list of suppressed. + * @param interruptNum the interrupt-type id + * @return \c true if sucessfully added, \c false otherwise (already + * existing) + */ + bool addSuppressedInterrupt(unsigned interruptNum); + /** + * Remove a Interrupt from the list of suppressed. + * @param interruptNum the interrupt-type id + * @return \c true if sucessfully removed, \c false otherwise (not + * found) + */ + bool removeSuppressedInterrupt(unsigned interruptNum); + /** + * Returns the (constant) initialized register manager. + * @return a reference to the register manager + */ + RegisterManager& getRegisterManager() { return (*m_Regs); } + const RegisterManager& getRegisterManager() const { return (*m_Regs); } + /** + * Sets the register manager. + * @param pReg the new register manager (or a concrete derived class of + * RegisterManager) + */ + void setRegisterManager(RegisterManager* pReg) { m_Regs = pReg; } + /** + * Returns the (constant) initialized memory manager. + * @return a reference to the memory manager + */ + MemoryManager& getMemoryManager() { return (*m_Mem); } + const MemoryManager& getMemoryManager() const { return (*m_Mem); } + /** + * Sets the memory manager. + * @param pMem a new concrete memory manager + */ + void setMemoryManager(MemoryManager* pMem) { m_Mem = pMem; } + /* ******************************************************************** + * Experiment-Flow & Event Management API: + * ********************************************************************/ + /** + * Adds the specified experiment or plugin and creates a coroutine to + * run it in. + * @param flow the experiment flow object to be added + */ + void addFlow(ExperimentFlow* flow); + /** + * Removes the specified experiment or plugin and destroys its coroutine + * and all associated events. + * @param flow the experiment flow object to be removed + */ + void removeFlow(ExperimentFlow* flow); + /** + * Add event ev to the event management. This causes the event to be + * active. + * @param ev the event pointer to be added for the current flow + * @return the id of the event used to identify the object on occurrence; + * -1 is returned on errors + */ + EventId addEvent(BaseEvent* ev); + /** + * Removes the event with the specified id. + * @param ev the pointer of the event-object to be removed; if \a ev is + * equal to \c NULL all events (for all experiments) will be + * removed + */ + void removeEvent(BaseEvent* ev) { m_EvList.remove(ev); } + /** + * Removes all previously added events for all experiments. To + * restrict this to a specific experiment flow, pass a pointer to it. + */ + void clearEvents(ExperimentFlow *flow = 0) { m_EvList.remove(flow); } + /** + * Waits on any events which have been added to the event management. If + * one of those events occour, waitAny() will return the id of that event. + * @return the previously occurred event + * + * FIXME: Maybe this should return immediately if there are not events? + * (additional parameter flag?) + */ + BaseEvent* waitAny(); + /** + * Add event \a ev to the global buffer and wait for it (combines + * \c addEvent() and \c waitAny()). + * @param ev the event pointer to be added + * @return the pointer of the occurred event (it is not guaranteed that + * this pointer will be equal to ev) + * + * FIXME: Rename to make clear this returns when *any* event occurs + */ + BaseEvent* addEventAndWait(BaseEvent* ev); + /** + * Checks whether any experiment flow has events in the event-list. + * @return \c true if there are still events, or \c false otherwise + */ + bool hasEvents() const { return getEventCount() > 0; } + /** + * Determines the number of (stored) events in the event-list which have + * not been triggered so far. + * @return the actual number of events + */ + unsigned getEventCount() const { return m_EvList.getEventCount(); } }; } // end-of-namespace: fail