Project

General

Profile

Statistics
| Branch: | Revision:

root / include / cmessage.h @ aeae20a1

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
#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
    int taskindex;                      // used by cTaskHeap (-1 if not on heap)
165
    unsigned long taskinsertordr;       // used by cTaskHeap
166

    
167
    cBarrierMessage* barrierMsg;
168

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
434
    /**
435
     * Add a parameter object 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(cMsgPar *p)  {getParList().add(p); return *p;}
444

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
724

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
998
NAMESPACE_END
999

    
1000
#endif
1001

    
1002