A Discrete-Event Network Simulator
Home
Tutorials ▼
English
Portuguese
Docs ▼
Wiki
Manual
Models
Develop ▼
API
Bugs
API
Main Page
Related Pages
Modules
Namespaces
Classes
Files
File List
File Members
All
Classes
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Properties
Friends
Macros
Groups
Pages
calendar-scheduler.cc
Go to the documentation of this file.
1
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2
/*
3
* Copyright (c) 2009 INRIA
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
#include "
calendar-scheduler.h
"
22
#include "
event-impl.h
"
23
#include <utility>
24
#include <string>
25
#include <list>
26
#include "
assert.h
"
27
#include "
log.h
"
28
29
namespace
ns3 {
30
31
NS_LOG_COMPONENT_DEFINE
(
"CalendarScheduler"
);
32
33
NS_OBJECT_ENSURE_REGISTERED
(CalendarScheduler);
34
35
TypeId
36
CalendarScheduler::GetTypeId
(
void
)
37
{
38
static
TypeId
tid =
TypeId
(
"ns3::CalendarScheduler"
)
39
.
SetParent
<
Scheduler
> ()
40
.AddConstructor<CalendarScheduler> ()
41
;
42
return
tid;
43
}
44
45
CalendarScheduler::CalendarScheduler
()
46
{
47
NS_LOG_FUNCTION
(
this
);
48
Init
(2, 1, 0);
49
m_qSize
= 0;
50
}
51
CalendarScheduler::~CalendarScheduler
()
52
{
53
NS_LOG_FUNCTION
(
this
);
54
delete
[]
m_buckets
;
55
m_buckets
= 0;
56
}
57
void
58
CalendarScheduler::Init
(uint32_t nBuckets,
59
uint64_t width,
60
uint64_t startPrio)
61
{
62
NS_LOG_FUNCTION
(
this
<< nBuckets << width << startPrio);
63
m_buckets
=
new
Bucket
[nBuckets];
64
m_nBuckets
= nBuckets;
65
m_width
= width;
66
m_lastPrio
= startPrio;
67
m_lastBucket
=
Hash
(startPrio);
68
m_bucketTop
= (startPrio / width + 1) * width;
69
}
70
void
71
CalendarScheduler::PrintInfo
(
void
)
72
{
73
std::cout <<
"nBuckets="
<<
m_nBuckets
<<
", width="
<<
m_width
<< std::endl;
74
std::cout <<
"Bucket Distribution "
;
75
for
(uint32_t i = 0; i <
m_nBuckets
; i++)
76
{
77
std::cout <<
m_buckets
[i].size () <<
" "
;
78
}
79
std::cout << std::endl;
80
}
81
uint32_t
82
CalendarScheduler::Hash
(uint64_t ts)
const
83
{
84
uint32_t bucket = (ts /
m_width
) %
m_nBuckets
;
85
return
bucket;
86
}
87
88
void
89
CalendarScheduler::DoInsert
(
const
Event
&ev)
90
{
91
NS_LOG_FUNCTION
(
this
<< ev.
key
.
m_ts
<< ev.
key
.
m_uid
);
92
// calculate bucket index.
93
uint32_t bucket =
Hash
(ev.
key
.
m_ts
);
94
NS_LOG_LOGIC
(
"insert in bucket="
<< bucket);
95
96
// insert in bucket list.
97
Bucket::iterator end =
m_buckets
[bucket].end ();
98
for
(Bucket::iterator i =
m_buckets
[bucket].begin (); i != end; ++i)
99
{
100
if
(ev.
key
< i->key)
101
{
102
m_buckets
[bucket].insert (i, ev);
103
return
;
104
}
105
}
106
m_buckets
[bucket].push_back (ev);
107
}
108
109
void
110
CalendarScheduler::Insert
(
const
Event
&ev)
111
{
112
DoInsert
(ev);
113
m_qSize
++;
114
ResizeUp
();
115
}
116
bool
117
CalendarScheduler::IsEmpty
(
void
)
const
118
{
119
return
m_qSize
== 0;
120
}
121
Scheduler::Event
122
CalendarScheduler::PeekNext
(
void
)
const
123
{
124
NS_LOG_FUNCTION
(
this
<<
m_lastBucket
<<
m_bucketTop
);
125
NS_ASSERT
(!
IsEmpty
());
126
uint32_t i =
m_lastBucket
;
127
uint64_t bucketTop =
m_bucketTop
;
128
Scheduler::Event
minEvent = {
static_cast<
uint64_t
>
(0), {
static_cast<
uint32_t
>
(~0), static_cast<uint32_t>(~0)}};
129
do
130
{
131
if
(!
m_buckets
[i].
empty
())
132
{
133
Scheduler::Event
next =
m_buckets
[i].front ();
134
if
(next.
key
.
m_ts
< bucketTop)
135
{
136
return
next;
137
}
138
if
(next.
key
< minEvent.
key
)
139
{
140
minEvent = next;
141
}
142
}
143
i++;
144
i %=
m_nBuckets
;
145
bucketTop +=
m_width
;
146
}
147
while
(i !=
m_lastBucket
);
148
149
return
minEvent;
150
}
151
152
Scheduler::Event
153
CalendarScheduler::DoRemoveNext
(
void
)
154
{
155
uint32_t i =
m_lastBucket
;
156
uint64_t bucketTop =
m_bucketTop
;
157
int32_t minBucket = -1;
158
Scheduler::EventKey
minKey;
159
NS_ASSERT
(!
IsEmpty
());
160
minKey.
m_ts
= uint64_t(-int64_t(1));
161
minKey.
m_uid
= 0;
162
minKey.
m_context
= 0xffffffff;
163
do
164
{
165
if
(!
m_buckets
[i].
empty
())
166
{
167
Scheduler::Event
next =
m_buckets
[i].front ();
168
if
(next.
key
.
m_ts
< bucketTop)
169
{
170
m_lastBucket
= i;
171
m_lastPrio
= next.
key
.
m_ts
;
172
m_bucketTop
= bucketTop;
173
m_buckets
[i].pop_front ();
174
return
next;
175
}
176
if
(next.
key
< minKey)
177
{
178
minKey = next.
key
;
179
minBucket = i;
180
}
181
}
182
i++;
183
i %=
m_nBuckets
;
184
bucketTop +=
m_width
;
185
}
186
while
(i !=
m_lastBucket
);
187
188
m_lastPrio
= minKey.
m_ts
;
189
m_lastBucket
=
Hash
(minKey.
m_ts
);
190
m_bucketTop
= (minKey.
m_ts
/
m_width
+ 1) *
m_width
;
191
Scheduler::Event
next =
m_buckets
[minBucket].front();
192
m_buckets
[minBucket].pop_front ();
193
194
return
next;
195
}
196
197
Scheduler::Event
198
CalendarScheduler::RemoveNext
(
void
)
199
{
200
NS_LOG_FUNCTION
(
this
<<
m_lastBucket
<<
m_bucketTop
);
201
NS_ASSERT
(!
IsEmpty
());
202
203
Scheduler::Event
ev =
DoRemoveNext
();
204
NS_LOG_LOGIC
(
"remove ts="
<< ev.
key
.
m_ts
<<
205
", key="
<< ev.
key
.
m_uid
<<
206
", from bucket="
<<
m_lastBucket
);
207
m_qSize
--;
208
ResizeDown
();
209
return
ev;
210
}
211
212
void
213
CalendarScheduler::Remove
(
const
Event
&ev)
214
{
215
NS_ASSERT
(!
IsEmpty
());
216
// bucket index of event
217
uint32_t bucket =
Hash
(ev.
key
.
m_ts
);
218
219
Bucket::iterator end =
m_buckets
[bucket].end ();
220
for
(Bucket::iterator i =
m_buckets
[bucket].begin (); i != end; ++i)
221
{
222
if
(i->key.m_uid == ev.
key
.
m_uid
)
223
{
224
NS_ASSERT
(ev.
impl
== i->impl);
225
m_buckets
[bucket].erase (i);
226
227
m_qSize
--;
228
ResizeDown
();
229
return
;
230
}
231
}
232
NS_ASSERT
(
false
);
233
}
234
235
void
236
CalendarScheduler::ResizeUp
(
void
)
237
{
238
if
(
m_qSize
>
m_nBuckets
* 2
239
&&
m_nBuckets
< 32768)
240
{
241
Resize
(
m_nBuckets
* 2);
242
}
243
}
244
void
245
CalendarScheduler::ResizeDown
(
void
)
246
{
247
if
(
m_qSize
<
m_nBuckets
/ 2)
248
{
249
Resize
(
m_nBuckets
/ 2);
250
}
251
}
252
253
uint32_t
254
CalendarScheduler::CalculateNewWidth
(
void
)
255
{
256
if
(
m_qSize
< 2)
257
{
258
return
1;
259
}
260
uint32_t nSamples;
261
if
(
m_qSize
<= 5)
262
{
263
nSamples =
m_qSize
;
264
}
265
else
266
{
267
nSamples = 5 +
m_qSize
/ 10;
268
}
269
if
(nSamples > 25)
270
{
271
nSamples = 25;
272
}
273
274
// we gather the first nSamples from the queue
275
std::list<Scheduler::Event> samples;
276
// save state
277
uint32_t lastBucket =
m_lastBucket
;
278
uint64_t bucketTop =
m_bucketTop
;
279
uint64_t lastPrio =
m_lastPrio
;
280
281
// gather requested events
282
for
(uint32_t i = 0; i < nSamples; i++)
283
{
284
samples.push_back (
DoRemoveNext
());
285
}
286
// put them back
287
for
(std::list<Scheduler::Event>::const_iterator i = samples.begin ();
288
i != samples.end (); ++i)
289
{
290
DoInsert
(*i);
291
}
292
293
// restore state.
294
m_lastBucket
= lastBucket;
295
m_bucketTop
= bucketTop;
296
m_lastPrio
= lastPrio;
297
298
// finally calculate inter-time average over samples.
299
uint64_t totalSeparation = 0;
300
std::list<Scheduler::Event>::const_iterator end = samples.end ();
301
std::list<Scheduler::Event>::const_iterator cur = samples.begin ();
302
std::list<Scheduler::Event>::const_iterator next = cur;
303
next++;
304
while
(next != end)
305
{
306
totalSeparation += next->key.m_ts - cur->key.m_ts;
307
cur++;
308
next++;
309
}
310
uint64_t twiceAvg = totalSeparation / (nSamples - 1) * 2;
311
totalSeparation = 0;
312
cur = samples.begin ();
313
next = cur;
314
next++;
315
while
(next != end)
316
{
317
uint64_t diff = next->key.m_ts - cur->key.m_ts;
318
if
(diff <= twiceAvg)
319
{
320
totalSeparation += diff;
321
}
322
cur++;
323
next++;
324
}
325
326
totalSeparation *= 3;
327
totalSeparation = std::max (totalSeparation, (uint64_t)1);
328
return
totalSeparation;
329
}
330
void
331
CalendarScheduler::DoResize
(uint32_t newSize, uint32_t newWidth)
332
{
333
Bucket
*oldBuckets =
m_buckets
;
334
uint32_t oldNBuckets =
m_nBuckets
;
335
Init
(newSize, newWidth,
m_lastPrio
);
336
337
for
(uint32_t i = 0; i < oldNBuckets; i++)
338
{
339
Bucket::iterator end = oldBuckets[i].end ();
340
for
(Bucket::iterator j = oldBuckets[i].begin (); j != end; ++j)
341
{
342
DoInsert
(*j);
343
}
344
}
345
delete
[] oldBuckets;
346
}
347
void
348
CalendarScheduler::Resize
(uint32_t newSize)
349
{
350
NS_LOG_FUNCTION
(
this
<< newSize);
351
352
// PrintInfo ();
353
uint32_t newWidth =
CalculateNewWidth
();
354
DoResize
(newSize, newWidth);
355
}
356
357
}
// namespace ns3
src
core
model
calendar-scheduler.cc
Generated on Tue Oct 9 2012 16:45:34 for ns-3 by
1.8.1.2