A Discrete-Event Network Simulator
API
heap-scheduler.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2006 INRIA
3  * Copyright (c) 2005 Mathieu Lacage
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
19  *
20  */
21 
22 #include "heap-scheduler.h"
23 
24 #include "assert.h"
25 #include "event-impl.h"
26 #include "log.h"
27 
34 namespace ns3
35 {
36 
37 NS_LOG_COMPONENT_DEFINE("HeapScheduler");
38 
39 NS_OBJECT_ENSURE_REGISTERED(HeapScheduler);
40 
41 TypeId
43 {
44  static TypeId tid = TypeId("ns3::HeapScheduler")
46  .SetGroupName("Core")
47  .AddConstructor<HeapScheduler>();
48  return tid;
49 }
50 
52 {
53  NS_LOG_FUNCTION(this);
54  // we purposely waste an item at the start of
55  // the array to make sure the indexes in the
56  // array start at one.
57  Scheduler::Event empty = {nullptr, {0, 0}};
58  m_heap.push_back(empty);
59 }
60 
62 {
63  NS_LOG_FUNCTION(this);
64 }
65 
66 std::size_t
67 HeapScheduler::Parent(std::size_t id) const
68 {
69  NS_LOG_FUNCTION(this << id);
70  return id / 2;
71 }
72 
73 std::size_t
74 HeapScheduler::Sibling(std::size_t id) const
75 {
76  NS_LOG_FUNCTION(this << id);
77  return id + 1;
78 }
79 
80 std::size_t
81 HeapScheduler::LeftChild(std::size_t id) const
82 {
83  NS_LOG_FUNCTION(this << id);
84  return id * 2;
85 }
86 
87 std::size_t
88 HeapScheduler::RightChild(std::size_t id) const
89 {
90  NS_LOG_FUNCTION(this << id);
91  return id * 2 + 1;
92 }
93 
94 std::size_t
96 {
97  NS_LOG_FUNCTION(this);
98  return 1;
99 }
100 
101 bool
102 HeapScheduler::IsRoot(std::size_t id) const
103 {
104  NS_LOG_FUNCTION(this << id);
105  return (id == Root());
106 }
107 
108 std::size_t
110 {
111  NS_LOG_FUNCTION(this);
112  return m_heap.size() - 1;
113 }
114 
115 bool
116 HeapScheduler::IsBottom(std::size_t id) const
117 {
118  NS_LOG_FUNCTION(this << id);
119  return (id >= m_heap.size());
120 }
121 
122 void
123 HeapScheduler::Exch(std::size_t a, std::size_t b)
124 {
125  NS_LOG_FUNCTION(this << a << b);
126  NS_ASSERT(b < m_heap.size() && a < m_heap.size());
127  NS_LOG_DEBUG("Exch " << a << ", " << b);
128  Event tmp(m_heap[a]);
129  m_heap[a] = m_heap[b];
130  m_heap[b] = tmp;
131 }
132 
133 bool
134 HeapScheduler::IsLessStrictly(std::size_t a, std::size_t b) const
135 {
136  NS_LOG_FUNCTION(this << a << b);
137  return m_heap[a] < m_heap[b];
138 }
139 
140 std::size_t
141 HeapScheduler::Smallest(std::size_t a, std::size_t b) const
142 {
143  NS_LOG_FUNCTION(this << a << b);
144  return IsLessStrictly(a, b) ? a : b;
145 }
146 
147 bool
149 {
150  NS_LOG_FUNCTION(this);
151  return (m_heap.size() == 1);
152 }
153 
154 void
156 {
157  NS_LOG_FUNCTION(this);
158  std::size_t index = Last();
159  while (!IsRoot(index) && IsLessStrictly(index, Parent(index)))
160  {
161  Exch(index, Parent(index));
162  index = Parent(index);
163  }
164 }
165 
166 void
168 {
169  NS_LOG_FUNCTION(this << start);
170  std::size_t index = start;
171  std::size_t right = RightChild(index);
172  while (!IsBottom(right))
173  {
174  std::size_t left = LeftChild(index);
175  std::size_t tmp = Smallest(left, right);
176  if (IsLessStrictly(index, tmp))
177  {
178  return;
179  }
180  Exch(index, tmp);
181  index = tmp;
182  right = RightChild(index);
183  }
184  if (IsBottom(index))
185  {
186  return;
187  }
188  NS_ASSERT(!IsBottom(index));
189  std::size_t left = LeftChild(index);
190  if (IsBottom(left))
191  {
192  return;
193  }
194  if (IsLessStrictly(index, left))
195  {
196  return;
197  }
198  Exch(index, left);
199 }
200 
201 void
203 {
204  NS_LOG_FUNCTION(this << &ev);
205  m_heap.push_back(ev);
206  BottomUp();
207 }
208 
211 {
212  NS_LOG_FUNCTION(this);
213  return m_heap[Root()];
214 }
215 
218 {
219  NS_LOG_FUNCTION(this);
220  Event next = m_heap[Root()];
221  Exch(Root(), Last());
222  m_heap.pop_back();
223  TopDown(Root());
224  return next;
225 }
226 
227 void
229 {
230  NS_LOG_FUNCTION(this << &ev);
231  std::size_t uid = ev.key.m_uid;
232  for (std::size_t i = 1; i < m_heap.size(); i++)
233  {
234  if (uid == m_heap[i].key.m_uid)
235  {
236  NS_ASSERT(m_heap[i].impl == ev.impl);
237  Exch(i, Last());
238  m_heap.pop_back();
239  TopDown(i);
240  return;
241  }
242  }
243  NS_ASSERT(false);
244 }
245 
246 } // namespace ns3
NS_ASSERT() and NS_ASSERT_MSG() macro definitions.
a binary heap event scheduler
std::size_t Root() const
Get the root index of the heap.
void TopDown(std::size_t start)
Percolate a deletion bubble down the heap.
void Insert(const Scheduler::Event &ev) override
Insert a new Event in the schedule.
~HeapScheduler() override
Destructor.
static TypeId GetTypeId()
Register this type.
Scheduler::Event RemoveNext() override
Remove the earliest event from the event list.
bool IsLessStrictly(std::size_t a, std::size_t b) const
Compare (less than) two items.
HeapScheduler()
Constructor.
std::size_t RightChild(std::size_t id) const
Get the right child index of a given entry.
BinaryHeap m_heap
The event list.
bool IsRoot(std::size_t id) const
Test if an index is the root.
Scheduler::Event PeekNext() const override
Get a pointer to the next event.
void Remove(const Scheduler::Event &ev) override
Remove a specific event from the event list.
void Exch(std::size_t a, std::size_t b)
Swap two items.
std::size_t Smallest(std::size_t a, std::size_t b) const
Minimum of two items.
std::size_t Sibling(std::size_t id) const
Get the next sibling of a given entry.
std::size_t Parent(std::size_t id) const
Get the parent index of a given entry.
bool IsBottom(std::size_t id) const
Test if an index is at the bottom of the heap.
std::size_t LeftChild(std::size_t id) const
Get the left child of a given entry.
void BottomUp()
Percolate a newly inserted Last item to its proper position.
std::size_t Last() const
Return the index of the last element.
bool IsEmpty() const override
Test if the schedule is empty.
Maintain the event list.
Definition: scheduler.h:157
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:931
ns3::EventImpl declarations.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:66
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:268
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:46
ns3::HeapScheduler declaration.
Debug message logging.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Scheduler event.
Definition: scheduler.h:184
EventKey key
Key for sorting and ordering Events.
Definition: scheduler.h:186
EventImpl * impl
Pointer to the event implementation.
Definition: scheduler.h:185
uint32_t m_uid
Event unique id.
Definition: scheduler.h:172