Statistics
| Branch: | Revision:

root / include / cmessage.h @ cbd2c699

History | View | Annotate | Download (35.6 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
    unsigned int executionOrderId;  // execution order of this event wrt to all other events at the same simtime
154
    unsigned int parentExecutionOrderId; // execution order id of the parent event wrt to all other events at the same simtime
155
    simtime_t parentStartTime;  // the time at which the parent event occurred
156
    unsigned int schedulingOrderId; // id specifying the number of events schedules before this one by the parent event
157

    
158
    // internal: create parlist
159
    void _createparlist();
160

    
161
protected:
162
    cMessage *encapmsg;        // ptr to encapsulated msg
163

    
164
    //
165
    // Horizon
166
    //
167
    simtime_t eventDuration;            // (minimum) eventDuration of the asynchronous event
168
    int taskindex;                      // used by cTaskHeap (-1 if not on heap)
169
    unsigned long taskinsertordr;       // used by cTaskHeap
170

    
171
    cBarrierMessage* barrierMsg;
172

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

    
178
    // internal: sets previousEventNumber.
179
    void setPreviousEventNumber(eventnumber_t num) {prev_event_num = num;}
180

    
181
    // internal: used by cMessageHeap.
182
    unsigned long getInsertOrder() const {return insertordr;}
183

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

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

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

    
199
    // internal: called by the simulation kernel to set the value returned
200
    // by the getArrivalTime() method
201
    void setArrivalTime(simtime_t t);
202

    
203
    // internal: used by the parallel simulation kernel.
204
    void setSrcProcId(int procId) {srcprocid = (short)procId;}
205

    
206
    // internal: used by the parallel simulation kernel.
207
    int getSrcProcId() const {return srcprocid;}
208

    
209
    /** @name Horizon API. */
210
    //@{
211

    
212
    /**
213
     * Returns the eventDuration of this event.
214
     */
215
    simtime_t getEventDuration();
216

    
217
    /**
218
     * Sets the eventDuration of this event.
219
     */
220
    inline void setEventDuration(simtime_t t)  {eventDuration = t;}
221

    
222
    /**
223
     * Returns the end of the eventDuration interval.
224
     */
225
    inline simtime_t getTend() const  {return delivd + eventDuration;}
226
    //@}
227

    
228
    /** @name Internal Horizon use only. */
229
    //@{
230

    
231
    /**
232
     * INTERNAL: used by cTaskHeap
233
     */
234
    inline unsigned long getTaskInsertOrder() const  {return taskinsertordr;}
235

    
236
    /**
237
     * INTERNAL:
238
     */
239
    void setBarrier(cBarrierMessage* barrier)  {this->barrierMsg = barrier;}
240

    
241
    /**
242
     * INTERNAL
243
     */
244
    cBarrierMessage* getBarrier() const  {return barrierMsg;}
245

    
246
    /**
247
     * INTERNAL
248
     */
249
    void setSchedulingOrderId(unsigned int id) {schedulingOrderId = id;}
250

    
251
    /**
252
     * INTERNAL
253
     */
254
    unsigned int getSchedulingOrderId() const  {return schedulingOrderId;}
255

    
256
    /**
257
     * INTERNAL: set how many other events have already been executed at this point
258
     *           in simtime
259
     */
260
    void setExecutionOrderId(unsigned int id)  {executionOrderId = id;}
261

    
262
    /**
263
     * INTERNAL: get how many other events have already been executed at this point
264
     *           in simtime
265
     */
266
    unsigned int getExecutionOrderId() const  {return executionOrderId;}
267

    
268
    /**
269
     * INTERNAL: set how many other events have already been executed at this point
270
     *           in simtime as the parent of this event
271
     */
272
    void setParentExecutionOrderId(unsigned int id)  {parentExecutionOrderId = id;}
273

    
274
    /**
275
     * INTERNAL: get how many other events have already been executed at this point
276
     *           in simtime as the parent of this event
277
     */
278
    unsigned int getParentExecutionOrderId() const  {return parentExecutionOrderId;}
279

    
280
    /**
281
     * INTERNAL: remember the starting time of the parent event
282
     */
283
    void setParentStartTime(simtime_t time)  {parentStartTime = time;}
284

    
285
    /**
286
     * INTERNAL: get the starting time of the parent event
287
     */
288
    simtime_t getParentStartTime() const  {return parentStartTime;}
289
    //@}
290

    
291
public:
292
    /** @name Constructors, destructor, assignment */
293
    //@{
294

    
295
    /**
296
     * Copy constructor.
297
     */
298
    cMessage(const cMessage& msg);
299

    
300
    /**
301
     * Constructor.
302
     */
303
    explicit cMessage(const char *name=NULL, short kind=0);
304

    
305
    /**
306
     * Destructor.
307
     */
308
    virtual ~cMessage();
309

    
310
    /**
311
     * Assignment operator. Duplication and the assignment operator work all right with cMessage.
312
     * The name member is not copied; see cNamedObject's operator=() for more details.
313
     */
314
    cMessage& operator=(const cMessage& msg);
315
    //@}
316

    
317
    /**
318
     * Returns whether the current class is subclass of cPacket.
319
     * The cMessage implementation returns false.
320
     */
321
    virtual bool isPacket() const {return false;}
322

    
323
    /** @name Redefined cObject member functions. */
324
    //@{
325

    
326
    /**
327
     * Creates and returns an exact copy of this object.
328
     * See cObject for more details.
329
     */
330
    virtual cMessage *dup() const  {return new cMessage(*this);}
331

    
332
    /**
333
     * Produces a one-line description of the object's contents.
334
     * See cObject for more details.
335
     */
336
    virtual std::string info() const;
337

    
338
    /**
339
     * Produces a multi-line description of the object's contents.
340
     * See cObject for more details.
341
     */
342
    virtual std::string detailedInfo() const;
343

    
344
    /**
345
     * Calls v->visit(this) for each contained object.
346
     * See cObject for more details.
347
     */
348
    virtual void forEachChild(cVisitor *v);
349

    
350
    /**
351
     * Serializes the object into an MPI send buffer
352
     * Used by the simulation kernel for parallel execution.
353
     * See cObject for more details.
354
     */
355
    virtual void parsimPack(cCommBuffer *buffer);
356

    
357
    /**
358
     * Deserializes the object from an MPI receive buffer
359
     * Used by the simulation kernel for parallel execution.
360
     * See cObject for more details.
361
     */
362
    virtual void parsimUnpack(cCommBuffer *buffer);
363
    //@}
364

    
365
    /** @name Message attributes. */
366
    //@{
367

    
368
    /**
369
     * Sets the message kind. Nonnegative values can be freely used by
370
     * the user; negative values are reserved by OMNeT++ for internal
371
     * purposes.
372
     */
373
    void setKind(short k)  {msgkind=k;}
374

    
375
    /**
376
     * Sets event scheduling priority of the message. The priority member is
377
     * used when the simulator inserts messages into the future events set
378
     * (FES), to order messages with identical arrival time values.
379
     */
380
    void setSchedulingPriority(short p)  {prior=p;}
381

    
382
    /**
383
     * Sets the message's time stamp to the current simulation time.
384
     */
385
    void setTimestamp() {tstamp=simulation.getSimTime();}
386

    
387
    /**
388
     * Directly sets the message's time stamp.
389
     */
390
    void setTimestamp(simtime_t t) {tstamp=t;}
391

    
392
    /**
393
     * Sets the context pointer. This pointer may store an arbitrary value.
394
     * It is useful when managing several timers (self-messages): when
395
     * scheduling the message one can set the context pointer to the data
396
     * structure the timer corresponds to (e.g. the buffer whose timeout
397
     * the message represents), so that when the self-message arrives it is
398
     * easier to identify where it belongs.
399
     */
400
    void setContextPointer(void *p) {contextptr=p;}
401

    
402
    /**
403
     * Attaches a "control info" structure (object) to the message.
404
     * This is most useful when passing packets between protocol layers
405
     * of a protocol stack: e.g. when sending down an IP datagram to Ethernet,
406
     * the attached "control info" can contain the destination MAC address.
407
     *
408
     * The "control info" object will be deleted when the message is deleted.
409
     * Only one "control info" structure can be attached (the second
410
     * setControlInfo() call throws an error).
411
     *
412
     * When the message is duplicated or copied, copies will have their
413
     * control info set to NULL because the cObject interface
414
     * does not define dup/copy operations.
415
     * The assignment operator does not change control info.
416
     */
417
    void setControlInfo(cObject *p);
418

    
419
    /**
420
     * Removes the "control info" structure (object) from the message
421
     * and returns its pointer. Returns NULL if there was no control info
422
     * in the message
423
     */
424
    cObject *removeControlInfo();
425

    
426
    /**
427
     * Returns the message kind.
428
     */
429
    short getKind() const  {return msgkind;}
430

    
431
    /**
432
     * Returns the event scheduling priority.
433
     */
434
    short getSchedulingPriority() const  {return prior;}
435

    
436
    /**
437
     * Returns the message's time stamp.
438
     */
439
    simtime_t_cref getTimestamp() const {return tstamp;}
440

    
441
    /**
442
     * Returns the context pointer.
443
     */
444
    void *getContextPointer() const {return contextptr;}
445

    
446
    /**
447
     * Returns pointer to the attached "control info".
448
     */
449
    cObject *getControlInfo() const {return ctrlp;}
450
    //@}
451

    
452
    /** @name Dynamically attaching objects. */
453
    //@{
454

    
455
    /**
456
     * Returns reference to the 'object list' of the message: a cArray
457
     * which is used to store parameter (cMsgPar) objects and other objects
458
     * attached to the message.
459
     *
460
     * One can use either getParList() combined with cArray methods,
461
     * or several convenience methods (addPar(), addObject(), par(), etc.)
462
     * to add, retrieve or remove cMsgPars and other objects.
463
     *
464
     * <i>NOTE: using the object list has alternatives which may better
465
     * suit your needs. For more information, see class description for discussion
466
     * about message subclassing vs dynamically attached objects.</i>
467
     */
468
    virtual cArray& getParList()  {if (!parlistp) _createparlist(); return *parlistp;}
469

    
470
    /**
471
     * Add a new, empty parameter (cMsgPar object) with the given name
472
     * to the message's object list.
473
     *
474
     * <i>NOTE: This is a convenience function: one may use getParList() and
475
     * cArray::add() instead. See also class description for discussion about
476
     * message subclassing vs dynamically attached objects.</i>
477
     *
478
     * @see getParList()
479
     */
480
    virtual cMsgPar& addPar(const char *s)  {cMsgPar *p=new cMsgPar(s);getParList().add(p);return *p;}
481

    
482
    /**
483
     * Add a parameter object to the message's object list.
484
     *
485
     * <i>NOTE: This is a convenience function: one may use getParList() and
486
     * cArray::add() instead. See also class description for discussion about
487
     * message subclassing vs dynamically attached objects.</i>
488
     *
489
     * @see getParList()
490
     */
491
    virtual cMsgPar& addPar(cMsgPar *p)  {getParList().add(p); return *p;}
492

    
493
    /**
494
     * DEPRECATED! Use addPar(cMsgPar *p) instead.
495
     */
496
    _OPPDEPRECATED cMsgPar& addPar(cMsgPar& p)  {return addPar(&p);}
497

    
498
    /**
499
     * Returns the nth object in the message's object list, converting it to a cMsgPar.
500
     * If the object does not exist or it cannot be cast to cMsgPar (using dynamic_cast\<\>),
501
     * the method throws a cRuntimeError.
502
     *
503
     * <i>NOTE: This is a convenience function: one may use getParList() and
504
     * cArray::get() instead. See also class description for discussion about
505
     * message subclassing vs dynamically attached objects.</i>
506
     *
507
     * @see getParList()
508
     */
509
    virtual cMsgPar& par(int n);
510

    
511
    /**
512
     * Returns the object with the given name in the message's object list,
513
     * converting it to a cMsgPar.
514
     * If the object does not exist or it cannot be cast to cMsgPar (using dynamic_cast\<\>),
515
     * the method throws a cRuntimeError.
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 cMsgPar& par(const char *s);
524

    
525
    /**
526
     * Returns the index of the parameter with the given name in the message's
527
     * object list, or -1 if it could not be found.
528
     *
529
     * <i>NOTE: This is a convenience function: one may use getParList() and
530
     * cArray::find() instead. See also class description for discussion about
531
     * message subclassing vs dynamically attached objects.</i>
532
     *
533
     * @see getParList()
534
     */
535
    virtual int findPar(const char *s) const;
536

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

    
549
    /**
550
     * Add an object to the message's object list.
551
     *
552
     * <i>NOTE: This is a convenience function: one may use getParList() and
553
     * cArray::add() instead. See also class description for discussion about
554
     * message subclassing vs dynamically attached objects.</i>
555
     *
556
     * @see getParList()
557
     */
558
    virtual cObject *addObject(cObject *p)  {getParList().add(p); return p;}
559

    
560
    /**
561
     * Returns the object with the given name in the message's object list.
562
     * If the object is not found, it returns NULL.
563
     *
564
     * <i>NOTE: This is a convenience function: one may use getParList() and
565
     * cArray::get() instead. See also class description for discussion about
566
     * message subclassing vs dynamically attached objects.</i>
567
     *
568
     * @see getParList()
569
     */
570
    virtual cObject *getObject(const char *s)  {return getParList().get(s);}
571

    
572
    /**
573
     * Check if an object with the given name exists in the message's object list.
574
     *
575
     * <i>NOTE: This is a convenience function: one may use getParList() and
576
     * cArray::exist() instead. See also class description for discussion about
577
     * message subclassing vs dynamically attached objects.</i>
578
     *
579
     * @see getParList()
580
     */
581
    virtual bool hasObject(const char *s)  {return !parlistp ? false : parlistp->find(s)>=0;}
582

    
583
    /**
584
     * Remove the object with the given name from the message's object list, and
585
     * return its pointer. If the object does not exist, NULL is returned.
586
     *
587
     * <i>NOTE: This is a convenience function: one may use getParList() and
588
     * cArray::remove() instead. See also class description for discussion about
589
     * message subclassing vs dynamically attached objects.</i>
590
     *
591
     * @see getParList()
592
     */
593
    virtual cObject *removeObject(const char *s)  {return getParList().remove(s);}
594

    
595
    /**
596
     * Remove the object with the given name from the message's object list, and
597
     * return its pointer. If the object does not exist, NULL is returned.
598
     *
599
     * <i>NOTE: This is a convenience function: one may use getParList() and
600
     * cArray::remove() instead. See also class description for discussion about
601
     * message subclassing vs dynamically attached objects.</i>
602
     *
603
     * @see getParList()
604
     */
605
    virtual cObject *removeObject(cObject *p)  {return getParList().remove(p);}
606
    //@}
607

    
608
    /** @name Sending/arrival information. */
609
    //@{
610

    
611
    /**
612
     * Return true if message was posted by scheduleAt().
613
     */
614
    bool isSelfMessage() const {return togate==-1;}
615

    
616
    /**
617
     * Return true if message is among future events.
618
     */
619
    bool isScheduled() const {return heapindex!=-1;}
620

    
621
    /**
622
     * Returns a pointer to the sender module. It returns NULL if the message
623
     * has not been sent/scheduled yet, or if the sender module got deleted
624
     * in the meantime.
625
     */
626
    cModule *getSenderModule() const {return simulation.getModule(frommod);}
627

    
628
    /**
629
     * Returns pointers to the gate from which the message was sent and
630
     * on which gate it arrived. A NULL pointer is returned
631
     * for new (unsent) messages and messages sent via scheduleAt().
632
     */
633
    cGate *getSenderGate() const;
634

    
635
    /**
636
     * Returns a pointer to the arrival module. It returns NULL if the message
637
     * has not been sent/scheduled yet, or if the module got deleted
638
     * in the meantime.
639
     */
640
    cModule *getArrivalModule() const {return simulation.getModule(tomod);}
641

    
642
    /**
643
     * Returns pointers to the gate from which the message was sent and
644
     * on which gate it arrived. A NULL pointer is returned
645
     * for new (unsent) messages and messages sent via scheduleAt().
646
     */
647
    cGate *getArrivalGate() const;
648

    
649
    /**
650
     * Returns sender module's index in the module vector or -1 if the
651
     * message has not been sent/scheduled yet.
652
     */
653
    int getSenderModuleId() const {return frommod;}
654

    
655
    /**
656
     * Returns index of gate sent through in the sender module or -1
657
     * if the message has not been sent/scheduled yet.
658
     */
659
    int getSenderGateId() const   {return fromgate;}
660

    
661
    /**
662
     * Returns receiver module's index in the module vector or -1 if
663
     * the message has not been sent/scheduled yet.
664
     */
665
    int getArrivalModuleId() const {return tomod;}
666

    
667
    /**
668
     * Returns index of gate the message arrived on in the sender module
669
     * or -1 if the message has not sent/scheduled yet.
670
     */
671
    int getArrivalGateId() const  {return togate;}
672

    
673
    /**
674
     * Returns time when the message was created.
675
     */
676
    simtime_t_cref getCreationTime() const {return created;}
677

    
678
    /**
679
     * Returns time when the message was sent/scheduled or 0 if the message
680
     * has not been sent yet.
681
     */
682
    simtime_t_cref getSendingTime()  const {return sent;}
683

    
684
    /**
685
     * Returns time when the message arrived (or will arrive if it
686
     * is currently scheduled or is underway), or 0 if the message
687
     * has not been sent/scheduled yet.
688
     *
689
     * When the message has nonzero length and it travelled though a
690
     * channel with nonzero data rate, arrival time may represent either
691
     * the start or the end of the reception, as returned by the
692
     * isReceptionStart() method. By default it is the end of the reception;
693
     * it can be changed by calling setDeliverOnReceptionStart(true) on the
694
     * gate at receiving end of the channel that has the nonzero data rate.
695
     *
696
     * @see getDuration()
697
     */
698
    simtime_t_cref getArrivalTime()  const {return delivd;}
699

    
700
    /**
701
     * Return true if the message arrived through the given gate.
702
     */
703
    bool arrivedOn(int gateId) const {return gateId==togate;}
704

    
705
    /**
706
     * Return true if the message arrived on the gate given with its name.
707
     * If it is a vector gate, the method returns true if the message arrived
708
     * on any gate in the vector.
709
     */
710
    bool arrivedOn(const char *gatename) const;
711

    
712
    /**
713
     * Return true if the message arrived through the given gate
714
     * in the named gate vector.
715
     */
716
    bool arrivedOn(const char *gatename, int gateindex) const;
717

    
718
    /**
719
     * Returns a unique message identifier assigned upon message creation.
720
     */
721
    long getId() const {return msgid;}
722

    
723
    /**
724
     * Returns an identifier which is shared among a message object and all messages
725
     * created by copying it (i.e. by dup() or the copy constructor).
726
     */
727
    long getTreeId() const {return msgtreeid;}
728
    //@}
729

    
730
    /** @name Miscellaneous. */
731
    //@{
732

    
733
    /**
734
     * Override to define a display string for the message. Display string
735
     * affects message appearance in Tkenv. This default implementation
736
     * returns "".
737
     */
738
    virtual const char *getDisplayString() const;
739
    //@}
740

    
741
    /** @name Statistics. */
742
    //@{
743
    /**
744
     * Returns the total number of messages created since the last
745
     * reset (reset is usually called my user interfaces at the beginning
746
     * of each simulation run). The counter is incremented by cMessage constructor.
747
     * Counter is <tt>signed</tt> to make it easier to detect if it overflows
748
     * during very long simulation runs.
749
     * May be useful for profiling or debugging memory leaks.
750
     */
751
    static long getTotalMessageCount() { return AO_load(&total_msgs);}
752

    
753
    /**
754
     * Returns the number of message objects that currently exist in the
755
     * program. The counter is incremented by cMessage constructor
756
     * and decremented by the destructor.
757
     * May be useful for profiling or debugging memory leaks caused by forgetting
758
     * to delete messages.
759
     */
760
    static long getLiveMessageCount() {return AO_load(&live_msgs);}
761

    
762
    /**
763
     * Reset counters used by getTotalMessageCount() and getLiveMessageCount().
764
     */
765
    static void resetMessageCounters()  {
766
        AO_store(&total_msgs, 0);
767
        AO_store(&live_msgs, 0);
768
    }
769
    //@}
770
};
771

    
772

    
773
/**
774
 * A subclass of cMessage that can be used to represent packets (frames,
775
 * datagrams, application messages, etc). cPacket adds length (measured in
776
 * bits or bytes), bit error flag, and encapsulation capability to cMessage.
777
 * Length and bit error flag are significant when the packet travels through
778
 * a cDatarateChannel or another channel that supports data rate and/or
779
 * error modelling.
780
 *
781
 * cPacket is rarely used "as is". Typically the user wants to subclass it
782
 * to create specific packet types for various protocols being modelled.
783
 * The most convenient way to do that are via message declaration files
784
 * (.msg), which are translated into C++ classes.
785
 * An example message declaration:
786
 *
787
 * \code
788
 * packet Datagram
789
 * {
790
 *     int destAddr = -1; // destination address
791
 *     int srcAddr = -1;  // source address
792
 *     int ttl =  32;     // time to live
793
 * }
794
 * \endcode
795
 *
796
 * @see cSimpleModule, cDatarateChannel, cPacketQueue
797
 *
798
 * @ingroup SimCore
799
 */
800
class SIM_API cPacket : public cMessage
801
{
802
  private:
803
    enum {
804
        FL_ISRECEPTIONSTART = 4,
805
        FL_BITERROR = 8,
806
    };
807
    int64 len;            // length of the packet in bits -- used for bit error and transmission delay modeling
808
    simtime_t duration;   // transmission duration on last channel with datarate
809
    cPacket *encapmsg;    // ptr to the encapsulated message
810
    unsigned short sharecount; // num of messages MINUS ONE that have this message encapsulated.
811
                               // 0: not shared (not encapsulated or encapsulated in one message);
812
                               // 1: shared once (shared among two messages);
813
                               // 2: shared twice (shared among three messages); etc.
814
                               // on reaching max sharecount a new packet gets created
815

    
816
  public:
817
    // internal: sets the message duration; called by channel objects and sendDirect
818
    void setDuration(simtime_t d) {duration = d;}
819

    
820
    // internal: sets the isReceptionStart() flag
821
    void setReceptionStart(bool b) {setFlag(FL_ISRECEPTIONSTART, b);}
822

    
823
    // internal convenience method: returns the getId() of the innermost encapsulated message,
824
    // or itself if there is no encapsulated message
825
    long getEncapsulationId() const;
826

    
827
    // internal convenience method: returns getTreeId() of the innermost encapsulated message,
828
    // or itself if there is no encapsulated message
829
    long getEncapsulationTreeId() const;
830

    
831
    // internal: if encapmsg is shared (sharecount>0), creates a private copy for this packet,
832
    // and in any case it sets encapmsg's owner to be this object. This method
833
    // has to be called before any operation on encapmsg, to prevent trouble
834
    // that may arise from accessing shared message instances. E.g. without calling
835
    // _detachEncapMsg(), encapmsg's ownerp is unpredictable (may be any previous owner,
836
    // possibly not even existing any more) which makes even a call to its getFullPath()
837
    // method dangerous.
838
    void _detachEncapMsg();
839

    
840
    // internal: delete encapmsg, paying attention to its sharecount (assumes encapmsg!=NULL)
841
    void _deleteEncapMsg();
842

    
843
    // internal: only to be used by test cases
844
    int getShareCount() const {return sharecount;}
845

    
846
  public:
847
    /** @name Constructors, destructor, assignment */
848
    //@{
849
    /**
850
     * Copy constructor.
851
     */
852
    cPacket(const cPacket& packet);
853

    
854
    /**
855
     * Constructor. It takes the packet name, message kind value, and the
856
     * packet length in bits; all optional.
857
     */
858
    explicit cPacket(const char *name=NULL, short kind=0, int64 bitLength=0);
859

    
860
    /**
861
     * Destructor
862
     */
863
    virtual ~cPacket();
864

    
865
    /**
866
     * Assignment operator. Duplication and the assignment operator work all right with cPacket.
867
     * The name member is not copied; see cNamedObject's operator=() for more details.
868
     */
869
    cPacket& operator=(const cPacket& packet);
870
    //@}
871

    
872
    /** @name Redefined cObject member functions. */
873
    //@{
874

    
875
    /**
876
     * Creates and returns an exact copy of this object.
877
     * See cObject for more details.
878
     */
879
    virtual cPacket *dup() const  {return new cPacket(*this);}
880

    
881
    /**
882
     * Produces a one-line description of the object's contents.
883
     * See cObject for more details.
884
     */
885
    virtual std::string info() const;
886

    
887
    /**
888
     * Produces a multi-line description of the object's contents.
889
     * See cObject for more details.
890
     */
891
    virtual std::string detailedInfo() const;
892

    
893
    /**
894
     * Calls v->visit(this) for each contained object.
895
     * See cObject for more details.
896
     */
897
    virtual void forEachChild(cVisitor *v);
898

    
899
    /**
900
     * Serializes the object into an MPI send buffer
901
     * Used by the simulation kernel for parallel execution.
902
     * See cObject for more details.
903
     */
904
    virtual void parsimPack(cCommBuffer *buffer);
905

    
906
    /**
907
     * Deserializes the object from an MPI receive buffer
908
     * Used by the simulation kernel for parallel execution.
909
     * See cObject for more details.
910
     */
911
    virtual void parsimUnpack(cCommBuffer *buffer);
912

    
913
    /**
914
     * Returns true.
915
     */
916
    virtual bool isPacket() const {return true;}
917
    //@}
918

    
919
    /** @name Length and bit error flag */
920
    //@{
921
    /**
922
     * Sets packet length (in bits). When the packet is sent through a
923
     * channel, packet length affects the transmission duration and the
924
     * probability of setting the bit error flag.
925
     */
926
    virtual void setBitLength(int64 l);
927

    
928
    /**
929
     * Sets packet length (bytes). This is just a convenience function which
930
     * invokes setBitLength() with 8*l as argument. The caller must take care
931
     * that the result does not overflow (i.e. fits into an int64).
932
     */
933
    void setByteLength(int64 l)  {setBitLength(l<<3);}
934

    
935
    /**
936
     * Changes packet length by the given value (bits). This is useful for
937
     * modeling encapsulation/decapsulation. (See also encapsulate() and
938
     * decapsulate().) The caller must take care that the result does not
939
     * overflow (i.e. fits into an int64).
940
     *
941
     * The value may be negative (packet length may be decreased too).
942
     * If the resulting length would be negative, the method throws a
943
     * cRuntimeError.
944
     */
945
    virtual void addBitLength(int64 delta);
946

    
947
    /**
948
     * Changes packet length by the given value (bytes). This is just a
949
     * convenience function which invokes addBitLength() with 8*l as argument.
950
     * The caller must take care that the result does not overflow (i.e.
951
     * fits into an int64).
952
     */
953
    void addByteLength(int64 delta)  {addBitLength(delta<<3);}
954

    
955
    /**
956
     * Returns the packet length (in bits).
957
     */
958
    virtual int64 getBitLength() const  {return len;}
959

    
960
    /**
961
     * Returns the packet length in bytes, that is, bitlength/8. If bitlength
962
     * is not a multiple of 8, the result is rounded up.
963
     */
964
    int64 getByteLength() const  {return (len+7)>>3;}
965

    
966
    /**
967
     * Sets the bit error flag.
968
     */
969
    virtual void setBitError(bool e) {setFlag(FL_BITERROR,e);}
970

    
971
    /**
972
     * Returns the bit error flag.
973
     */
974
    virtual bool hasBitError() const {return flags&FL_BITERROR;}
975
    //@}
976

    
977
    /** @name Message encapsulation. */
978
    //@{
979

    
980
    /**
981
     * Encapsulates packet in the packet. The packet length gets increased
982
     * by the length of the encapsulated packet.
983
     *
984
     * IMPORTANT NOTE: IT IS FORBIDDEN TO KEEP A POINTER TO A MESSAGE
985
     * AFTER IT WAS ENCAPSULATED. For performance reasons, encapsulated
986
     * packets are reference counted, meaning that the encapsulated
987
     * packet is not duplicated when you duplicate a packet, but rather,
988
     * both (all) copies share the same packet instance. Any change done
989
     * to the encapsulated packet would affect other packets as well.
990
     * Decapsulation (and even calling getEncapsulatedPacket()) will create an
991
     * own (non-shared) copy of the packet.
992
     */
993
    virtual void encapsulate(cPacket *packet);
994

    
995
    /**
996
     * Decapsulates a packet from the packet object. The length of
997
     * this packet will be decreased by the length of the encapsulated
998
     * packet, except if it was zero. If the length would become
999
     * negative, cRuntimeError is thrown. If there is no encapsulated
1000
     * packet, the method returns NULL.
1001
     */
1002
    virtual cPacket *decapsulate();
1003

    
1004
    /**
1005
     * Returns a pointer to the encapsulated packet, or NULL if there
1006
     * is no encapsulated packet.
1007
     *
1008
     * IMPORTANT: see notes at encapsulate() about reference counting
1009
     * of encapsulated packets.
1010
     */
1011
    virtual cPacket *getEncapsulatedPacket() const;
1012

    
1013
    /**
1014
     * DEPRECATED. getEncapsulatedMsg() was renamed to getEncapsulatedPacket(),
1015
     * this method was left for backward compatibility.
1016
     */
1017
    _OPPDEPRECATED cPacket *getEncapsulatedMsg() const {return getEncapsulatedPacket();}
1018
    //@}
1019

    
1020
    /** @name Transmission state */
1021
    //@{
1022
    /**
1023
     * Returns the transmission duration after the packet was sent through
1024
     * a channel with data rate.
1025
     *
1026
     * @see isReceptionStart(), getArrivalTime(), cDatarateChannel
1027
     */
1028
    simtime_t_cref getDuration() const {return duration;}
1029

    
1030
    /**
1031
     * Tells whether this packet represents the start or the end of the
1032
     * reception, provided the packet has nonzero length and it travelled
1033
     * through a channel with nonzero data rate. This can be configured
1034
     * on the receiving gate (see cGate::setDeliverOnReceptionStart()).
1035
     *
1036
     * @see getArrivalTime(), getDuration(), cDatarateChannel
1037
     */
1038
    bool isReceptionStart() const {return flags & FL_ISRECEPTIONSTART;}
1039
    //@}
1040
};
1041

    
1042
#ifdef WITHOUT_CPACKET
1043
#define cMessage cPacket /* restore #define in simkerneldefs.h */
1044
#endif
1045

    
1046
NAMESPACE_END
1047

    
1048
#endif
1049

    
1050