diff options
Diffstat (limited to 'src/mem/ruby/buffers')
-rw-r--r-- | src/mem/ruby/buffers/MessageBuffer.cc | 363 | ||||
-rw-r--r-- | src/mem/ruby/buffers/MessageBuffer.hh | 156 | ||||
-rw-r--r-- | src/mem/ruby/buffers/MessageBufferNode.cc | 48 | ||||
-rw-r--r-- | src/mem/ruby/buffers/MessageBufferNode.hh | 88 |
4 files changed, 655 insertions, 0 deletions
diff --git a/src/mem/ruby/buffers/MessageBuffer.cc b/src/mem/ruby/buffers/MessageBuffer.cc new file mode 100644 index 000000000..ff2547f0f --- /dev/null +++ b/src/mem/ruby/buffers/MessageBuffer.cc @@ -0,0 +1,363 @@ + +/* + * Copyright (c) 1999-2008 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. + */ + +/* + * $Id$ + */ + +#include "MessageBuffer.hh" +#include "RubyConfig.hh" + +MessageBuffer::MessageBuffer() +{ + m_msg_counter = 0; + m_consumer_ptr = NULL; + m_ordering_set = false; + m_strict_fifo = true; + m_size = 0; + m_max_size = -1; + m_last_arrival_time = 0; + m_randomization = true; + m_size_last_time_size_checked = 0; + m_time_last_time_size_checked = 0; + m_time_last_time_enqueue = 0; + m_time_last_time_pop = 0; + m_size_at_cycle_start = 0; + m_msgs_this_cycle = 0; + m_not_avail_count = 0; + m_priority_rank = 0; +} + +MessageBuffer::MessageBuffer(const Chip* chip_ptr) // The chip_ptr is ignored, but could be used for extra debugging +{ + m_msg_counter = 0; + m_consumer_ptr = NULL; + m_ordering_set = false; + m_strict_fifo = true; + m_size = 0; + m_max_size = -1; + m_last_arrival_time = 0; + m_randomization = true; + m_size_last_time_size_checked = 0; + m_time_last_time_size_checked = 0; + m_time_last_time_enqueue = 0; + m_time_last_time_pop = 0; + m_size_at_cycle_start = 0; + m_msgs_this_cycle = 0; + m_not_avail_count = 0; + m_priority_rank = 0; +} + +int MessageBuffer::getSize() +{ + if(m_time_last_time_size_checked == g_eventQueue_ptr->getTime()){ + return m_size_last_time_size_checked; + } else { + m_time_last_time_size_checked = g_eventQueue_ptr->getTime(); + m_size_last_time_size_checked = m_size; + return m_size; + } +} + +bool MessageBuffer::areNSlotsAvailable(int n) +{ + + // fast path when message buffers have infinite size + if(m_max_size == -1) { + return true; + } + + // determine my correct size for the current cycle + // pop operations shouldn't effect the network's visible size until next cycle, + // but enqueue operations effect the visible size immediately + int current_size = max(m_size_at_cycle_start, m_size); + if (m_time_last_time_pop < g_eventQueue_ptr->getTime()) { // no pops this cycle - m_size is correct + current_size = m_size; + } else { + if (m_time_last_time_enqueue < g_eventQueue_ptr->getTime()) { // no enqueues this cycle - m_size_at_cycle_start is correct + current_size = m_size_at_cycle_start; + } else { // both pops and enqueues occured this cycle - add new enqueued msgs to m_size_at_cycle_start + current_size = m_size_at_cycle_start+m_msgs_this_cycle; + } + } + + // now compare the new size with our max size + if(current_size+n <= m_max_size){ + return true; + } else { + DEBUG_MSG(QUEUE_COMP,MedPrio,n); + DEBUG_MSG(QUEUE_COMP,MedPrio,current_size); + DEBUG_MSG(QUEUE_COMP,MedPrio,m_size); + DEBUG_MSG(QUEUE_COMP,MedPrio,m_max_size); + m_not_avail_count++; + return false; + } +} + +const MsgPtr MessageBuffer::getMsgPtrCopy() const +{ + assert(isReady()); + + MsgPtr temp_msg; + temp_msg = *(m_prio_heap.peekMin().m_msgptr.ref()); + assert(temp_msg.ref() != NULL); + return temp_msg; +} + +const Message* MessageBuffer::peekAtHeadOfQueue() const +{ + const Message* msg_ptr; + DEBUG_NEWLINE(QUEUE_COMP,MedPrio); + + DEBUG_MSG(QUEUE_COMP,MedPrio,"Peeking at head of queue " + m_name + " time: " + + int_to_string(g_eventQueue_ptr->getTime()) + "."); + assert(isReady()); + + msg_ptr = m_prio_heap.peekMin().m_msgptr.ref(); + assert(msg_ptr != NULL); + + DEBUG_EXPR(QUEUE_COMP,MedPrio,*msg_ptr); + DEBUG_NEWLINE(QUEUE_COMP,MedPrio); + return msg_ptr; +} + +// FIXME - move me somewhere else +int random_time() +{ + int time = 1; + time += random() & 0x3; // [0...3] + if ((random() & 0x7) == 0) { // 1 in 8 chance + time += 100 + (random() % 0xf); // 100 + [1...15] + } + return time; +} + +void MessageBuffer::enqueue(const MsgPtr& message, Time delta) +{ + DEBUG_NEWLINE(QUEUE_COMP,HighPrio); + DEBUG_MSG(QUEUE_COMP,HighPrio,"enqueue " + m_name + " time: " + + int_to_string(g_eventQueue_ptr->getTime()) + "."); + DEBUG_EXPR(QUEUE_COMP,MedPrio,message); + DEBUG_NEWLINE(QUEUE_COMP,HighPrio); + + m_msg_counter++; + m_size++; + + // record current time incase we have a pop that also adjusts my size + if (m_time_last_time_enqueue < g_eventQueue_ptr->getTime()) { + m_msgs_this_cycle = 0; // first msg this cycle + m_time_last_time_enqueue = g_eventQueue_ptr->getTime(); + } + m_msgs_this_cycle++; + + // ASSERT(m_max_size == -1 || m_size <= m_max_size + 1); + // the plus one is a kluge because of a SLICC issue + + if (!m_ordering_set) { + WARN_EXPR(*this); + WARN_EXPR(m_name); + ERROR_MSG("Ordering property of this queue has not been set"); + } + + // Calculate the arrival time of the message, that is, the first + // cycle the message can be dequeued. + assert(delta>0); + Time current_time = g_eventQueue_ptr->getTime(); + Time arrival_time = 0; + if (!RANDOMIZATION || (m_randomization == false)) { + // No randomization + arrival_time = current_time + delta; + + } else { + // Randomization - ignore delta + if (m_strict_fifo) { + if (m_last_arrival_time < current_time) { + m_last_arrival_time = current_time; + } + arrival_time = m_last_arrival_time + random_time(); + } else { + arrival_time = current_time + random_time(); + } + } + + // Check the arrival time + assert(arrival_time > current_time); + if (m_strict_fifo) { + if (arrival_time >= m_last_arrival_time) { + + } else { + WARN_EXPR(*this); + WARN_EXPR(m_name); + WARN_EXPR(current_time); + WARN_EXPR(delta); + WARN_EXPR(arrival_time); + WARN_EXPR(m_last_arrival_time); + ERROR_MSG("FIFO ordering violated"); + } + } + m_last_arrival_time = arrival_time; + + // compute the delay cycles and set enqueue time + Message* msg_ptr = NULL; + msg_ptr = message.mod_ref(); + assert(msg_ptr != NULL); + assert(g_eventQueue_ptr->getTime() >= msg_ptr->getLastEnqueueTime()); // ensure we aren't dequeued early + msg_ptr->setDelayedCycles((g_eventQueue_ptr->getTime() - msg_ptr->getLastEnqueueTime())+msg_ptr->getDelayedCycles()); + msg_ptr->setLastEnqueueTime(arrival_time); + + // Insert the message into the priority heap + MessageBufferNode thisNode(arrival_time, m_msg_counter, message); + m_prio_heap.insert(thisNode); + + DEBUG_NEWLINE(QUEUE_COMP,HighPrio); + DEBUG_MSG(QUEUE_COMP,HighPrio,"enqueue " + m_name + + " with arrival_time " + int_to_string(arrival_time) + + " cur_time: " + int_to_string(g_eventQueue_ptr->getTime()) + "."); + DEBUG_EXPR(QUEUE_COMP,MedPrio,message); + DEBUG_NEWLINE(QUEUE_COMP,HighPrio); + + // Schedule the wakeup + if (m_consumer_ptr != NULL) { + g_eventQueue_ptr->scheduleEventAbsolute(m_consumer_ptr, arrival_time); + } else { + WARN_EXPR(*this); + WARN_EXPR(m_name); + ERROR_MSG("No consumer"); + } +} + +int MessageBuffer::dequeue_getDelayCycles(MsgPtr& message) +{ + int delay_cycles = -1; // null value + + dequeue(message); + + // get the delay cycles + delay_cycles = setAndReturnDelayCycles(message); + + assert(delay_cycles >= 0); + return delay_cycles; +} + +void MessageBuffer::dequeue(MsgPtr& message) +{ + DEBUG_MSG(QUEUE_COMP,MedPrio,"dequeue from " + m_name); + message = m_prio_heap.peekMin().m_msgptr; + + pop(); + DEBUG_EXPR(QUEUE_COMP,MedPrio,message); +} + +int MessageBuffer::dequeue_getDelayCycles() +{ + int delay_cycles = -1; // null value + + // get MsgPtr of the message about to be dequeued + MsgPtr message = m_prio_heap.peekMin().m_msgptr; + + // get the delay cycles + delay_cycles = setAndReturnDelayCycles(message); + + dequeue(); + + assert(delay_cycles >= 0); + return delay_cycles; +} + +void MessageBuffer::pop() +{ + DEBUG_MSG(QUEUE_COMP,MedPrio,"pop from " + m_name); + assert(isReady()); + Time ready_time = m_prio_heap.extractMin().m_time; + // record previous size and time so the current buffer size isn't adjusted until next cycle + if (m_time_last_time_pop < g_eventQueue_ptr->getTime()) { + m_size_at_cycle_start = m_size; + m_time_last_time_pop = g_eventQueue_ptr->getTime(); + } + m_size--; +} + +void MessageBuffer::clear() +{ + while(m_prio_heap.size() > 0){ + m_prio_heap.extractMin(); + } + + ASSERT(m_prio_heap.size() == 0); + + m_msg_counter = 0; + m_size = 0; + m_time_last_time_enqueue = 0; + m_time_last_time_pop = 0; + m_size_at_cycle_start = 0; + m_msgs_this_cycle = 0; +} + +void MessageBuffer::recycle() +{ + // const int RECYCLE_LATENCY = 3; + DEBUG_MSG(QUEUE_COMP,MedPrio,"recycling " + m_name); + assert(isReady()); + MessageBufferNode node = m_prio_heap.extractMin(); + node.m_time = g_eventQueue_ptr->getTime() + RECYCLE_LATENCY; + m_prio_heap.insert(node); + g_eventQueue_ptr->scheduleEventAbsolute(m_consumer_ptr, g_eventQueue_ptr->getTime() + RECYCLE_LATENCY); +} + +int MessageBuffer::setAndReturnDelayCycles(MsgPtr& message) +{ + int delay_cycles = -1; // null value + + // get the delay cycles of the message at the top of the queue + Message* msg_ptr = message.ref(); + + // this function should only be called on dequeue + // ensure the msg hasn't been enqueued + assert(msg_ptr->getLastEnqueueTime() <= g_eventQueue_ptr->getTime()); + msg_ptr->setDelayedCycles((g_eventQueue_ptr->getTime() - msg_ptr->getLastEnqueueTime())+msg_ptr->getDelayedCycles()); + delay_cycles = msg_ptr->getDelayedCycles(); + + assert(delay_cycles >= 0); + return delay_cycles; +} + +void MessageBuffer::print(ostream& out) const +{ + out << "[MessageBuffer: "; + if (m_consumer_ptr != NULL) { + out << " consumer-yes "; + } + out << m_prio_heap << "] " << m_name << endl; +} + +void MessageBuffer::printStats(ostream& out) +{ + out << "MessageBuffer: " << m_name << " stats - msgs:" << m_msg_counter << " full:" << m_not_avail_count << endl; +} + diff --git a/src/mem/ruby/buffers/MessageBuffer.hh b/src/mem/ruby/buffers/MessageBuffer.hh new file mode 100644 index 000000000..6851423c3 --- /dev/null +++ b/src/mem/ruby/buffers/MessageBuffer.hh @@ -0,0 +1,156 @@ + +/* + * Copyright (c) 1999-2008 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. + */ + +/* + * $Id$ + * + * Description: Unordered buffer of messages that can be inserted such + * that they can be dequeued after a given delta time has expired. + * + */ + +#ifndef MESSAGEBUFFER_H +#define MESSAGEBUFFER_H + +#include "Global.hh" +#include "MessageBufferNode.hh" +#include "Consumer.hh" +#include "EventQueue.hh" +#include "Message.hh" +#include "PrioHeap.hh" +#include "util.hh" + +class Chip; + +class MessageBuffer { +public: + // Constructors + MessageBuffer(); + MessageBuffer(const Chip* chip_ptr); // The chip_ptr is ignored, but could be used for extra debugging + + // Use Default Destructor + // ~MessageBuffer() + + // Public Methods + + static void printConfig(ostream& out) {} + + // TRUE if head of queue timestamp <= SystemTime + bool isReady() const { + return ((m_prio_heap.size() > 0) && + (m_prio_heap.peekMin().m_time <= g_eventQueue_ptr->getTime())); + } + + bool areNSlotsAvailable(int n); + int getPriority() { return m_priority_rank; } + void setPriority(int rank) { m_priority_rank = rank; } + void setConsumer(Consumer* consumer_ptr) { ASSERT(m_consumer_ptr==NULL); m_consumer_ptr = consumer_ptr; } + void setDescription(const string& name) { m_name = name; } + string getDescription() { return m_name;} + + Consumer* getConsumer() { return m_consumer_ptr; } + + const Message* peekAtHeadOfQueue() const; + const Message* peek() const { return peekAtHeadOfQueue(); } + const MsgPtr getMsgPtrCopy() const; + const MsgPtr& peekMsgPtr() const { assert(isReady()); return m_prio_heap.peekMin().m_msgptr; } + const MsgPtr& peekMsgPtrEvenIfNotReady() const {return m_prio_heap.peekMin().m_msgptr; } + + void enqueue(const MsgPtr& message) { enqueue(message, 1); } + void enqueue(const MsgPtr& message, Time delta); + // void enqueueAbsolute(const MsgPtr& message, Time absolute_time); + int dequeue_getDelayCycles(MsgPtr& message); // returns delay cycles of the message + void dequeue(MsgPtr& message); + int dequeue_getDelayCycles(); // returns delay cycles of the message + void dequeue() { pop(); } + void pop(); + void recycle(); + bool isEmpty() const { return m_prio_heap.size() == 0; } + + void setOrdering(bool order) { m_strict_fifo = order; m_ordering_set = true; } + void setSize(int size) {m_max_size = size;} + int getSize(); + void setRandomization(bool random_flag) { m_randomization = random_flag; } + + void clear(); + + void print(ostream& out) const; + void printStats(ostream& out); + void clearStats() { m_not_avail_count = 0; m_msg_counter = 0; } + +private: + // Private Methods + int setAndReturnDelayCycles(MsgPtr& message); + + // Private copy constructor and assignment operator + MessageBuffer(const MessageBuffer& obj); + MessageBuffer& operator=(const MessageBuffer& obj); + + // Data Members (m_ prefix) + Consumer* m_consumer_ptr; // Consumer to signal a wakeup(), can be NULL + PrioHeap<MessageBufferNode> m_prio_heap; + string m_name; + + int m_max_size; + int m_size; + + Time m_time_last_time_size_checked; + int m_size_last_time_size_checked; + + // variables used so enqueues appear to happen imediately, while pop happen the next cycle + Time m_time_last_time_enqueue; + Time m_time_last_time_pop; + int m_size_at_cycle_start; + int m_msgs_this_cycle; + + int m_not_avail_count; // count the # of times I didn't have N slots available + int m_msg_counter; + int m_priority_rank; + bool m_strict_fifo; + bool m_ordering_set; + bool m_randomization; + Time m_last_arrival_time; +}; + +// Output operator declaration +//template <class TYPE> +ostream& operator<<(ostream& out, const MessageBuffer& obj); + +// ******************* Definitions ******************* + +// Output operator definition +extern inline +ostream& operator<<(ostream& out, const MessageBuffer& obj) +{ + obj.print(out); + out << flush; + return out; +} + +#endif //MESSAGEBUFFER_H diff --git a/src/mem/ruby/buffers/MessageBufferNode.cc b/src/mem/ruby/buffers/MessageBufferNode.cc new file mode 100644 index 000000000..c84347a38 --- /dev/null +++ b/src/mem/ruby/buffers/MessageBufferNode.cc @@ -0,0 +1,48 @@ + +/* + * Copyright (c) 1999-2008 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. + */ + +/* + * EventQueueNode.C + * + * Description: See EventQueueNode.h + * + * $Id: MessageBufferNode.C,v 3.1 2001/02/02 16:57:54 sorin Exp $ + * + */ + +#include "MessageBufferNode.hh" + +void MessageBufferNode::print(ostream& out) const +{ + out << "["; + out << m_time << ", "; + out << m_msg_counter << ", "; + out << m_msgptr << "; "; + out << "]"; +} diff --git a/src/mem/ruby/buffers/MessageBufferNode.hh b/src/mem/ruby/buffers/MessageBufferNode.hh new file mode 100644 index 000000000..c562c45eb --- /dev/null +++ b/src/mem/ruby/buffers/MessageBufferNode.hh @@ -0,0 +1,88 @@ + +/* + * Copyright (c) 1999-2008 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. + */ + +#ifndef MESSAGEBUFFERNODE_H +#define MESSAGEBUFFERNODE_H + +#include "Global.hh" +#include "Message.hh" + +class MessageBufferNode { +public: + // Constructors + MessageBufferNode() { m_time = 0; m_msg_counter = 0; } + MessageBufferNode(const Time& time, int counter, const MsgPtr& msgptr) + { m_time = time; m_msgptr = msgptr; m_msg_counter = counter; } + // Destructor + //~MessageBufferNode(); + + // Public Methods + void print(ostream& out) const; +private: + // Private Methods + + // Default copy constructor and assignment operator + // MessageBufferNode(const MessageBufferNode& obj); + // MessageBufferNode& operator=(const MessageBufferNode& obj); + + // Data Members (m_ prefix) +public: + Time m_time; + int m_msg_counter; // FIXME, should this be a 64-bit value? + MsgPtr m_msgptr; +}; + +// Output operator declaration +ostream& operator<<(ostream& out, const MessageBufferNode& obj); + +// ******************* Definitions ******************* + +inline extern bool node_less_then_eq(const MessageBufferNode& n1, const MessageBufferNode& n2); + +inline extern +bool node_less_then_eq(const MessageBufferNode& n1, const MessageBufferNode& n2) +{ + if (n1.m_time == n2.m_time) { + assert(n1.m_msg_counter != n2.m_msg_counter); + return (n1.m_msg_counter <= n2.m_msg_counter); + } else { + return (n1.m_time <= n2.m_time); + } +} + +// Output operator definition +extern inline +ostream& operator<<(ostream& out, const MessageBufferNode& obj) +{ + obj.print(out); + out << flush; + return out; +} + +#endif //MESSAGEBUFFERNODE_H |