Statistics
| Branch: | Revision:

root / src / sim / cqueue.cc @ fbe00e73

History | View | Annotate | Download (7.43 KB)

1 01873262 Georg Kunz
//=========================================================================
2
//  CQUEUE.CC - part of
3
//
4
//                  OMNeT++/OMNEST
5
//           Discrete System Simulation in C++
6
//
7
//   Member functions of
8
//    cQueue : queue of cObject descendants
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 <stdio.h>
23
#include <string.h>
24
#include <sstream>
25
#include "globals.h"
26
#include "cqueue.h"
27
#include "cexception.h"
28
29
#ifdef WITH_PARSIM
30
#include "ccommbuffer.h"
31
#endif
32
33
USING_NAMESPACE
34
35
using std::ostream;
36
37
38
Register_Class(cQueue);
39
40
41
cQueue::cQueue(const cQueue& queue) : cOwnedObject()
42
{
43
    frontp = backp = NULL;
44
    n = 0;
45
    setName( queue.getName() );
46
    operator=(queue);
47
}
48
49
cQueue::cQueue(const char *name, CompareFunc cmp) : cOwnedObject(name)
50
{
51
    tkownership = true;
52
    frontp = backp = NULL;
53
    n = 0;
54
    compare = cmp;
55
}
56
57
cQueue::~cQueue()
58
{
59
    clear();
60
}
61
62
std::string cQueue::info() const
63
{
64
    if (n==0)
65
        return std::string("empty");
66
    std::stringstream out;
67
    out << "length=" << n;
68
    return out.str();
69
}
70
71
void cQueue::forEachChild(cVisitor *v)
72
{
73
    // loop through elements
74
    for (QElem *p=frontp; p!=NULL; p=p->next)
75
         v->visit(p->obj);
76
}
77
78
void cQueue::parsimPack(cCommBuffer *buffer)
79
{
80
#ifndef WITH_PARSIM
81
    throw cRuntimeError(this,eNOPARSIM);
82
#else
83
    cOwnedObject::parsimPack(buffer);
84
85
    if (compare)
86
        throw cRuntimeError(this,"parsimPack(): cannot transmit comparison function");
87
88
    buffer->pack(n);
89
90
    for (cQueue::Iterator iter(*this, 0); !iter.end(); iter--)
91
    {
92
        if (iter()->isOwnedObject() && iter()->getOwner() != this)
93
            throw cRuntimeError(this,"parsimPack(): refusing to transmit an object not owned by the queue");
94
        buffer->packObject(iter());
95
    }
96
#endif
97
}
98
99
void cQueue::parsimUnpack(cCommBuffer *buffer)
100
{
101
#ifndef WITH_PARSIM
102
    throw cRuntimeError(this,eNOPARSIM);
103
#else
104
    cOwnedObject::parsimUnpack(buffer);
105
106
    buffer->unpack(n);
107
108
    for (int i=0; i<n; i++)
109
    {
110
        cObject *obj = buffer->unpackObject();
111
        insert(obj);
112
    }
113
#endif
114
}
115
116
void cQueue::clear()
117
{
118
    while (frontp)
119
    {
120
        QElem *tmp = frontp->next;
121
        cObject *obj = frontp->obj;
122
        if (!obj->isOwnedObject())
123
            delete obj;
124
        else if (obj->getOwner()==this)
125
            dropAndDelete(static_cast<cOwnedObject *>(obj));
126
        delete frontp;
127
        frontp = tmp;
128
    }
129
    backp = NULL;
130
    n = 0;
131
}
132
133
cQueue& cQueue::operator=(const cQueue& queue)
134
{
135
    if (this==&queue) return *this;
136
137
    clear();
138
139
    cOwnedObject::operator=(queue);
140
    tkownership = queue.tkownership;
141
    compare = queue.compare;
142
143
    bool old_tk = getTakeOwnership();
144
    for (cQueue::Iterator iter(queue, false); !iter.end(); iter++)
145
    {
146
        cObject *obj = iter();
147
        if (!obj->isOwnedObject())
148
            {insert(obj->dup());}
149
        else if (iter()->getOwner()==const_cast<cQueue*>(&queue))
150
            {setTakeOwnership(true); insert(obj->dup());}
151
        else
152
            {setTakeOwnership(false); insert(obj);}
153
    }
154
    setTakeOwnership(old_tk);
155
    return *this;
156
}
157
158
void cQueue::setup(CompareFunc cmp)
159
{
160
    compare=cmp;
161
}
162
163
cQueue::QElem *cQueue::find_qelem(cObject *obj) const
164
{
165
    QElem *p = frontp;
166
    while (p && p->obj!=obj)
167
        p = p->next;
168
    return p;
169
}
170
171
cQueue::QElem *cQueue::find_qelemByName(const char *name) const
172
{
173
    QElem *p = frontp;
174
    while( p && (strcmp(p->obj->getName(), name) != 0) )
175
        p = p->next;
176
    return p;
177
}
178
179
void cQueue::insbefore_qelem(QElem *p, cObject *obj)
180
{
181
    QElem *e = new QElem;
182
    e->obj = obj;
183
184
    e->prev = p->prev;
185
    e->next = p;
186
    p->prev = e;
187
    if (e->prev)
188
        e->prev->next = e;
189
    else
190
        frontp = e;
191
    n++;
192
}
193
194
void cQueue::insafter_qelem(QElem *p, cObject *obj)
195
{
196
    QElem *e = new QElem;
197
    e->obj = obj;
198
199
    e->next = p->next;
200
    e->prev = p;
201
    p->next = e;
202
    if (e->next)
203
        e->next->prev = e;
204
    else
205
        backp = e;
206
    n++;
207
}
208
209
cObject *cQueue::remove_qelem(QElem *p)
210
{
211
    if (p->next)
212
        p->next->prev = p->prev;
213
    else
214
        backp = p->prev;
215
    if (p->prev)
216
        p->prev->next = p->next;
217
    else
218
        frontp = p->next;
219
220
    cObject *retobj = p->obj;
221
    delete p;
222
    n--;
223
    if (retobj->isOwnedObject() && retobj->getOwner()==this)
224
        drop(static_cast<cOwnedObject *>(retobj));
225
    return retobj;
226
}
227
228
229
void cQueue::insert(cObject *obj)
230
{
231
    if (!obj)
232
        throw cRuntimeError(this, "cannot insert NULL pointer");
233
234
    if (obj->isOwnedObject() && getTakeOwnership())
235
        take(static_cast<cOwnedObject *>(obj));
236
237
    if (!backp)
238
    {
239
        // insert as the only item
240
        QElem *e = new QElem;
241
        e->obj = obj;
242
        e->next = e->prev = NULL;
243
        frontp = backp = e;
244
        n = 1;
245
    }
246
    else if (compare==NULL)
247
    {
248
        insafter_qelem(backp, obj);
249
    }
250
    else
251
    {
252
        // priority queue: seek insertion place
253
        QElem *p = backp;
254
        while (p && compare(obj, p->obj) < 0)
255
            p = p->prev;
256
        if (p)
257
            insafter_qelem(p, obj);
258
        else
259
            insbefore_qelem(frontp, obj);
260
    }
261
}
262
263
void cQueue::insertBefore(cObject *where, cObject *obj)
264
{
265
    if (!obj)
266
        throw cRuntimeError(this, "cannot insert NULL pointer");
267
268
    QElem *p = find_qelem(where);
269
    if (!p)
270
        throw cRuntimeError(this, "insertBefore(w,o): object w=`%s' not in the queue", where->getName());
271
272
    if (obj->isOwnedObject() && getTakeOwnership())
273
        take(static_cast<cOwnedObject *>(obj));
274
    insbefore_qelem(p,obj);
275
}
276
277
void cQueue::insertAfter(cObject *where, cObject *obj)
278
{
279
    if (!obj)
280
        throw cRuntimeError(this,"cannot insert NULL pointer");
281
282
    QElem *p = find_qelem(where);
283
    if (!p)
284
        throw cRuntimeError(this, "insertAfter(w,o): object w=`%s' not in the queue",where->getName());
285
286
    if (obj->isOwnedObject() && getTakeOwnership())
287
        take(static_cast<cOwnedObject *>(obj));
288
    insafter_qelem(p,obj);
289
}
290
291
cObject *cQueue::front() const
292
{
293
    return frontp ? frontp->obj : NULL;
294
}
295
296
cObject *cQueue::back() const
297
{
298
    return backp ? backp->obj : NULL;
299
}
300
301
cObject *cQueue::remove(cObject *obj)
302
{
303
    if (!obj)
304
        return NULL;
305
    //FIXME: handle special cases faster: if obj==front() or ==back(), don't invoke find_qelem()
306
    QElem *p = find_qelem(obj);
307
    if (!p)
308
        return NULL;
309
    return remove_qelem(p);
310
}
311
312
cObject* cQueue::removeByName(const char* name)
313
{
314
    if (!name)  return NULL;
315
316
    QElem *p = find_qelemByName(name);
317
    if (!p)
318
        return NULL;
319
    return remove_qelem(p);
320
}
321
322
cObject *cQueue::pop()
323
{
324
    if (!frontp)
325
        throw cRuntimeError(this,"pop(): queue empty");
326
327
    return remove_qelem(frontp);
328
}
329
330
int cQueue::getLength() const
331
{
332
    return n;
333
}
334
335
bool cQueue::contains(cObject *obj) const
336
{
337
    return find_qelem(obj)!=NULL;
338
}
339
340
cObject *cQueue::get(int i) const
341
{
342
    QElem *p = frontp;
343
    while (p!=NULL && i>0)
344
        p = p->next, i--;
345
    return p ? p->obj : NULL;
346
}
347
348
bool cQueue::containsByName(const char* name) const
349
{
350
    return find_qelemByName(name);
351
}
352
353
cObject* cQueue::findObjectByName(const char* name) const
354
{
355
    QElem *p = find_qelemByName(name);
356
    if (!p)
357
      return NULL;
358
    return p->obj;
359
}