File: | /tmp/asd-nat/home/nat/Work/ns-3-dev-git/build/../src/core/model/object.cc |
Location: | line 424, column 14 |
Description: | Attempt to delete released memory |
1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ | |||
2 | /* | |||
3 | * Copyright (c) 2007 INRIA, Gustavo Carneiro | |||
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 | * Authors: Gustavo Carneiro <gjcarneiro@gmail.com>, | |||
19 | * Mathieu Lacage <mathieu.lacage@sophia.inria.fr> | |||
20 | */ | |||
21 | ||||
22 | #include "object.h" | |||
23 | #include "object-factory.h" | |||
24 | #include "assert.h" | |||
25 | #include "attribute.h" | |||
26 | #include "log.h" | |||
27 | #include "string.h" | |||
28 | #include <vector> | |||
29 | #include <sstream> | |||
30 | #include <cstdlib> | |||
31 | #include <cstring> | |||
32 | ||||
33 | /** | |||
34 | * \file | |||
35 | * \ingroup object | |||
36 | * ns3::Object class implementation. | |||
37 | */ | |||
38 | ||||
39 | namespace ns3 { | |||
40 | ||||
41 | NS_LOG_COMPONENT_DEFINE ("Object")static ns3::LogComponent g_log = ns3::LogComponent ("Object", "../src/core/model/object.cc"); | |||
42 | ||||
43 | /********************************************************************* | |||
44 | * The Object implementation | |||
45 | *********************************************************************/ | |||
46 | ||||
47 | NS_OBJECT_ENSURE_REGISTERED (Object)static struct ObjectObjectRegistrationClass { ObjectObjectRegistrationClass () { ns3::TypeId tid = Object::GetTypeId (); tid.SetSize (sizeof (Object)); tid.GetParent (); } } ObjectObjectRegistrationVariable; | |||
48 | ||||
49 | Object::AggregateIterator::AggregateIterator () | |||
50 | : m_object (0), | |||
51 | m_current (0) | |||
52 | { | |||
53 | NS_LOG_FUNCTION (this)do { if (g_log.IsEnabled (ns3::LOG_FUNCTION)) { if (g_log.IsEnabled (ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3:: LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog ); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE )) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter (); if (printer != 0) { (*printer)(std::clog); std::clog << " "; } }; ; std::clog << g_log.Name () << ":" << __FUNCTION__ << "("; ns3::ParameterLogger (std::clog) << this; std::clog << ")" << std::endl; } } while ( false); | |||
54 | } | |||
55 | ||||
56 | bool | |||
57 | Object::AggregateIterator::HasNext (void) const | |||
58 | { | |||
59 | NS_LOG_FUNCTION (this)do { if (g_log.IsEnabled (ns3::LOG_FUNCTION)) { if (g_log.IsEnabled (ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3:: LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog ); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE )) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter (); if (printer != 0) { (*printer)(std::clog); std::clog << " "; } }; ; std::clog << g_log.Name () << ":" << __FUNCTION__ << "("; ns3::ParameterLogger (std::clog) << this; std::clog << ")" << std::endl; } } while ( false); | |||
60 | return m_current < m_object->m_aggregates->n; | |||
61 | } | |||
62 | Ptr<const Object> | |||
63 | Object::AggregateIterator::Next (void) | |||
64 | { | |||
65 | NS_LOG_FUNCTION (this)do { if (g_log.IsEnabled (ns3::LOG_FUNCTION)) { if (g_log.IsEnabled (ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3:: LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog ); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE )) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter (); if (printer != 0) { (*printer)(std::clog); std::clog << " "; } }; ; std::clog << g_log.Name () << ":" << __FUNCTION__ << "("; ns3::ParameterLogger (std::clog) << this; std::clog << ")" << std::endl; } } while ( false); | |||
66 | Object *object = m_object->m_aggregates->buffer[m_current]; | |||
67 | m_current++; | |||
68 | return object; | |||
69 | } | |||
70 | Object::AggregateIterator::AggregateIterator (Ptr<const Object> object) | |||
71 | : m_object (object), | |||
72 | m_current (0) | |||
73 | { | |||
74 | NS_LOG_FUNCTION (this << object)do { if (g_log.IsEnabled (ns3::LOG_FUNCTION)) { if (g_log.IsEnabled (ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3:: LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog ); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE )) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter (); if (printer != 0) { (*printer)(std::clog); std::clog << " "; } }; ; std::clog << g_log.Name () << ":" << __FUNCTION__ << "("; ns3::ParameterLogger (std::clog) << this << object; std::clog << ")" << std::endl ; } } while (false); | |||
75 | } | |||
76 | ||||
77 | ||||
78 | TypeId | |||
79 | Object::GetInstanceTypeId (void) const | |||
80 | { | |||
81 | NS_LOG_FUNCTION (this)do { if (g_log.IsEnabled (ns3::LOG_FUNCTION)) { if (g_log.IsEnabled (ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3:: LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog ); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE )) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter (); if (printer != 0) { (*printer)(std::clog); std::clog << " "; } }; ; std::clog << g_log.Name () << ":" << __FUNCTION__ << "("; ns3::ParameterLogger (std::clog) << this; std::clog << ")" << std::endl; } } while ( false); | |||
82 | return m_tid; | |||
83 | } | |||
84 | ||||
85 | TypeId | |||
86 | Object::GetTypeId (void) | |||
87 | { | |||
88 | static TypeId tid = TypeId ("ns3::Object") | |||
89 | .SetParent<ObjectBase> () | |||
90 | .SetGroupName ("Core") | |||
91 | ; | |||
92 | return tid; | |||
93 | } | |||
94 | ||||
95 | ||||
96 | Object::Object () | |||
97 | : m_tid (Object::GetTypeId ()), | |||
98 | m_disposed (false), | |||
99 | m_initialized (false), | |||
100 | m_aggregates ((struct Aggregates *) std::malloc (sizeof (struct Aggregates))), | |||
101 | m_getObjectCount (0) | |||
102 | { | |||
103 | NS_LOG_FUNCTION (this)do { if (g_log.IsEnabled (ns3::LOG_FUNCTION)) { if (g_log.IsEnabled (ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3:: LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog ); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE )) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter (); if (printer != 0) { (*printer)(std::clog); std::clog << " "; } }; ; std::clog << g_log.Name () << ":" << __FUNCTION__ << "("; ns3::ParameterLogger (std::clog) << this; std::clog << ")" << std::endl; } } while ( false); | |||
104 | m_aggregates->n = 1; | |||
105 | m_aggregates->buffer[0] = this; | |||
106 | } | |||
107 | Object::~Object () | |||
108 | { | |||
109 | // remove this object from the aggregate list | |||
110 | NS_LOG_FUNCTION (this)do { if (g_log.IsEnabled (ns3::LOG_FUNCTION)) { if (g_log.IsEnabled (ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3:: LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog ); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE )) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter (); if (printer != 0) { (*printer)(std::clog); std::clog << " "; } }; ; std::clog << g_log.Name () << ":" << __FUNCTION__ << "("; ns3::ParameterLogger (std::clog) << this; std::clog << ")" << std::endl; } } while ( false); | |||
111 | uint32_t n = m_aggregates->n; | |||
112 | for (uint32_t i = 0; i < n; i++) | |||
113 | { | |||
114 | Object *current = m_aggregates->buffer[i]; | |||
115 | if (current == this) | |||
116 | { | |||
117 | std::memmove (&m_aggregates->buffer[i], | |||
118 | &m_aggregates->buffer[i+1], | |||
119 | sizeof (Object *)*(m_aggregates->n - (i+1))); | |||
120 | m_aggregates->n--; | |||
121 | } | |||
122 | } | |||
123 | // finally, if all objects have been removed from the list, | |||
124 | // delete the aggregate list | |||
125 | if (m_aggregates->n == 0) | |||
126 | { | |||
127 | std::free (m_aggregates); | |||
128 | } | |||
129 | m_aggregates = 0; | |||
130 | } | |||
131 | Object::Object (const Object &o) | |||
132 | : m_tid (o.m_tid), | |||
133 | m_disposed (false), | |||
134 | m_initialized (false), | |||
135 | m_aggregates ((struct Aggregates *) std::malloc (sizeof (struct Aggregates))), | |||
136 | m_getObjectCount (0) | |||
137 | { | |||
138 | m_aggregates->n = 1; | |||
139 | m_aggregates->buffer[0] = this; | |||
140 | } | |||
141 | void | |||
142 | Object::Construct (const AttributeConstructionList &attributes) | |||
143 | { | |||
144 | NS_LOG_FUNCTION (this << &attributes)do { if (g_log.IsEnabled (ns3::LOG_FUNCTION)) { if (g_log.IsEnabled (ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3:: LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog ); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE )) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter (); if (printer != 0) { (*printer)(std::clog); std::clog << " "; } }; ; std::clog << g_log.Name () << ":" << __FUNCTION__ << "("; ns3::ParameterLogger (std::clog) << this << &attributes; std::clog << ")" << std::endl; } } while (false); | |||
145 | ConstructSelf (attributes); | |||
146 | } | |||
147 | ||||
148 | Ptr<Object> | |||
149 | Object::DoGetObject (TypeId tid) const | |||
150 | { | |||
151 | NS_LOG_FUNCTION (this << tid)do { if (g_log.IsEnabled (ns3::LOG_FUNCTION)) { if (g_log.IsEnabled (ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3:: LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog ); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE )) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter (); if (printer != 0) { (*printer)(std::clog); std::clog << " "; } }; ; std::clog << g_log.Name () << ":" << __FUNCTION__ << "("; ns3::ParameterLogger (std::clog) << this << tid; std::clog << ")" << std::endl ; } } while (false); | |||
152 | NS_ASSERT (CheckLoose ())do { if (!(CheckLoose ())) { std::cerr << "assert failed. cond=\"" << "CheckLoose ()" << "\", "; do { std::cerr << "file=" << "../src/core/model/object.cc" << ", line=" << 152 << std::endl; ::ns3::FatalImpl::FlushStreams (); if (true) std::terminate (); } while (false); } } while ( false); | |||
153 | ||||
154 | uint32_t n = m_aggregates->n; | |||
155 | TypeId objectTid = Object::GetTypeId (); | |||
156 | for (uint32_t i = 0; i < n; i++) | |||
157 | { | |||
158 | Object *current = m_aggregates->buffer[i]; | |||
159 | TypeId cur = current->GetInstanceTypeId (); | |||
160 | while (cur != tid && cur != objectTid) | |||
161 | { | |||
162 | cur = cur.GetParent (); | |||
163 | } | |||
164 | if (cur == tid) | |||
165 | { | |||
166 | // This is an attempt to 'cache' the result of this lookup. | |||
167 | // the idea is that if we perform a lookup for a TypeId on this object, | |||
168 | // we are likely to perform the same lookup later so, we make sure | |||
169 | // that the aggregate array is sorted by the number of accesses | |||
170 | // to each object. | |||
171 | ||||
172 | // first, increment the access count | |||
173 | current->m_getObjectCount++; | |||
174 | // then, update the sort | |||
175 | UpdateSortedArray (m_aggregates, i); | |||
176 | // finally, return the match | |||
177 | return const_cast<Object *> (current); | |||
178 | } | |||
179 | } | |||
180 | return 0; | |||
181 | } | |||
182 | void | |||
183 | Object::Initialize (void) | |||
184 | { | |||
185 | /** | |||
186 | * Note: the code here is a bit tricky because we need to protect ourselves from | |||
187 | * modifications in the aggregate array while DoInitialize is called. The user's | |||
188 | * implementation of the DoInitialize method could call GetObject (which could | |||
189 | * reorder the array) and it could call AggregateObject which would add an | |||
190 | * object at the end of the array. To be safe, we restart iteration over the | |||
191 | * array whenever we call some user code, just in case. | |||
192 | */ | |||
193 | NS_LOG_FUNCTION (this)do { if (g_log.IsEnabled (ns3::LOG_FUNCTION)) { if (g_log.IsEnabled (ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3:: LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog ); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE )) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter (); if (printer != 0) { (*printer)(std::clog); std::clog << " "; } }; ; std::clog << g_log.Name () << ":" << __FUNCTION__ << "("; ns3::ParameterLogger (std::clog) << this; std::clog << ")" << std::endl; } } while ( false); | |||
194 | restart: | |||
195 | uint32_t n = m_aggregates->n; | |||
196 | for (uint32_t i = 0; i < n; i++) | |||
197 | { | |||
198 | Object *current = m_aggregates->buffer[i]; | |||
199 | if (!current->m_initialized) | |||
200 | { | |||
201 | current->DoInitialize (); | |||
202 | current->m_initialized = true; | |||
203 | goto restart; | |||
204 | } | |||
205 | } | |||
206 | } | |||
207 | bool | |||
208 | Object::IsInitialized (void) const | |||
209 | { | |||
210 | NS_LOG_FUNCTION (this)do { if (g_log.IsEnabled (ns3::LOG_FUNCTION)) { if (g_log.IsEnabled (ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3:: LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog ); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE )) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter (); if (printer != 0) { (*printer)(std::clog); std::clog << " "; } }; ; std::clog << g_log.Name () << ":" << __FUNCTION__ << "("; ns3::ParameterLogger (std::clog) << this; std::clog << ")" << std::endl; } } while ( false); | |||
211 | return m_initialized; | |||
212 | } | |||
213 | void | |||
214 | Object::Dispose (void) | |||
215 | { | |||
216 | /** | |||
217 | * Note: the code here is a bit tricky because we need to protect ourselves from | |||
218 | * modifications in the aggregate array while DoDispose is called. The user's | |||
219 | * DoDispose implementation could call GetObject (which could reorder the array) | |||
220 | * and it could call AggregateObject which would add an object at the end of the array. | |||
221 | * So, to be safe, we restart the iteration over the array whenever we call some | |||
222 | * user code. | |||
223 | */ | |||
224 | NS_LOG_FUNCTION (this)do { if (g_log.IsEnabled (ns3::LOG_FUNCTION)) { if (g_log.IsEnabled (ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3:: LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog ); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE )) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter (); if (printer != 0) { (*printer)(std::clog); std::clog << " "; } }; ; std::clog << g_log.Name () << ":" << __FUNCTION__ << "("; ns3::ParameterLogger (std::clog) << this; std::clog << ")" << std::endl; } } while ( false); | |||
225 | restart: | |||
226 | uint32_t n = m_aggregates->n; | |||
227 | for (uint32_t i = 0; i < n; i++) | |||
228 | { | |||
229 | Object *current = m_aggregates->buffer[i]; | |||
230 | if (!current->m_disposed) | |||
231 | { | |||
232 | current->DoDispose (); | |||
233 | current->m_disposed = true; | |||
234 | goto restart; | |||
235 | } | |||
236 | } | |||
237 | } | |||
238 | void | |||
239 | Object::UpdateSortedArray (struct Aggregates *aggregates, uint32_t j) const | |||
240 | { | |||
241 | NS_LOG_FUNCTION (this << aggregates << j)do { if (g_log.IsEnabled (ns3::LOG_FUNCTION)) { if (g_log.IsEnabled (ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3:: LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog ); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE )) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter (); if (printer != 0) { (*printer)(std::clog); std::clog << " "; } }; ; std::clog << g_log.Name () << ":" << __FUNCTION__ << "("; ns3::ParameterLogger (std::clog) << this << aggregates << j; std::clog << ")" << std::endl; } } while (false); | |||
242 | while (j > 0 && | |||
243 | aggregates->buffer[j]->m_getObjectCount > aggregates->buffer[j-1]->m_getObjectCount) | |||
244 | { | |||
245 | Object *tmp = aggregates->buffer[j-1]; | |||
246 | aggregates->buffer[j-1] = aggregates->buffer[j]; | |||
247 | aggregates->buffer[j] = tmp; | |||
248 | j--; | |||
249 | } | |||
250 | } | |||
251 | void | |||
252 | Object::AggregateObject (Ptr<Object> o) | |||
253 | { | |||
254 | NS_LOG_FUNCTION (this << o)do { if (g_log.IsEnabled (ns3::LOG_FUNCTION)) { if (g_log.IsEnabled (ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3:: LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog ); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE )) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter (); if (printer != 0) { (*printer)(std::clog); std::clog << " "; } }; ; std::clog << g_log.Name () << ":" << __FUNCTION__ << "("; ns3::ParameterLogger (std::clog) << this << o; std::clog << ")" << std::endl; } } while (false); | |||
255 | NS_ASSERT (!m_disposed)do { if (!(!m_disposed)) { std::cerr << "assert failed. cond=\"" << "!m_disposed" << "\", "; do { std::cerr << "file=" << "../src/core/model/object.cc" << ", line=" << 255 << std::endl; ::ns3::FatalImpl::FlushStreams (); if (true) std::terminate (); } while (false); } } while ( false); | |||
256 | NS_ASSERT (!o->m_disposed)do { if (!(!o->m_disposed)) { std::cerr << "assert failed. cond=\"" << "!o->m_disposed" << "\", "; do { std::cerr << "file=" << "../src/core/model/object.cc" << ", line=" << 256 << std::endl; ::ns3::FatalImpl:: FlushStreams (); if (true) std::terminate (); } while (false) ; } } while (false); | |||
257 | NS_ASSERT (CheckLoose ())do { if (!(CheckLoose ())) { std::cerr << "assert failed. cond=\"" << "CheckLoose ()" << "\", "; do { std::cerr << "file=" << "../src/core/model/object.cc" << ", line=" << 257 << std::endl; ::ns3::FatalImpl::FlushStreams (); if (true) std::terminate (); } while (false); } } while ( false); | |||
258 | NS_ASSERT (o->CheckLoose ())do { if (!(o->CheckLoose ())) { std::cerr << "assert failed. cond=\"" << "o->CheckLoose ()" << "\", "; do { std::cerr << "file=" << "../src/core/model/object.cc" << ", line=" << 258 << std::endl; ::ns3::FatalImpl:: FlushStreams (); if (true) std::terminate (); } while (false) ; } } while (false); | |||
259 | ||||
260 | Object *other = PeekPointer (o); | |||
261 | // first create the new aggregate buffer. | |||
262 | uint32_t total = m_aggregates->n + other->m_aggregates->n; | |||
263 | struct Aggregates *aggregates = | |||
264 | (struct Aggregates *)std::malloc (sizeof(struct Aggregates)+(total-1)*sizeof(Object*)); | |||
265 | aggregates->n = total; | |||
266 | ||||
267 | // copy our buffer to the new buffer | |||
268 | std::memcpy (&aggregates->buffer[0], | |||
269 | &m_aggregates->buffer[0], | |||
270 | m_aggregates->n*sizeof(Object*)); | |||
271 | ||||
272 | // append the other buffer into the new buffer too | |||
273 | for (uint32_t i = 0; i < other->m_aggregates->n; i++) | |||
274 | { | |||
275 | aggregates->buffer[m_aggregates->n+i] = other->m_aggregates->buffer[i]; | |||
276 | const TypeId typeId = other->m_aggregates->buffer[i]->GetInstanceTypeId (); | |||
277 | if (DoGetObject (typeId)) | |||
278 | { | |||
279 | NS_FATAL_ERROR ("Object::AggregateObject(): "do { std::cerr << "msg=\"" << "Object::AggregateObject(): " "Multiple aggregation of objects of type " << other-> GetInstanceTypeId () << " on objects of type " << typeId << "\", "; do { std::cerr << "file=" << "../src/core/model/object.cc" << ", line=" << 282 << std::endl; ::ns3::FatalImpl::FlushStreams (); if (true ) std::terminate (); } while (false); } while (false) | |||
280 | "Multiple aggregation of objects of type " <<do { std::cerr << "msg=\"" << "Object::AggregateObject(): " "Multiple aggregation of objects of type " << other-> GetInstanceTypeId () << " on objects of type " << typeId << "\", "; do { std::cerr << "file=" << "../src/core/model/object.cc" << ", line=" << 282 << std::endl; ::ns3::FatalImpl::FlushStreams (); if (true ) std::terminate (); } while (false); } while (false) | |||
281 | other->GetInstanceTypeId () <<do { std::cerr << "msg=\"" << "Object::AggregateObject(): " "Multiple aggregation of objects of type " << other-> GetInstanceTypeId () << " on objects of type " << typeId << "\", "; do { std::cerr << "file=" << "../src/core/model/object.cc" << ", line=" << 282 << std::endl; ::ns3::FatalImpl::FlushStreams (); if (true ) std::terminate (); } while (false); } while (false) | |||
282 | " on objects of type " << typeId)do { std::cerr << "msg=\"" << "Object::AggregateObject(): " "Multiple aggregation of objects of type " << other-> GetInstanceTypeId () << " on objects of type " << typeId << "\", "; do { std::cerr << "file=" << "../src/core/model/object.cc" << ", line=" << 282 << std::endl; ::ns3::FatalImpl::FlushStreams (); if (true ) std::terminate (); } while (false); } while (false); | |||
283 | } | |||
284 | UpdateSortedArray (aggregates, m_aggregates->n + i); | |||
285 | } | |||
286 | ||||
287 | // keep track of the old aggregate buffers for the iteration | |||
288 | // of NotifyNewAggregates | |||
289 | struct Aggregates *a = m_aggregates; | |||
290 | struct Aggregates *b = other->m_aggregates; | |||
291 | ||||
292 | // Then, assign the new aggregation buffer to every object | |||
293 | uint32_t n = aggregates->n; | |||
294 | for (uint32_t i = 0; i < n; i++) | |||
295 | { | |||
296 | Object *current = aggregates->buffer[i]; | |||
297 | current->m_aggregates = aggregates; | |||
298 | } | |||
299 | ||||
300 | // Finally, call NotifyNewAggregate on all the objects aggregates together. | |||
301 | // We purposedly use the old aggregate buffers to iterate over the objects | |||
302 | // because this allows us to assume that they will not change from under | |||
303 | // our feet, even if our users call AggregateObject from within their | |||
304 | // NotifyNewAggregate method. | |||
305 | for (uint32_t i = 0; i < a->n; i++) | |||
306 | { | |||
307 | Object *current = a->buffer[i]; | |||
308 | current->NotifyNewAggregate (); | |||
309 | } | |||
310 | for (uint32_t i = 0; i < b->n; i++) | |||
311 | { | |||
312 | Object *current = b->buffer[i]; | |||
313 | current->NotifyNewAggregate (); | |||
314 | } | |||
315 | ||||
316 | // Now that we are done with them, we can free our old aggregate buffers | |||
317 | std::free (a); | |||
318 | std::free (b); | |||
319 | } | |||
320 | /** | |||
321 | * This function must be implemented in the stack that needs to notify | |||
322 | * other stacks connected to the node of their presence in the node. | |||
323 | */ | |||
324 | void | |||
325 | Object::NotifyNewAggregate () | |||
326 | { | |||
327 | NS_LOG_FUNCTION (this)do { if (g_log.IsEnabled (ns3::LOG_FUNCTION)) { if (g_log.IsEnabled (ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3:: LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog ); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE )) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter (); if (printer != 0) { (*printer)(std::clog); std::clog << " "; } }; ; std::clog << g_log.Name () << ":" << __FUNCTION__ << "("; ns3::ParameterLogger (std::clog) << this; std::clog << ")" << std::endl; } } while ( false); | |||
328 | } | |||
329 | ||||
330 | Object::AggregateIterator | |||
331 | Object::GetAggregateIterator (void) const | |||
332 | { | |||
333 | NS_LOG_FUNCTION (this)do { if (g_log.IsEnabled (ns3::LOG_FUNCTION)) { if (g_log.IsEnabled (ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3:: LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog ); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE )) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter (); if (printer != 0) { (*printer)(std::clog); std::clog << " "; } }; ; std::clog << g_log.Name () << ":" << __FUNCTION__ << "("; ns3::ParameterLogger (std::clog) << this; std::clog << ")" << std::endl; } } while ( false); | |||
334 | return AggregateIterator (this); | |||
335 | } | |||
336 | ||||
337 | void | |||
338 | Object::SetTypeId (TypeId tid) | |||
339 | { | |||
340 | NS_LOG_FUNCTION (this << tid)do { if (g_log.IsEnabled (ns3::LOG_FUNCTION)) { if (g_log.IsEnabled (ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3:: LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog ); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE )) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter (); if (printer != 0) { (*printer)(std::clog); std::clog << " "; } }; ; std::clog << g_log.Name () << ":" << __FUNCTION__ << "("; ns3::ParameterLogger (std::clog) << this << tid; std::clog << ")" << std::endl ; } } while (false); | |||
341 | NS_ASSERT (Check ())do { if (!(Check ())) { std::cerr << "assert failed. cond=\"" << "Check ()" << "\", "; do { std::cerr << "file=" << "../src/core/model/object.cc" << ", line=" << 341 << std::endl; ::ns3::FatalImpl::FlushStreams (); if (true) std::terminate (); } while (false); } } while ( false); | |||
342 | m_tid = tid; | |||
343 | } | |||
344 | ||||
345 | void | |||
346 | Object::DoDispose (void) | |||
347 | { | |||
348 | NS_LOG_FUNCTION (this)do { if (g_log.IsEnabled (ns3::LOG_FUNCTION)) { if (g_log.IsEnabled (ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3:: LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog ); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE )) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter (); if (printer != 0) { (*printer)(std::clog); std::clog << " "; } }; ; std::clog << g_log.Name () << ":" << __FUNCTION__ << "("; ns3::ParameterLogger (std::clog) << this; std::clog << ")" << std::endl; } } while ( false); | |||
349 | NS_ASSERT (!m_disposed)do { if (!(!m_disposed)) { std::cerr << "assert failed. cond=\"" << "!m_disposed" << "\", "; do { std::cerr << "file=" << "../src/core/model/object.cc" << ", line=" << 349 << std::endl; ::ns3::FatalImpl::FlushStreams (); if (true) std::terminate (); } while (false); } } while ( false); | |||
350 | } | |||
351 | ||||
352 | void | |||
353 | Object::DoInitialize (void) | |||
354 | { | |||
355 | NS_LOG_FUNCTION (this)do { if (g_log.IsEnabled (ns3::LOG_FUNCTION)) { if (g_log.IsEnabled (ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3:: LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog ); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE )) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter (); if (printer != 0) { (*printer)(std::clog); std::clog << " "; } }; ; std::clog << g_log.Name () << ":" << __FUNCTION__ << "("; ns3::ParameterLogger (std::clog) << this; std::clog << ")" << std::endl; } } while ( false); | |||
356 | NS_ASSERT (!m_initialized)do { if (!(!m_initialized)) { std::cerr << "assert failed. cond=\"" << "!m_initialized" << "\", "; do { std::cerr << "file=" << "../src/core/model/object.cc" << ", line=" << 356 << std::endl; ::ns3::FatalImpl::FlushStreams (); if (true) std::terminate (); } while (false); } } while ( false); | |||
357 | } | |||
358 | ||||
359 | bool | |||
360 | Object::Check (void) const | |||
361 | { | |||
362 | NS_LOG_FUNCTION (this)do { if (g_log.IsEnabled (ns3::LOG_FUNCTION)) { if (g_log.IsEnabled (ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3:: LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog ); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE )) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter (); if (printer != 0) { (*printer)(std::clog); std::clog << " "; } }; ; std::clog << g_log.Name () << ":" << __FUNCTION__ << "("; ns3::ParameterLogger (std::clog) << this; std::clog << ")" << std::endl; } } while ( false); | |||
363 | return (GetReferenceCount () > 0); | |||
364 | } | |||
365 | ||||
366 | /* In some cases, when an event is scheduled against a subclass of | |||
367 | * Object, and if no one owns a reference directly to this object, the | |||
368 | * object is alive, has a refcount of zero and the method ran when the | |||
369 | * event expires runs against the raw pointer which means that we are | |||
370 | * manipulating an object with a refcount of zero. So, instead we | |||
371 | * check the aggregate reference count. | |||
372 | */ | |||
373 | bool | |||
374 | Object::CheckLoose (void) const | |||
375 | { | |||
376 | NS_LOG_FUNCTION (this)do { if (g_log.IsEnabled (ns3::LOG_FUNCTION)) { if (g_log.IsEnabled (ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3:: LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog ); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE )) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter (); if (printer != 0) { (*printer)(std::clog); std::clog << " "; } }; ; std::clog << g_log.Name () << ":" << __FUNCTION__ << "("; ns3::ParameterLogger (std::clog) << this; std::clog << ")" << std::endl; } } while ( false); | |||
377 | uint32_t refcount = 0; | |||
378 | uint32_t n = m_aggregates->n; | |||
379 | for (uint32_t i = 0; i < n; i++) | |||
380 | { | |||
381 | Object *current = m_aggregates->buffer[i]; | |||
382 | /// \todo Shortcircuit this loop. | |||
383 | refcount += current->GetReferenceCount (); | |||
384 | } | |||
385 | return (refcount > 0); | |||
386 | } | |||
387 | void | |||
388 | Object::DoDelete (void) | |||
389 | { | |||
390 | // check if we really need to die | |||
391 | NS_LOG_FUNCTION (this)do { if (g_log.IsEnabled (ns3::LOG_FUNCTION)) { if (g_log.IsEnabled (ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3:: LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog ); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE )) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter (); if (printer != 0) { (*printer)(std::clog); std::clog << " "; } }; ; std::clog << g_log.Name () << ":" << __FUNCTION__ << "("; ns3::ParameterLogger (std::clog) << this; std::clog << ")" << std::endl; } } while ( false); | |||
392 | for (uint32_t i = 0; i < m_aggregates->n; i++) | |||
| ||||
393 | { | |||
394 | Object *current = m_aggregates->buffer[i]; | |||
395 | if (current->GetReferenceCount () > 0) | |||
396 | { | |||
397 | return; | |||
398 | } | |||
399 | } | |||
400 | ||||
401 | // Now, we know that we are alone to use this aggregate so, | |||
402 | // we can dispose and delete everything safely. | |||
403 | ||||
404 | uint32_t n = m_aggregates->n; | |||
405 | // Ensure we are disposed. | |||
406 | for (uint32_t i = 0; i < n; i++) | |||
407 | { | |||
408 | Object *current = m_aggregates->buffer[i]; | |||
409 | if (!current->m_disposed) | |||
410 | { | |||
411 | current->DoDispose (); | |||
412 | } | |||
413 | } | |||
414 | ||||
415 | // Now, actually delete all objects | |||
416 | struct Aggregates *aggregates = m_aggregates; | |||
417 | for (uint32_t i = 0; i < n; i++) | |||
418 | { | |||
419 | // There is a trick here: each time we call delete below, | |||
420 | // the deleted object is removed from the aggregate buffer | |||
421 | // in the destructor so, the index of the next element to | |||
422 | // lookup is always zero | |||
423 | Object *current = aggregates->buffer[0]; | |||
424 | delete current; | |||
| ||||
425 | } | |||
426 | } | |||
427 | } // namespace ns3 | |||
428 |