Statistics
| Branch: | Revision:

root / src / sim / cqueue.cc @ fbe00e73

History | View | Annotate | Download (7.43 KB)

1
//=========================================================================
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
}
360