Statistics
| Branch: | Revision:

root / include / cmessage.h @ 7f251033

History | View | Annotate | Download (34.1 KB)

1
//==========================================================================
2
//   CMESSAGE.H  -  header for
3
//                     OMNeT++/OMNEST
4
//            Discrete System Simulation in C++
5
//
6
//
7
//  Declaration of the following classes:
8
//    cMessage : message and event object
9
//
10
//==========================================================================
11

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

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

    
20
#ifndef __CMESSAGE_H
21
#define __CMESSAGE_H
22

    
23
#include "cownedobject.h"
24
#include "carray.h"
25
#include "cmsgpar.h"
26
#include "csimulation.h"
27

    
28
#ifdef ATOMIC_OPS_DEBUG
29
#include "catomicopsdebug.h"
30
#else
31
#include <atomic_ops.h>
32
#endif
33

    
34
#include <semaphore.h>
35

    
36
NAMESPACE_BEGIN
37

    
38
class cMsgPar;
39
class cGate;
40
class cChannel;
41
class cModule;
42
class cSimpleModule;
43
class cCompoundModule;
44
class cSimulation;
45
class cMessageHeap;
46
class cBarrierMessage;
47

    
48
/**
49
 * Predefined message kind values (values for cMessage's getKind(),
50
 * setKind() methods).
51
 *
52
 * Negative values are reserved for the \opp system and its
53
 * standard libraries. Zero and positive values can be freely used
54
 * by simulation models.
55
 */
56
enum eMessageKind
57
{
58
  MK_STARTER = -1,  /// Starter message. Used by scheduleStart().
59
  MK_TIMEOUT = -2,  /// Internal timeout message. Used by wait(), etc.
60
  MK_PACKET  = -3,  /// Obsolete
61
  MK_INFO    = -4,  /// Obsolete
62

    
63
  MK_PARSIM_BEGIN = -1000  /// values -1000...-2000 reserved for parallel simulation
64
};
65

    
66
/**
67
 * Maximum number of partitions for parallel simulation.
68
 *
69
 * @ingroup ParsimBrief
70
 * @ingroup Parsim
71
 */
72
// Note: it cannot go to cparsimcomm.h, without causing unwanted dependency on sim/parsim
73
#define MAX_PARSIM_PARTITIONS  32768 // srcprocid in cMessage
74

    
75

    
76
#ifdef WITHOUT_CPACKET
77
#undef cMessage
78
#endif
79

    
80
/**
81
 * The message class in \opp. cMessage objects may represent events,
82
 * messages, jobs or other entities in a simulation. To represent network
83
 * packets, use the cPacket subclass.
84
 *
85
 * Messages may be scheduled (to arrive back at the same module at a later
86
 * time), cancelled, sent out on a gate, or sent directly to another module;
87
 * all via methods of cSimpleModule.
88
 *
89
 * cMessage can be assigned a name (a property inherited from cNamedObject);
90
 * other attributes include message kind, priority, and time stamp.
91
 * Messages may be cloned with the dup() function. The control info field
92
 * facilitates modelling communication between protocol layers. The context
93
 * pointer field makes it easier to work with several timers (self-messages)
94
 * at a time. A message also stores information about its last sending,
95
 * including sending time, arrival time, arrival module and gate.
96
 *
97
 * Useful methods are isSelfMessage(), which tells apart self-messages from
98
 * messages received from other modules, and isScheduled(), which returns
99
 * whether a self-message is currently scheduled.
100
 *
101
 * Further fields can be added to cMessage via message declaration files (.msg)
102
 * which are translated into C++ classes. An example message declaration:
103
 *
104
 * \code
105
 * message Job
106
 * {
107
 *    fields:
108
 *        string label;
109
 *        int color = -1;
110
 * }
111
 * \endcode
112
 *
113
 * @see cSimpleModule, cQueue, cPacket
114
 *
115
 * @ingroup SimCore
116
 */
117
//XXX note: sizeof(cMessage) could be made a little smaller: the fields created, frommod, fromgate are rarely used by models (note: sendtime and tstamp *do* get used in practice)
118
class SIM_API cMessage : public cOwnedObject
119
{
120
    friend class cMessageHeap;
121
    friend class cTaskHeap;
122
    friend class cSimulation;
123
    friend class cThreadPool;
124

    
125
  private:
126
    static AO_t total_msgs;     // global variables for statistics
127
    static AO_t live_msgs;      // use atomic counters here
128
    // note: fields are in an order that maximizes packing (minimizes sizeof(cMessage))
129
    short msgkind;             // message kind -- 0>= user-defined meaning, <0 reserved
130
    short prior;               // priority -- used for scheduling msgs with equal times
131
    short srcprocid;           // reserved for use by parallel execution: id of source partition
132
    cArray *parlistp;          // ptr to list of parameters
133
    cObject *ctrlp;            // ptr to "control info"
134
    void *contextptr;          // a stored pointer -- user-defined meaning, used with self-messages
135

    
136
    int frommod, fromgate;     // source module and gate IDs -- set internally
137
    int tomod, togate;         // dest. module and gate IDs -- set internally
138
    simtime_t created;         // creation time -- set be constructor
139
    simtime_t sent,delivd;     // time of sending & delivery -- set internally
140
    simtime_t tstamp;          // time stamp -- user-defined meaning
141

    
142
    int heapindex;             // used by cMessageHeap (-1 if not on heap; all other values, including negative ones, means "on the heap")
143
    unsigned long insertordr;  // used by cMessageHeap
144

    
145
    eventnumber_t prev_event_num; // event number of the sending/scheduling this message
146

    
147
    long msgid;                // a unique message identifier assigned upon message creation
148
    long msgtreeid;            // a message identifier that is inherited by dup, if non dupped it is msgid
149

    
150
    static AO_t next_id;       // the next unique message identifier to be assigned upon message creation
151

    
152

    
153
  private:
154
    // internal: create parlist
155
    void _createparlist();
156

    
157
protected:
158
    cMessage *encapmsg;        // ptr to encapsulated msg
159

    
160
    //
161
    // Horizon
162
    //
163
    simtime_t duration;                 // (minimum) duration of the asynchronous event
164
    simtime_t t_start;                  //
165
    int taskindex;                      // used by cTaskHeap (-1 if not on heap)
166
    unsigned long taskinsertordr;       // used by cTaskHeap
167

    
168
    cBarrierMessage* barrierMsg;
169

    
170
  public:
171
    // internal: returns the event number which scheduled this event, or the event in which
172
    // this message was last delivered to a module. Stored for recording into the event log file.
173
    eventnumber_t getPreviousEventNumber() const {return prev_event_num;}
174

    
175
    // internal: sets previousEventNumber.
176
    void setPreviousEventNumber(eventnumber_t num) {prev_event_num = num;}
177

    
178
    // internal: used by cMessageHeap.
179
    unsigned long getInsertOrder() const {return insertordr;}
180

    
181
    // internal: called by the simulation kernel as part of the send(),
182
    // scheduleAt() calls to set the values returned by the
183
    // getSenderModuleId(), getSenderGate(), getSendingTime() methods.
184
    void setSentFrom(cModule *module, int gateId, simtime_t_cref t);
185

    
186
    // internal: called by the simulation kernel as part of processing
187
    // the send(), scheduleAt() calls to set the values returned
188
    // by the getArrivalModuleId(), getArrivalGate() methods.
189
    void setArrival(cModule *module, int gateId);
190

    
191
    // internal: called by the simulation kernel as part of processing
192
    // the send(), scheduleAt() calls to set the values returned
193
    // by the getArrivalModuleId(), getArrivalGate(), getArrivalTime() methods.
194
    void setArrival(cModule *module, int gate, simtime_t_cref t);
195

    
196
    // internal: called by the simulation kernel to set the value returned
197
    // by the getArrivalTime() method
198
    void setArrivalTime(simtime_t t);
199

    
200
    // internal: used by the parallel simulation kernel.
201
    void setSrcProcId(int procId) {srcprocid = (short)procId;}
202

    
203
    // internal: used by the parallel simulation kernel.
204
    int getSrcProcId() const {return srcprocid;}
205

    
206
    /** @name Horizon API. */
207
    //@{
208

    
209
    /**
210
     * Returns the duration of this event.
211
     */
212
    inline simtime_t getEventDuration() const   {return duration;}
213

    
214
    /**
215
     * Sets the duration of this event.
216
     */
217
    inline void setEventDuration(simtime_t t)  {duration = t;}
218

    
219
    /**
220
     * Returns the end of the duration interval.
221
     */
222
    inline simtime_t getTend() const  {return t_start + duration;}
223
    //@}
224

    
225
    /** @name Internal Horizon use only. */
226
    //@{
227

    
228
    /**
229
     * INTERNAL: store the t_start time. Used for internal state keeping.
230
     */
231
    inline void setTstart(simtime_t t)  {t_start = t;}
232

    
233
    /**
234
     * INTERNAL: get the t_start time. Used for internal state keeping.
235
     */
236
    inline simtime_t getTstart()        {return t_start;}
237

    
238
    /**
239
     * INTERNAL: used by cTaskHeap
240
     */
241
    inline unsigned long taskInsertOrder() const  {return taskinsertordr;}
242

    
243
    /**
244
     * INTERNAL:
245
     */
246
    void setBarrier(cBarrierMessage* barrier)  {this->barrierMsg = barrier;}
247

    
248
    /**
249
     * INTERNAL
250
     */
251
    cBarrierMessage* getBarrier()  {return barrierMsg;}
252
    //@}
253

    
254
public:
255
    /** @name Constructors, destructor, assignment */
256
    //@{
257

    
258
    /**
259
     * Copy constructor.
260
     */
261
    cMessage(const cMessage& msg);
262

    
263
    /**
264
     * Constructor.
265
     */
266
    explicit cMessage(const char *name=NULL, short kind=0);
267

    
268
    /**
269
     * Destructor.
270
     */
271
    virtual ~cMessage();
272

    
273
    /**
274
     * Assignment operator. Duplication and the assignment operator work all right with cMessage.
275
     * The name member is not copied; see cNamedObject's operator=() for more details.
276
     */
277
    cMessage& operator=(const cMessage& msg);
278
    //@}
279

    
280
    /**
281
     * Returns whether the current class is subclass of cPacket.
282
     * The cMessage implementation returns false.
283
     */
284
    virtual bool isPacket() const {return false;}
285

    
286
    /** @name Redefined cObject member functions. */
287
    //@{
288

    
289
    /**
290
     * Creates and returns an exact copy of this object.
291
     * See cObject for more details.
292
     */
293
    virtual cMessage *dup() const  {return new cMessage(*this);}
294

    
295
    /**
296
     * Produces a one-line description of the object's contents.
297
     * See cObject for more details.
298
     */
299
    virtual std::string info() const;
300

    
301
    /**
302
     * Produces a multi-line description of the object's contents.
303
     * See cObject for more details.
304
     */
305
    virtual std::string detailedInfo() const;
306

    
307
    /**
308
     * Calls v->visit(this) for each contained object.
309
     * See cObject for more details.
310
     */
311
    virtual void forEachChild(cVisitor *v);
312

    
313
    /**
314
     * Serializes the object into an MPI send buffer
315
     * Used by the simulation kernel for parallel execution.
316
     * See cObject for more details.
317
     */
318
    virtual void parsimPack(cCommBuffer *buffer);
319

    
320
    /**
321
     * Deserializes the object from an MPI receive buffer
322
     * Used by the simulation kernel for parallel execution.
323
     * See cObject for more details.
324
     */
325
    virtual void parsimUnpack(cCommBuffer *buffer);
326
    //@}
327

    
328
    /** @name Message attributes. */
329
    //@{
330

    
331
    /**
332
     * Sets the message kind. Nonnegative values can be freely used by
333
     * the user; negative values are reserved by OMNeT++ for internal
334
     * purposes.
335
     */
336
    void setKind(short k)  {msgkind=k;}
337

    
338
    /**
339
     * Sets event scheduling priority of the message. The priority member is
340
     * used when the simulator inserts messages into the future events set
341
     * (FES), to order messages with identical arrival time values.
342
     */
343
    void setSchedulingPriority(short p)  {prior=p;}
344

    
345
    /**
346
     * Sets the message's time stamp to the current simulation time.
347
     */
348
    void setTimestamp() {tstamp=simulation.getSimTime();}
349

    
350
    /**
351
     * Directly sets the message's time stamp.
352
     */
353
    void setTimestamp(simtime_t t) {tstamp=t;}
354

    
355
    /**
356
     * Sets the context pointer. This pointer may store an arbitrary value.
357
     * It is useful when managing several timers (self-messages): when
358
     * scheduling the message one can set the context pointer to the data
359
     * structure the timer corresponds to (e.g. the buffer whose timeout
360
     * the message represents), so that when the self-message arrives it is
361
     * easier to identify where it belongs.
362
     */
363
    void setContextPointer(void *p) {contextptr=p;}
364

    
365
    /**
366
     * Attaches a "control info" structure (object) to the message.
367
     * This is most useful when passing packets between protocol layers
368
     * of a protocol stack: e.g. when sending down an IP datagram to Ethernet,
369
     * the attached "control info" can contain the destination MAC address.
370
     *
371
     * The "control info" object will be deleted when the message is deleted.
372
     * Only one "control info" structure can be attached (the second
373
     * setControlInfo() call throws an error).
374
     *
375
     * When the message is duplicated or copied, copies will have their
376
     * control info set to NULL because the cObject interface
377
     * does not define dup/copy operations.
378
     * The assignment operator does not change control info.
379
     */
380
    void setControlInfo(cObject *p);
381

    
382
    /**
383
     * Removes the "control info" structure (object) from the message
384
     * and returns its pointer. Returns NULL if there was no control info
385
     * in the message
386
     */
387
    cObject *removeControlInfo();
388

    
389
    /**
390
     * Returns the message kind.
391
     */
392
    short getKind() const  {return msgkind;}
393

    
394
    /**
395
     * Returns the event scheduling priority.
396
     */
397
    short getSchedulingPriority() const  {return prior;}
398

    
399
    /**
400
     * Returns the message's time stamp.
401
     */
402
    simtime_t_cref getTimestamp() const {return tstamp;}
403

    
404
    /**
405
     * Returns the context pointer.
406
     */
407
    void *getContextPointer() const {return contextptr;}
408

    
409
    /**
410
     * Returns pointer to the attached "control info".
411
     */
412
    cObject *getControlInfo() const {return ctrlp;}
413
    //@}
414

    
415
    /** @name Dynamically attaching objects. */
416
    //@{
417

    
418
    /**
419
     * Returns reference to the 'object list' of the message: a cArray
420
     * which is used to store parameter (cMsgPar) objects and other objects
421
     * attached to the message.
422
     *
423
     * One can use either getParList() combined with cArray methods,
424
     * or several convenience methods (addPar(), addObject(), par(), etc.)
425
     * to add, retrieve or remove cMsgPars and other objects.
426
     *
427
     * <i>NOTE: using the object list has alternatives which may better
428
     * suit your needs. For more information, see class description for discussion
429
     * about message subclassing vs dynamically attached objects.</i>
430
     */
431
    virtual cArray& getParList()  {if (!parlistp) _createparlist(); return *parlistp;}
432

    
433
    /**
434
     * Add a new, empty parameter (cMsgPar object) with the given name
435
     * to the message's object list.
436
     *
437
     * <i>NOTE: This is a convenience function: one may use getParList() and
438
     * cArray::add() instead. See also class description for discussion about
439
     * message subclassing vs dynamically attached objects.</i>
440
     *
441
     * @see getParList()
442
     */
443
    virtual cMsgPar& addPar(const char *s)  {cMsgPar *p=new cMsgPar(s);getParList().add(p);return *p;}
444

    
445
    /**
446
     * Add a parameter object to the message's object list.
447
     *
448
     * <i>NOTE: This is a convenience function: one may use getParList() and
449
     * cArray::add() instead. See also class description for discussion about
450
     * message subclassing vs dynamically attached objects.</i>
451
     *
452
     * @see getParList()
453
     */
454
    virtual cMsgPar& addPar(cMsgPar *p)  {getParList().add(p); return *p;}
455

    
456
    /**
457
     * DEPRECATED! Use addPar(cMsgPar *p) instead.
458
     */
459
    _OPPDEPRECATED cMsgPar& addPar(cMsgPar& p)  {return addPar(&p);}
460

    
461
    /**
462
     * Returns the nth object in the message's object list, converting it to a cMsgPar.
463
     * If the object does not exist or it cannot be cast to cMsgPar (using dynamic_cast\<\>),
464
     * the method throws a cRuntimeError.
465
     *
466
     * <i>NOTE: This is a convenience function: one may use getParList() and
467
     * cArray::get() instead. See also class description for discussion about
468
     * message subclassing vs dynamically attached objects.</i>
469
     *
470
     * @see getParList()
471
     */
472
    virtual cMsgPar& par(int n);
473

    
474
    /**
475
     * Returns the object with the given name in the message's object list,
476
     * converting it to a cMsgPar.
477
     * If the object does not exist or it cannot be cast to cMsgPar (using dynamic_cast\<\>),
478
     * the method throws a cRuntimeError.
479
     *
480
     * <i>NOTE: This is a convenience function: one may use getParList() and
481
     * cArray::get() instead. See also class description for discussion about
482
     * message subclassing vs dynamically attached objects.</i>
483
     *
484
     * @see getParList()
485
     */
486
    virtual cMsgPar& par(const char *s);
487

    
488
    /**
489
     * Returns the index of the parameter with the given name in the message's
490
     * object list, or -1 if it could not be found.
491
     *
492
     * <i>NOTE: This is a convenience function: one may use getParList() and
493
     * cArray::find() instead. See also class description for discussion about
494
     * message subclassing vs dynamically attached objects.</i>
495
     *
496
     * @see getParList()
497
     */
498
    virtual int findPar(const char *s) const;
499

    
500
    /**
501
     * Check if a parameter with the given name exists in the message's
502
     * object list.
503
     *
504
     * <i>NOTE: This is a convenience function: one may use getParList() and
505
     * cArray::exist() instead. See also class description for discussion about
506
     * message subclassing vs dynamically attached objects.</i>
507
     *
508
     * @see getParList()
509
     */
510
    virtual bool hasPar(const char *s) const {return findPar(s)>=0;}
511

    
512
    /**
513
     * Add an object to the message's object list.
514
     *
515
     * <i>NOTE: This is a convenience function: one may use getParList() and
516
     * cArray::add() instead. See also class description for discussion about
517
     * message subclassing vs dynamically attached objects.</i>
518
     *
519
     * @see getParList()
520
     */
521
    virtual cObject *addObject(cObject *p)  {getParList().add(p); return p;}
522

    
523
    /**
524
     * Returns the object with the given name in the message's object list.
525
     * If the object is not found, it returns NULL.
526
     *
527
     * <i>NOTE: This is a convenience function: one may use getParList() and
528
     * cArray::get() instead. See also class description for discussion about
529
     * message subclassing vs dynamically attached objects.</i>
530
     *
531
     * @see getParList()
532
     */
533
    virtual cObject *getObject(const char *s)  {return getParList().get(s);}
534

    
535
    /**
536
     * Check if an object with the given name exists in the message's object list.
537
     *
538
     * <i>NOTE: This is a convenience function: one may use getParList() and
539
     * cArray::exist() instead. See also class description for discussion about
540
     * message subclassing vs dynamically attached objects.</i>
541
     *
542
     * @see getParList()
543
     */
544
    virtual bool hasObject(const char *s)  {return !parlistp ? false : parlistp->find(s)>=0;}
545

    
546
    /**
547
     * Remove the object with the given name from the message's object list, and
548
     * return its pointer. If the object does not exist, NULL is returned.
549
     *
550
     * <i>NOTE: This is a convenience function: one may use getParList() and
551
     * cArray::remove() instead. See also class description for discussion about
552
     * message subclassing vs dynamically attached objects.</i>
553
     *
554
     * @see getParList()
555
     */
556
    virtual cObject *removeObject(const char *s)  {return getParList().remove(s);}
557

    
558
    /**
559
     * Remove the object with the given name from the message's object list, and
560
     * return its pointer. If the object does not exist, NULL is returned.
561
     *
562
     * <i>NOTE: This is a convenience function: one may use getParList() and
563
     * cArray::remove() instead. See also class description for discussion about
564
     * message subclassing vs dynamically attached objects.</i>
565
     *
566
     * @see getParList()
567
     */
568
    virtual cObject *removeObject(cObject *p)  {return getParList().remove(p);}
569
    //@}
570

    
571
    /** @name Sending/arrival information. */
572
    //@{
573

    
574
    /**
575
     * Return true if message was posted by scheduleAt().
576
     */
577
    bool isSelfMessage() const {return togate==-1;}
578

    
579
    /**
580
     * Return true if message is among future events.
581
     */
582
    bool isScheduled() const {return heapindex!=-1;}
583

    
584
    /**
585
     * Returns a pointer to the sender module. It returns NULL if the message
586
     * has not been sent/scheduled yet, or if the sender module got deleted
587
     * in the meantime.
588
     */
589
    cModule *getSenderModule() const {return simulation.getModule(frommod);}
590

    
591
    /**
592
     * Returns pointers to the gate from which the message was sent and
593
     * on which gate it arrived. A NULL pointer is returned
594
     * for new (unsent) messages and messages sent via scheduleAt().
595
     */
596
    cGate *getSenderGate() const;
597

    
598
    /**
599
     * Returns a pointer to the arrival module. It returns NULL if the message
600
     * has not been sent/scheduled yet, or if the module got deleted
601
     * in the meantime.
602
     */
603
    cModule *getArrivalModule() const {return simulation.getModule(tomod);}
604

    
605
    /**
606
     * Returns pointers to the gate from which the message was sent and
607
     * on which gate it arrived. A NULL pointer is returned
608
     * for new (unsent) messages and messages sent via scheduleAt().
609
     */
610
    cGate *getArrivalGate() const;
611

    
612
    /**
613
     * Returns sender module's index in the module vector or -1 if the
614
     * message has not been sent/scheduled yet.
615
     */
616
    int getSenderModuleId() const {return frommod;}
617

    
618
    /**
619
     * Returns index of gate sent through in the sender module or -1
620
     * if the message has not been sent/scheduled yet.
621
     */
622
    int getSenderGateId() const   {return fromgate;}
623

    
624
    /**
625
     * Returns receiver module's index in the module vector or -1 if
626
     * the message has not been sent/scheduled yet.
627
     */
628
    int getArrivalModuleId() const {return tomod;}
629

    
630
    /**
631
     * Returns index of gate the message arrived on in the sender module
632
     * or -1 if the message has not sent/scheduled yet.
633
     */
634
    int getArrivalGateId() const  {return togate;}
635

    
636
    /**
637
     * Returns time when the message was created.
638
     */
639
    simtime_t_cref getCreationTime() const {return created;}
640

    
641
    /**
642
     * Returns time when the message was sent/scheduled or 0 if the message
643
     * has not been sent yet.
644
     */
645
    simtime_t_cref getSendingTime()  const {return sent;}
646

    
647
    /**
648
     * Returns time when the message arrived (or will arrive if it
649
     * is currently scheduled or is underway), or 0 if the message
650
     * has not been sent/scheduled yet.
651
     *
652
     * When the message has nonzero length and it travelled though a
653
     * channel with nonzero data rate, arrival time may represent either
654
     * the start or the end of the reception, as returned by the
655
     * isReceptionStart() method. By default it is the end of the reception;
656
     * it can be changed by calling setDeliverOnReceptionStart(true) on the
657
     * gate at receiving end of the channel that has the nonzero data rate.
658
     *
659
     * @see getDuration()
660
     */
661
    simtime_t_cref getArrivalTime()  const {return delivd;}
662

    
663
    /**
664
     * Return true if the message arrived through the given gate.
665
     */
666
    bool arrivedOn(int gateId) const {return gateId==togate;}
667

    
668
    /**
669
     * Return true if the message arrived on the gate given with its name.
670
     * If it is a vector gate, the method returns true if the message arrived
671
     * on any gate in the vector.
672
     */
673
    bool arrivedOn(const char *gatename) const;
674

    
675
    /**
676
     * Return true if the message arrived through the given gate
677
     * in the named gate vector.
678
     */
679
    bool arrivedOn(const char *gatename, int gateindex) const;
680

    
681
    /**
682
     * Returns a unique message identifier assigned upon message creation.
683
     */
684
    long getId() const {return msgid;}
685

    
686
    /**
687
     * Returns an identifier which is shared among a message object and all messages
688
     * created by copying it (i.e. by dup() or the copy constructor).
689
     */
690
    long getTreeId() const {return msgtreeid;}
691
    //@}
692

    
693
    /** @name Miscellaneous. */
694
    //@{
695

    
696
    /**
697
     * Override to define a display string for the message. Display string
698
     * affects message appearance in Tkenv. This default implementation
699
     * returns "".
700
     */
701
    virtual const char *getDisplayString() const;
702
    //@}
703

    
704
    /** @name Statistics. */
705
    //@{
706
    /**
707
     * Returns the total number of messages created since the last
708
     * reset (reset is usually called my user interfaces at the beginning
709
     * of each simulation run). The counter is incremented by cMessage constructor.
710
     * Counter is <tt>signed</tt> to make it easier to detect if it overflows
711
     * during very long simulation runs.
712
     * May be useful for profiling or debugging memory leaks.
713
     */
714
    static long getTotalMessageCount() { return AO_load(&total_msgs);}
715

    
716
    /**
717
     * Returns the number of message objects that currently exist in the
718
     * program. The counter is incremented by cMessage constructor
719
     * and decremented by the destructor.
720
     * May be useful for profiling or debugging memory leaks caused by forgetting
721
     * to delete messages.
722
     */
723
    static long getLiveMessageCount() {return AO_load(&live_msgs);}
724

    
725
    /**
726
     * Reset counters used by getTotalMessageCount() and getLiveMessageCount().
727
     */
728
    static void resetMessageCounters()  {
729
        AO_store(&total_msgs, 0);
730
        AO_store(&live_msgs, 0);
731
    }
732
    //@}
733
};
734

    
735

    
736
/**
737
 * A subclass of cMessage that can be used to represent packets (frames,
738
 * datagrams, application messages, etc). cPacket adds length (measured in
739
 * bits or bytes), bit error flag, and encapsulation capability to cMessage.
740
 * Length and bit error flag are significant when the packet travels through
741
 * a cDatarateChannel or another channel that supports data rate and/or
742
 * error modelling.
743
 *
744
 * cPacket is rarely used "as is". Typically the user wants to subclass it
745
 * to create specific packet types for various protocols being modelled.
746
 * The most convenient way to do that are via message declaration files
747
 * (.msg), which are translated into C++ classes.
748
 * An example message declaration:
749
 *
750
 * \code
751
 * packet Datagram
752
 * {
753
 *     int destAddr = -1; // destination address
754
 *     int srcAddr = -1;  // source address
755
 *     int ttl =  32;     // time to live
756
 * }
757
 * \endcode
758
 *
759
 * @see cSimpleModule, cDatarateChannel, cPacketQueue
760
 *
761
 * @ingroup SimCore
762
 */
763
class SIM_API cPacket : public cMessage
764
{
765
  private:
766
    enum {
767
        FL_ISRECEPTIONSTART = 4,
768
        FL_BITERROR = 8,
769
    };
770
    int64 len;            // length of the packet in bits -- used for bit error and transmission delay modeling
771
    simtime_t duration;   // transmission duration on last channel with datarate
772
    cPacket *encapmsg;    // ptr to the encapsulated message
773
    unsigned short sharecount; // num of messages MINUS ONE that have this message encapsulated.
774
                               // 0: not shared (not encapsulated or encapsulated in one message);
775
                               // 1: shared once (shared among two messages);
776
                               // 2: shared twice (shared among three messages); etc.
777
                               // on reaching max sharecount a new packet gets created
778

    
779
  public:
780
    // internal: sets the message duration; called by channel objects and sendDirect
781
    void setDuration(simtime_t d) {duration = d;}
782

    
783
    // internal: sets the isReceptionStart() flag
784
    void setReceptionStart(bool b) {setFlag(FL_ISRECEPTIONSTART, b);}
785

    
786
    // internal convenience method: returns the getId() of the innermost encapsulated message,
787
    // or itself if there is no encapsulated message
788
    long getEncapsulationId() const;
789

    
790
    // internal convenience method: returns getTreeId() of the innermost encapsulated message,
791
    // or itself if there is no encapsulated message
792
    long getEncapsulationTreeId() const;
793

    
794
    // internal: if encapmsg is shared (sharecount>0), creates a private copy for this packet,
795
    // and in any case it sets encapmsg's owner to be this object. This method
796
    // has to be called before any operation on encapmsg, to prevent trouble
797
    // that may arise from accessing shared message instances. E.g. without calling
798
    // _detachEncapMsg(), encapmsg's ownerp is unpredictable (may be any previous owner,
799
    // possibly not even existing any more) which makes even a call to its getFullPath()
800
    // method dangerous.
801
    void _detachEncapMsg();
802

    
803
    // internal: delete encapmsg, paying attention to its sharecount (assumes encapmsg!=NULL)
804
    void _deleteEncapMsg();
805

    
806
    // internal: only to be used by test cases
807
    int getShareCount() const {return sharecount;}
808

    
809
  public:
810
    /** @name Constructors, destructor, assignment */
811
    //@{
812
    /**
813
     * Copy constructor.
814
     */
815
    cPacket(const cPacket& packet);
816

    
817
    /**
818
     * Constructor. It takes the packet name, message kind value, and the
819
     * packet length in bits; all optional.
820
     */
821
    explicit cPacket(const char *name=NULL, short kind=0, int64 bitLength=0);
822

    
823
    /**
824
     * Destructor
825
     */
826
    virtual ~cPacket();
827

    
828
    /**
829
     * Assignment operator. Duplication and the assignment operator work all right with cPacket.
830
     * The name member is not copied; see cNamedObject's operator=() for more details.
831
     */
832
    cPacket& operator=(const cPacket& packet);
833
    //@}
834

    
835
    /** @name Redefined cObject member functions. */
836
    //@{
837

    
838
    /**
839
     * Creates and returns an exact copy of this object.
840
     * See cObject for more details.
841
     */
842
    virtual cPacket *dup() const  {return new cPacket(*this);}
843

    
844
    /**
845
     * Produces a one-line description of the object's contents.
846
     * See cObject for more details.
847
     */
848
    virtual std::string info() const;
849

    
850
    /**
851
     * Produces a multi-line description of the object's contents.
852
     * See cObject for more details.
853
     */
854
    virtual std::string detailedInfo() const;
855

    
856
    /**
857
     * Calls v->visit(this) for each contained object.
858
     * See cObject for more details.
859
     */
860
    virtual void forEachChild(cVisitor *v);
861

    
862
    /**
863
     * Serializes the object into an MPI send buffer
864
     * Used by the simulation kernel for parallel execution.
865
     * See cObject for more details.
866
     */
867
    virtual void parsimPack(cCommBuffer *buffer);
868

    
869
    /**
870
     * Deserializes the object from an MPI receive buffer
871
     * Used by the simulation kernel for parallel execution.
872
     * See cObject for more details.
873
     */
874
    virtual void parsimUnpack(cCommBuffer *buffer);
875

    
876
    /**
877
     * Returns true.
878
     */
879
    virtual bool isPacket() const {return true;}
880
    //@}
881

    
882
    /** @name Length and bit error flag */
883
    //@{
884
    /**
885
     * Sets packet length (in bits). When the packet is sent through a
886
     * channel, packet length affects the transmission duration and the
887
     * probability of setting the bit error flag.
888
     */
889
    virtual void setBitLength(int64 l);
890

    
891
    /**
892
     * Sets packet length (bytes). This is just a convenience function which
893
     * invokes setBitLength() with 8*l as argument. The caller must take care
894
     * that the result does not overflow (i.e. fits into an int64).
895
     */
896
    void setByteLength(int64 l)  {setBitLength(l<<3);}
897

    
898
    /**
899
     * Changes packet length by the given value (bits). This is useful for
900
     * modeling encapsulation/decapsulation. (See also encapsulate() and
901
     * decapsulate().) The caller must take care that the result does not
902
     * overflow (i.e. fits into an int64).
903
     *
904
     * The value may be negative (packet length may be decreased too).
905
     * If the resulting length would be negative, the method throws a
906
     * cRuntimeError.
907
     */
908
    virtual void addBitLength(int64 delta);
909

    
910
    /**
911
     * Changes packet length by the given value (bytes). This is just a
912
     * convenience function which invokes addBitLength() with 8*l as argument.
913
     * The caller must take care that the result does not overflow (i.e.
914
     * fits into an int64).
915
     */
916
    void addByteLength(int64 delta)  {addBitLength(delta<<3);}
917

    
918
    /**
919
     * Returns the packet length (in bits).
920
     */
921
    virtual int64 getBitLength() const  {return len;}
922

    
923
    /**
924
     * Returns the packet length in bytes, that is, bitlength/8. If bitlength
925
     * is not a multiple of 8, the result is rounded up.
926
     */
927
    int64 getByteLength() const  {return (len+7)>>3;}
928

    
929
    /**
930
     * Sets the bit error flag.
931
     */
932
    virtual void setBitError(bool e) {setFlag(FL_BITERROR,e);}
933

    
934
    /**
935
     * Returns the bit error flag.
936
     */
937
    virtual bool hasBitError() const {return flags&FL_BITERROR;}
938
    //@}
939

    
940
    /** @name Message encapsulation. */
941
    //@{
942

    
943
    /**
944
     * Encapsulates packet in the packet. The packet length gets increased
945
     * by the length of the encapsulated packet.
946
     *
947
     * IMPORTANT NOTE: IT IS FORBIDDEN TO KEEP A POINTER TO A MESSAGE
948
     * AFTER IT WAS ENCAPSULATED. For performance reasons, encapsulated
949
     * packets are reference counted, meaning that the encapsulated
950
     * packet is not duplicated when you duplicate a packet, but rather,
951
     * both (all) copies share the same packet instance. Any change done
952
     * to the encapsulated packet would affect other packets as well.
953
     * Decapsulation (and even calling getEncapsulatedPacket()) will create an
954
     * own (non-shared) copy of the packet.
955
     */
956
    virtual void encapsulate(cPacket *packet);
957

    
958
    /**
959
     * Decapsulates a packet from the packet object. The length of
960
     * this packet will be decreased by the length of the encapsulated
961
     * packet, except if it was zero. If the length would become
962
     * negative, cRuntimeError is thrown. If there is no encapsulated
963
     * packet, the method returns NULL.
964
     */
965
    virtual cPacket *decapsulate();
966

    
967
    /**
968
     * Returns a pointer to the encapsulated packet, or NULL if there
969
     * is no encapsulated packet.
970
     *
971
     * IMPORTANT: see notes at encapsulate() about reference counting
972
     * of encapsulated packets.
973
     */
974
    virtual cPacket *getEncapsulatedPacket() const;
975

    
976
    /**
977
     * DEPRECATED. getEncapsulatedMsg() was renamed to getEncapsulatedPacket(),
978
     * this method was left for backward compatibility.
979
     */
980
    _OPPDEPRECATED cPacket *getEncapsulatedMsg() const {return getEncapsulatedPacket();}
981
    //@}
982

    
983
    /** @name Transmission state */
984
    //@{
985
    /**
986
     * Returns the transmission duration after the packet was sent through
987
     * a channel with data rate.
988
     *
989
     * @see isReceptionStart(), getArrivalTime(), cDatarateChannel
990
     */
991
    simtime_t_cref getDuration() const {return duration;}
992

    
993
    /**
994
     * Tells whether this packet represents the start or the end of the
995
     * reception, provided the packet has nonzero length and it travelled
996
     * through a channel with nonzero data rate. This can be configured
997
     * on the receiving gate (see cGate::setDeliverOnReceptionStart()).
998
     *
999
     * @see getArrivalTime(), getDuration(), cDatarateChannel
1000
     */
1001
    bool isReceptionStart() const {return flags & FL_ISRECEPTIONSTART;}
1002
    //@}
1003
};
1004

    
1005
#ifdef WITHOUT_CPACKET
1006
#define cMessage cPacket /* restore #define in simkerneldefs.h */
1007
#endif
1008

    
1009
NAMESPACE_END
1010

    
1011
#endif
1012

    
1013