Project

General

Profile

Statistics
| Branch: | Revision:

root / src / sim / cdefaultlist.cc @ 3e29b8a0

History | View | Annotate | Download (6.06 KB)

1
//=========================================================================
2
//  CDEFAULTLIST.CC - part of
3
//
4
//                  OMNeT++/OMNEST
5
//           Discrete System Simulation in C++
6
//
7
//   Member functions of
8
//    cDefaultList : stores a set of cOwnedObjects
9
//
10
//  Author: Andras Varga
11
//
12
//=========================================================================
13

    
14
/*--------------------------------------------------------------*
15
  Copyright (C) 1992-2008 Andras Varga
16
  Copyright (C) 2006-2008 OpenSim Ltd.
17

18
  This file is distributed WITHOUT ANY WARRANTY. See the file
19
  `license' for details on this and other legal matters.
20
*--------------------------------------------------------------*/
21

    
22
#include <string.h>  // memcpy
23
#include "globals.h"
24
#include "carray.h"
25
#include "cexception.h"
26
#include "cdefaultlist.h"
27
#include "csimulation.h"
28
#include "cmessageheap.h"
29
#include "cenvir.h"
30
#include "cwatch.h"
31
#include "cthreadpool.h"
32

    
33
#ifdef WITH_PARSIM
34
#include "ccommbuffer.h"
35
#endif
36

    
37
NAMESPACE_BEGIN
38

    
39

    
40
Register_Class(cDefaultList);
41

    
42

    
43
cDefaultList::cDefaultList(const char *name) : cNoncopyableOwnedObject(name)
44
{
45
    // careful: if we are a global variable (ctor called before main()),
46
    // then insert() may get called before constructor and it invoked
47
    // construct() already.
48
    if (cStaticFlag::isSet() || capacity==0)
49
        construct();
50

    
51
    // if we're invoked before main, then we are a global variable (dynamic
52
    // instances of cDefaultList are not supposed to be created
53
    // before main()) --> remove ourselves from ownership tree because
54
    // we shouldn't be destroyed via operator delete
55
    if (!cStaticFlag::isSet())
56
        removeFromOwnershipTree();
57
}
58

    
59
void cDefaultList::construct()
60
{
61
    capacity = 2;
62
    size = 0;
63
    vect = new cOwnedObject *[capacity];
64
    for (int i=0; i<capacity; i++)
65
        vect[i] = NULL;
66
}
67

    
68
cDefaultList::~cDefaultList()
69
{
70
    if (getPerformFinalGC())
71
    {
72
        // delete all owned objects. One place we make use of this is behavior is
73
        // when a simple module gets deleted -- there we have to delete all dynamically
74
        // allocated objects held by the module. But: deletion has dangers,
75
        // i.e. if we try to delete objects embedded in other objects/structs or
76
        // arrays, it will crash mysteriously to the user -- so consider not deleting.
77
        while (size>0)
78
            delete vect[0];
79
        delete [] vect;
80
    }
81
    else
82
    {
83
        // experimental: do not delete objects (except cWatches), just print their names
84
        for (int i=0; i<size; i++)
85
        {
86
            if (dynamic_cast<cWatchBase *>(vect[i]))
87
                delete vect[i--]; // "i--" used because delete will move last item to position i
88
            else
89
                ev.undisposedObject(vect[i]);
90
        }
91

    
92
        // we can free up the pointer array itself though
93
        delete [] vect;
94
    }
95
}
96

    
97
void cDefaultList::doInsert(cOwnedObject *obj)
98
{
99
#ifdef ENABLE_OWNERSHIP
100
    ASSERT(obj!=this || this==&defaultList);
101

    
102
    if (size>=capacity)
103
    {
104
        if (capacity==0)
105
        {
106
            // this is if we're invoked before main, before our ctor run
107
            construct();
108
        }
109
        else
110
        {
111
            // must allocate bigger vector (grow 25% but at least 2)
112
            capacity += (capacity<8) ? 2 : (capacity>>2);
113
            cOwnedObject **v = new cOwnedObject *[capacity];
114
            memcpy(v, vect, sizeof(cOwnedObject*)*size);
115
            delete [] vect;
116
            vect = v;
117
        }
118
    }
119

    
120
    obj->ownerp = this;
121
    vect[obj->pos = size++] = obj;
122
#else
123
    obj->ownerp = this;
124
#endif
125
}
126

    
127
void cDefaultList::ownedObjectDeleted(cOwnedObject *obj)
128
{
129
    ASSERT(obj && obj->ownerp==this);
130
#ifdef ENABLE_OWNERSHIP
131
    // move last object to obj's old position
132
    int pos = obj->pos;
133
    (vect[pos] = vect[--size])->pos = pos;
134
#endif
135
}
136

    
137
void cDefaultList::yieldOwnership(cOwnedObject *obj, cObject *newowner)
138
{
139
#ifdef ENABLE_OWNERSHIP
140
    ASSERT(obj && obj->ownerp==this && size>0);
141

    
142
    // give object to its new owner
143
    obj->ownerp = newowner;
144

    
145
    // move last object to obj's old position
146
    int pos = obj->pos;
147
    (vect[pos] = vect[--size])->pos = pos;
148
#else
149
    ASSERT(obj && obj->ownerp==this);
150
    obj->ownerp = newowner;
151
#endif
152
}
153

    
154
void cDefaultList::takeAllObjectsFrom(cDefaultList& other)
155
{
156
    while (other.defaultListSize()>0)
157
        take(other.defaultListGet(0));
158
}
159

    
160
std::string cDefaultList::info() const
161
{
162
    std::stringstream out;
163
    out << "n=" << size;
164
    return out.str();
165
}
166

    
167
void cDefaultList::forEachChild(cVisitor *v)
168
{
169
    for (int i=0; i<size; i++)
170
        v->visit(vect[i]);
171
}
172

    
173
void cDefaultList::parsimPack(cCommBuffer *buffer)
174
{
175
#ifndef WITH_PARSIM
176
    throw cRuntimeError(this,eNOPARSIM);
177
#else
178
    cOwnedObject::parsimPack(buffer);
179

    
180
    if (size>0)
181
        throw cRuntimeError(this, "parsimPack() not supported (makes no sense)");
182
#endif
183
}
184

    
185
void cDefaultList::parsimUnpack(cCommBuffer *buffer)
186
{
187
#ifndef WITH_PARSIM
188
    throw cRuntimeError(this,eNOPARSIM);
189
#else
190
    cOwnedObject::parsimUnpack(buffer);
191
    if (size>0)
192
        throw cRuntimeError(this, "parsimUnpack(): can only unpack into empty object");
193
#endif
194
}
195

    
196
void cDefaultList::take(cOwnedObject *obj)
197
{
198
#ifdef ENABLE_OWNERSHIP
199
    // ask current owner to release it -- if it's a cDefaultList, it will.
200
    obj->ownerp->yieldOwnership(obj, this);
201
    doInsert(obj);
202
#else
203
    obj->ownerp = this;
204
#endif
205
}
206

    
207
void cDefaultList::drop(cOwnedObject *obj)
208
{
209
#ifdef ENABLE_OWNERSHIP
210
    if (obj->ownerp!=this)
211
        throw cRuntimeError(this,"drop(): not owner of object (%s)%s",
212
                                obj->getClassName(), obj->getFullPath().c_str());
213
    // the following 2 lines are actually the same as defaultOwner->take(obj);
214
    yieldOwnership(obj, cThreadPool::getDefaultOwner());
215
    cThreadPool::getDefaultOwner()->doInsert(obj);
216
#else
217
    obj->ownerp = cThreadPool::getDefaultOwner();
218
#endif
219
}
220

    
221
cOwnedObject *cDefaultList::defaultListGet(int k)
222
{
223
    if (k<0 || k>=size)
224
        return NULL;
225
    return vect[k];
226
}
227

    
228
bool cDefaultList::defaultListContains(cOwnedObject *obj) const
229
{
230
    return obj && obj->getOwner()==const_cast<cDefaultList *>(this);
231
}
232

    
233
NAMESPACE_END