Project

General

Profile

Statistics
| Branch: | Revision:

root / include / cmessage.h @ 96e929a8

History | View | Annotate | Download (33.8 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

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

    
35
#include <semaphore.h>
36

    
37
NAMESPACE_BEGIN
38

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

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

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

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

    
76

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

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

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

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

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

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

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

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

    
153

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

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

    
161
    //
162
    // Horizon
163
    //
164
    simtime_t duration;                 // (minimum) duration of the asynchronous event
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
    simtime_t getEventDuration();
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 delivd + duration;}
223
    //@}
224

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

    
228
    /**
229
     * INTERNAL: used by cTaskHeap
230
     */
231
    inline unsigned long taskInsertOrder() const  {return taskinsertordr;}
232

    
233
    /**
234
     * INTERNAL:
235
     */
236
    void setBarrier(cBarrierMessage* barrier)  {this->barrierMsg = barrier;}
237

    
238
    /**
239
     * INTERNAL
240
     */
241
    cBarrierMessage* getBarrier()  {return barrierMsg;}
242
    //@}
243

    
244
public:
245
    /** @name Constructors, destructor, assignment */
246
    //@{
247

    
248
    /**
249
     * Copy constructor.
250
     */
251
    cMessage(const cMessage& msg);
252

    
253
    /**
254
     * Constructor.
255
     */
256
    explicit cMessage(const char *name=NULL, short kind=0);
257

    
258
    /**
259
     * Destructor.
260
     */
261
    virtual ~cMessage();
262

    
263
    /**
264
     * Assignment operator. Duplication and the assignment operator work all right with cMessage.
265
     * The name member is not copied; see cNamedObject's operator=() for more details.
266
     */
267
    cMessage& operator=(const cMessage& msg);
268
    //@}
269

    
270
    /**
271
     * Returns whether the current class is subclass of cPacket.
272
     * The cMessage implementation returns false.
273
     */
274
    virtual bool isPacket() const {return false;}
275

    
276
    /** @name Redefined cObject member functions. */
277
    //@{
278

    
279
    /**
280
     * Creates and returns an exact copy of this object.
281
     * See cObject for more details.
282
     */
283
    virtual cMessage *dup() const  {return new cMessage(*this);}
284

    
285
    /**
286
     * Produces a one-line description of the object's contents.
287
     * See cObject for more details.
288
     */
289
    virtual std::string info() const;
290

    
291
    /**
292
     * Produces a multi-line description of the object's contents.
293
     * See cObject for more details.
294
     */
295
    virtual std::string detailedInfo() const;
296

    
297
    /**
298
     * Calls v->visit(this) for each contained object.
299
     * See cObject for more details.
300
     */
301
    virtual void forEachChild(cVisitor *v);
302

    
303
    /**
304
     * Serializes the object into an MPI send buffer
305
     * Used by the simulation kernel for parallel execution.
306
     * See cObject for more details.
307
     */
308
    virtual void parsimPack(cCommBuffer *buffer);
309

    
310
    /**
311
     * Deserializes the object from an MPI receive buffer
312
     * Used by the simulation kernel for parallel execution.
313
     * See cObject for more details.
314
     */
315
    virtual void parsimUnpack(cCommBuffer *buffer);
316
    //@}
317

    
318
    /** @name Message attributes. */
319
    //@{
320

    
321
    /**
322
     * Sets the message kind. Nonnegative values can be freely used by
323
     * the user; negative values are reserved by OMNeT++ for internal
324
     * purposes.
325
     */
326
    void setKind(short k)  {msgkind=k;}
327

    
328
    /**
329
     * Sets event scheduling priority of the message. The priority member is
330
     * used when the simulator inserts messages into the future events set
331
     * (FES), to order messages with identical arrival time values.
332
     */
333
    void setSchedulingPriority(short p)  {prior=p;}
334

    
335
    /**
336
     * Sets the message's time stamp to the current simulation time.
337
     */
338
    void setTimestamp() {tstamp=simulation.getSimTime();}
339

    
340
    /**
341
     * Directly sets the message's time stamp.
342
     */
343
    void setTimestamp(simtime_t t) {tstamp=t;}
344

    
345
    /**
346
     * Sets the context pointer. This pointer may store an arbitrary value.
347
     * It is useful when managing several timers (self-messages): when
348
     * scheduling the message one can set the context pointer to the data
349
     * structure the timer corresponds to (e.g. the buffer whose timeout
350
     * the message represents), so that when the self-message arrives it is
351
     * easier to identify where it belongs.
352
     */
353
    void setContextPointer(void *p) {contextptr=p;}
354

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

    
372
    /**
373
     * Removes the "control info" structure (object) from the message
374
     * and returns its pointer. Returns NULL if there was no control info
375
     * in the message
376
     */
377
    cObject *removeControlInfo();
378

    
379
    /**
380
     * Returns the message kind.
381
     */
382
    short getKind() const  {return msgkind;}
383

    
384
    /**
385
     * Returns the event scheduling priority.
386
     */
387
    short getSchedulingPriority() const  {return prior;}
388

    
389
    /**
390
     * Returns the message's time stamp.
391
     */
392
    simtime_t_cref getTimestamp() const {return tstamp;}
393

    
394
    /**
395
     * Returns the context pointer.
396
     */
397
    void *getContextPointer() const {return contextptr;}
398

    
399
    /**
400
     * Returns pointer to the attached "control info".
401
     */
402
    cObject *getControlInfo() const {return ctrlp;}
403
    //@}
404

    
405
    /** @name Dynamically attaching objects. */
406
    //@{
407

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

    
423
    /**
424
     * Add a new, empty parameter (cMsgPar object) with the given name
425
     * to the message's object list.
426
     *
427
     * <i>NOTE: This is a convenience function: one may use getParList() and
428
     * cArray::add() instead. See also class description for discussion about
429
     * message subclassing vs dynamically attached objects.</i>
430
     *
431
     * @see getParList()
432
     */
433
    virtual cMsgPar& addPar(const char *s)  {cMsgPar *p=new cMsgPar(s);getParList().add(p);return *p;}
434

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

    
446
    /**
447
     * DEPRECATED! Use addPar(cMsgPar *p) instead.
448
     */
449
    _OPPDEPRECATED cMsgPar& addPar(cMsgPar& p)  {return addPar(&p);}
450

    
451
    /**
452
     * Returns the nth object in the message's object list, converting it to a cMsgPar.
453
     * If the object does not exist or it cannot be cast to cMsgPar (using dynamic_cast\<\>),
454
     * the method throws a cRuntimeError.
455
     *
456
     * <i>NOTE: This is a convenience function: one may use getParList() and
457
     * cArray::get() instead. See also class description for discussion about
458
     * message subclassing vs dynamically attached objects.</i>
459
     *
460
     * @see getParList()
461
     */
462
    virtual cMsgPar& par(int n);
463

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

    
478
    /**
479
     * Returns the index of the parameter with the given name in the message's
480
     * object list, or -1 if it could not be found.
481
     *
482
     * <i>NOTE: This is a convenience function: one may use getParList() and
483
     * cArray::find() instead. See also class description for discussion about
484
     * message subclassing vs dynamically attached objects.</i>
485
     *
486
     * @see getParList()
487
     */
488
    virtual int findPar(const char *s) const;
489

    
490
    /**
491
     * Check if a parameter with the given name exists in the message's
492
     * object list.
493
     *
494
     * <i>NOTE: This is a convenience function: one may use getParList() and
495
     * cArray::exist() instead. See also class description for discussion about
496
     * message subclassing vs dynamically attached objects.</i>
497
     *
498
     * @see getParList()
499
     */
500
    virtual bool hasPar(const char *s) const {return findPar(s)>=0;}
501

    
502
    /**
503
     * Add an object to the message's object list.
504
     *
505
     * <i>NOTE: This is a convenience function: one may use getParList() and
506
     * cArray::add() instead. See also class description for discussion about
507
     * message subclassing vs dynamically attached objects.</i>
508
     *
509
     * @see getParList()
510
     */
511
    virtual cObject *addObject(cObject *p)  {getParList().add(p); return p;}
512

    
513
    /**
514
     * Returns the object with the given name in the message's object list.
515
     * If the object is not found, it returns NULL.
516
     *
517
     * <i>NOTE: This is a convenience function: one may use getParList() and
518
     * cArray::get() instead. See also class description for discussion about
519
     * message subclassing vs dynamically attached objects.</i>
520
     *
521
     * @see getParList()
522
     */
523
    virtual cObject *getObject(const char *s)  {return getParList().get(s);}
524

    
525
    /**
526
     * Check if an object with the given name exists in the message's object list.
527
     *
528
     * <i>NOTE: This is a convenience function: one may use getParList() and
529
     * cArray::exist() instead. See also class description for discussion about
530
     * message subclassing vs dynamically attached objects.</i>
531
     *
532
     * @see getParList()
533
     */
534
    virtual bool hasObject(const char *s)  {return !parlistp ? false : parlistp->find(s)>=0;}
535

    
536
    /**
537
     * Remove the object with the given name from the message's object list, and
538
     * return its pointer. If the object does not exist, NULL is returned.
539
     *
540
     * <i>NOTE: This is a convenience function: one may use getParList() and
541
     * cArray::remove() instead. See also class description for discussion about
542
     * message subclassing vs dynamically attached objects.</i>
543
     *
544
     * @see getParList()
545
     */
546
    virtual cObject *removeObject(const char *s)  {return getParList().remove(s);}
547

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

    
561
    /** @name Sending/arrival information. */
562
    //@{
563

    
564
    /**
565
     * Return true if message was posted by scheduleAt().
566
     */
567
    bool isSelfMessage() const {return togate==-1;}
568

    
569
    /**
570
     * Return true if message is among future events.
571
     */
572
    bool isScheduled() const {return heapindex!=-1;}
573

    
574
    /**
575
     * Returns a pointer to the sender module. It returns NULL if the message
576
     * has not been sent/scheduled yet, or if the sender module got deleted
577
     * in the meantime.
578
     */
579
    cModule *getSenderModule() const {return simulation.getModule(frommod);}
580

    
581
    /**
582
     * Returns pointers to the gate from which the message was sent and
583
     * on which gate it arrived. A NULL pointer is returned
584
     * for new (unsent) messages and messages sent via scheduleAt().
585
     */
586
    cGate *getSenderGate() const;
587

    
588
    /**
589
     * Returns a pointer to the arrival module. It returns NULL if the message
590
     * has not been sent/scheduled yet, or if the module got deleted
591
     * in the meantime.
592
     */
593
    cModule *getArrivalModule() const {return simulation.getModule(tomod);}
594

    
595
    /**
596
     * Returns pointers to the gate from which the message was sent and
597
     * on which gate it arrived. A NULL pointer is returned
598
     * for new (unsent) messages and messages sent via scheduleAt().
599
     */
600
    cGate *getArrivalGate() const;
601

    
602
    /**
603
     * Returns sender module's index in the module vector or -1 if the
604
     * message has not been sent/scheduled yet.
605
     */
606
    int getSenderModuleId() const {return frommod;}
607

    
608
    /**
609
     * Returns index of gate sent through in the sender module or -1
610
     * if the message has not been sent/scheduled yet.
611
     */
612
    int getSenderGateId() const   {return fromgate;}
613

    
614
    /**
615
     * Returns receiver module's index in the module vector or -1 if
616
     * the message has not been sent/scheduled yet.
617
     */
618
    int getArrivalModuleId() const {return tomod;}
619

    
620
    /**
621
     * Returns index of gate the message arrived on in the sender module
622
     * or -1 if the message has not sent/scheduled yet.
623
     */
624
    int getArrivalGateId() const  {return togate;}
625

    
626
    /**
627
     * Returns time when the message was created.
628
     */
629
    simtime_t_cref getCreationTime() const {return created;}
630

    
631
    /**
632
     * Returns time when the message was sent/scheduled or 0 if the message
633
     * has not been sent yet.
634
     */
635
    simtime_t_cref getSendingTime()  const {return sent;}
636

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

    
653
    /**
654
     * Return true if the message arrived through the given gate.
655
     */
656
    bool arrivedOn(int gateId) const {return gateId==togate;}
657

    
658
    /**
659
     * Return true if the message arrived on the gate given with its name.
660
     * If it is a vector gate, the method returns true if the message arrived
661
     * on any gate in the vector.
662
     */
663
    bool arrivedOn(const char *gatename) const;
664

    
665
    /**
666
     * Return true if the message arrived through the given gate
667
     * in the named gate vector.
668
     */
669
    bool arrivedOn(const char *gatename, int gateindex) const;
670

    
671
    /**
672
     * Returns a unique message identifier assigned upon message creation.
673
     */
674
    long getId() const {return msgid;}
675

    
676
    /**
677
     * Returns an identifier which is shared among a message object and all messages
678
     * created by copying it (i.e. by dup() or the copy constructor).
679
     */
680
    long getTreeId() const {return msgtreeid;}
681
    //@}
682

    
683
    /** @name Miscellaneous. */
684
    //@{
685

    
686
    /**
687
     * Override to define a display string for the message. Display string
688
     * affects message appearance in Tkenv. This default implementation
689
     * returns "".
690
     */
691
    virtual const char *getDisplayString() const;
692
    //@}
693

    
694
    /** @name Statistics. */
695
    //@{
696
    /**
697
     * Returns the total number of messages created since the last
698
     * reset (reset is usually called my user interfaces at the beginning
699
     * of each simulation run). The counter is incremented by cMessage constructor.
700
     * Counter is <tt>signed</tt> to make it easier to detect if it overflows
701
     * during very long simulation runs.
702
     * May be useful for profiling or debugging memory leaks.
703
     */
704
    static long getTotalMessageCount() { return AO_load(&total_msgs);}
705

    
706
    /**
707
     * Returns the number of message objects that currently exist in the
708
     * program. The counter is incremented by cMessage constructor
709
     * and decremented by the destructor.
710
     * May be useful for profiling or debugging memory leaks caused by forgetting
711
     * to delete messages.
712
     */
713
    static long getLiveMessageCount() {return AO_load(&live_msgs);}
714

    
715
    /**
716
     * Reset counters used by getTotalMessageCount() and getLiveMessageCount().
717
     */
718
    static void resetMessageCounters()  {
719
        AO_store(&total_msgs, 0);
720
        AO_store(&live_msgs, 0);
721
    }
722
    //@}
723
};
724

    
725

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

    
769
  public:
770
    // internal: sets the message duration; called by channel objects and sendDirect
771
    void setDuration(simtime_t d) {duration = d;}
772

    
773
    // internal: sets the isReceptionStart() flag
774
    void setReceptionStart(bool b) {setFlag(FL_ISRECEPTIONSTART, b);}
775

    
776
    // internal convenience method: returns the getId() of the innermost encapsulated message,
777
    // or itself if there is no encapsulated message
778
    long getEncapsulationId() const;
779

    
780
    // internal convenience method: returns getTreeId() of the innermost encapsulated message,
781
    // or itself if there is no encapsulated message
782
    long getEncapsulationTreeId() const;
783

    
784
    // internal: if encapmsg is shared (sharecount>0), creates a private copy for this packet,
785
    // and in any case it sets encapmsg's owner to be this object. This method
786
    // has to be called before any operation on encapmsg, to prevent trouble
787
    // that may arise from accessing shared message instances. E.g. without calling
788
    // _detachEncapMsg(), encapmsg's ownerp is unpredictable (may be any previous owner,
789
    // possibly not even existing any more) which makes even a call to its getFullPath()
790
    // method dangerous.
791
    void _detachEncapMsg();
792

    
793
    // internal: delete encapmsg, paying attention to its sharecount (assumes encapmsg!=NULL)
794
    void _deleteEncapMsg();
795

    
796
    // internal: only to be used by test cases
797
    int getShareCount() const {return sharecount;}
798

    
799
  public:
800
    /** @name Constructors, destructor, assignment */
801
    //@{
802
    /**
803
     * Copy constructor.
804
     */
805
    cPacket(const cPacket& packet);
806

    
807
    /**
808
     * Constructor. It takes the packet name, message kind value, and the
809
     * packet length in bits; all optional.
810
     */
811
    explicit cPacket(const char *name=NULL, short kind=0, int64 bitLength=0);
812

    
813
    /**
814
     * Destructor
815
     */
816
    virtual ~cPacket();
817

    
818
    /**
819
     * Assignment operator. Duplication and the assignment operator work all right with cPacket.
820
     * The name member is not copied; see cNamedObject's operator=() for more details.
821
     */
822
    cPacket& operator=(const cPacket& packet);
823
    //@}
824

    
825
    /** @name Redefined cObject member functions. */
826
    //@{
827

    
828
    /**
829
     * Creates and returns an exact copy of this object.
830
     * See cObject for more details.
831
     */
832
    virtual cPacket *dup() const  {return new cPacket(*this);}
833

    
834
    /**
835
     * Produces a one-line description of the object's contents.
836
     * See cObject for more details.
837
     */
838
    virtual std::string info() const;
839

    
840
    /**
841
     * Produces a multi-line description of the object's contents.
842
     * See cObject for more details.
843
     */
844
    virtual std::string detailedInfo() const;
845

    
846
    /**
847
     * Calls v->visit(this) for each contained object.
848
     * See cObject for more details.
849
     */
850
    virtual void forEachChild(cVisitor *v);
851

    
852
    /**
853
     * Serializes the object into an MPI send buffer
854
     * Used by the simulation kernel for parallel execution.
855
     * See cObject for more details.
856
     */
857
    virtual void parsimPack(cCommBuffer *buffer);
858

    
859
    /**
860
     * Deserializes the object from an MPI receive buffer
861
     * Used by the simulation kernel for parallel execution.
862
     * See cObject for more details.
863
     */
864
    virtual void parsimUnpack(cCommBuffer *buffer);
865

    
866
    /**
867
     * Returns true.
868
     */
869
    virtual bool isPacket() const {return true;}
870
    //@}
871

    
872
    /** @name Length and bit error flag */
873
    //@{
874
    /**
875
     * Sets packet length (in bits). When the packet is sent through a
876
     * channel, packet length affects the transmission duration and the
877
     * probability of setting the bit error flag.
878
     */
879
    virtual void setBitLength(int64 l);
880

    
881
    /**
882
     * Sets packet length (bytes). This is just a convenience function which
883
     * invokes setBitLength() with 8*l as argument. The caller must take care
884
     * that the result does not overflow (i.e. fits into an int64).
885
     */
886
    void setByteLength(int64 l)  {setBitLength(l<<3);}
887

    
888
    /**
889
     * Changes packet length by the given value (bits). This is useful for
890
     * modeling encapsulation/decapsulation. (See also encapsulate() and
891
     * decapsulate().) The caller must take care that the result does not
892
     * overflow (i.e. fits into an int64).
893
     *
894
     * The value may be negative (packet length may be decreased too).
895
     * If the resulting length would be negative, the method throws a
896
     * cRuntimeError.
897
     */
898
    virtual void addBitLength(int64 delta);
899

    
900
    /**
901
     * Changes packet length by the given value (bytes). This is just a
902
     * convenience function which invokes addBitLength() with 8*l as argument.
903
     * The caller must take care that the result does not overflow (i.e.
904
     * fits into an int64).
905
     */
906
    void addByteLength(int64 delta)  {addBitLength(delta<<3);}
907

    
908
    /**
909
     * Returns the packet length (in bits).
910
     */
911
    virtual int64 getBitLength() const  {return len;}
912

    
913
    /**
914
     * Returns the packet length in bytes, that is, bitlength/8. If bitlength
915
     * is not a multiple of 8, the result is rounded up.
916
     */
917
    int64 getByteLength() const  {return (len+7)>>3;}
918

    
919
    /**
920
     * Sets the bit error flag.
921
     */
922
    virtual void setBitError(bool e) {setFlag(FL_BITERROR,e);}
923

    
924
    /**
925
     * Returns the bit error flag.
926
     */
927
    virtual bool hasBitError() const {return flags&FL_BITERROR;}
928
    //@}
929

    
930
    /** @name Message encapsulation. */
931
    //@{
932

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

    
948
    /**
949
     * Decapsulates a packet from the packet object. The length of
950
     * this packet will be decreased by the length of the encapsulated
951
     * packet, except if it was zero. If the length would become
952
     * negative, cRuntimeError is thrown. If there is no encapsulated
953
     * packet, the method returns NULL.
954
     */
955
    virtual cPacket *decapsulate();
956

    
957
    /**
958
     * Returns a pointer to the encapsulated packet, or NULL if there
959
     * is no encapsulated packet.
960
     *
961
     * IMPORTANT: see notes at encapsulate() about reference counting
962
     * of encapsulated packets.
963
     */
964
    virtual cPacket *getEncapsulatedPacket() const;
965

    
966
    /**
967
     * DEPRECATED. getEncapsulatedMsg() was renamed to getEncapsulatedPacket(),
968
     * this method was left for backward compatibility.
969
     */
970
    _OPPDEPRECATED cPacket *getEncapsulatedMsg() const {return getEncapsulatedPacket();}
971
    //@}
972

    
973
    /** @name Transmission state */
974
    //@{
975
    /**
976
     * Returns the transmission duration after the packet was sent through
977
     * a channel with data rate.
978
     *
979
     * @see isReceptionStart(), getArrivalTime(), cDatarateChannel
980
     */
981
    simtime_t_cref getDuration() const {return duration;}
982

    
983
    /**
984
     * Tells whether this packet represents the start or the end of the
985
     * reception, provided the packet has nonzero length and it travelled
986
     * through a channel with nonzero data rate. This can be configured
987
     * on the receiving gate (see cGate::setDeliverOnReceptionStart()).
988
     *
989
     * @see getArrivalTime(), getDuration(), cDatarateChannel
990
     */
991
    bool isReceptionStart() const {return flags & FL_ISRECEPTIONSTART;}
992
    //@}
993
};
994

    
995
#ifdef WITHOUT_CPACKET
996
#define cMessage cPacket /* restore #define in simkerneldefs.h */
997
#endif
998

    
999
NAMESPACE_END
1000

    
1001
#endif
1002

    
1003