Revision fbe00e73 include/csimplemodule.h

View differences:

include/csimplemodule.h
12 12
/*--------------------------------------------------------------*
13 13
  Copyright (C) 1992-2008 Andras Varga
14 14
  Copyright (C) 2006-2008 OpenSim Ltd.
15
  Copyright (C) 2009 Georg Kunz
15 16

  
16 17
  This file is distributed WITHOUT ANY WARRANTY. See the file
17 18
  `license' for details on this and other legal matters.
......
20 21
#ifndef __CSIMPLEMODULE_H
21 22
#define __CSIMPLEMODULE_H
22 23

  
24
#include <pthread.h>
25
#include <semaphore.h>
26

  
23 27
#include "cmodule.h"
24 28
#include "cnumgen.h"
25 29

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

  
26 36
NAMESPACE_BEGIN
27 37

  
28 38
class cQueue;
......
79 89
    static bool stack_cleanup_requested; // 'true' value asks activity() to throw a cStackCleanupException
80 90
    static cSimpleModule *after_cleanup_transfer_to; // transfer back to this module (or to main)
81 91

  
92
  private: // Horizon
93
    // the two different execution states: either handleMessage is called
94
    // synchronously by the scheduler or asynchronously (to the scheduler)
95
    // by a worker thread
96
    enum ExecutionStates
97
    {
98
        synchronous,
99
        asynchronous
100
    };
101

  
102
    // current state of execution
103
    ExecutionStates executionState;
104

  
105
    // new messages may only be scheduled with timestamps >= this value
106
    simtime_t t_end;
107

  
108
    // priority of the current event
109
    short currentEventPriority;
110

  
111
    // shall zero duration events be executed in parallel
112
    bool parZeroDur;
113

  
114
    // no worker is active inside this module
115
    static const AO_t NOT_BUSY = 0;
116

  
117
    // a worker is active inside this module
118
    static const AO_t BUSY     = 1;
119

  
120
    // flag indicating that a thread is processing an event within this module
121
    AO_t busy;
122

  
123
    // how many messages did a given event send?
124
    unsigned int scheduledMessageCount;
125

  
126
    //
127
    unsigned int executionOrderId;
128

  
129
    // current simulation time within this module
130
    simtime_t now;
131

  
132
    /**
133
     * update meta data needed for event execution
134
     */
135
    void prepareHandleMessage(cMessage* msg);
136

  
137
    /**
138
     * set extended meta data of a message upon sending.
139
     */
140
    void setMessageMetaData(cMessage* msg);
141

  
82 142
  private:
83 143
    // internal use
84 144
    static void activate(void *p);
......
141 201
    virtual ~cSimpleModule();
142 202
    //@}
143 203

  
144
    /*
145
     * Returns true if Module is capable of Horizon specific parallel execution
146
     * Called in doOneEvent
147
     * Overridden in cAsyncmodule
148
     */
149
    virtual bool isAsyncModule() const {
150
    	return false;
151
    }
152

  
153 204
    /** @name Redefined cObject member functions. */
154 205
    //@{
155 206
    /**
......
232 283
    /**
233 284
     * Sends a message through the gate given with its ID.
234 285
     */
235
    int send(cMessage *msg, int gateid)  {return sendDelayed(msg, SIMTIME_ZERO, gateid);}
286
    int send(cMessage *msg, int gateid);
236 287

  
237 288
    /**
238 289
     * Sends a message through the gate given with its name and index
239 290
     * (if multiple gate).
240 291
     */
241
    int send(cMessage *msg, const char *gatename, int gateindex=-1)  {return sendDelayed(msg, SIMTIME_ZERO, gatename, gateindex);}
292
    int send(cMessage *msg, const char *gatename, int gateindex=-1);
242 293

  
243 294
    /**
244 295
     * Sends a message through the gate given with its pointer.
245 296
     */
246
    int send(cMessage *msg, cGate *outputgate)  {return sendDelayed(msg, SIMTIME_ZERO, outputgate);}
297
    int send(cMessage *msg, cGate *outputgate);
247 298

  
248 299
    /**
249 300
     * Delayed sending. Sends a message through the gate given with
......
487 538
     * @see cCoroutine
488 539
     */
489 540
    virtual unsigned getStackUsage() const;
490
    //@}
541

  
542
  public: // Horizon
543
    /** @name User-implemented methods for asynchronous event handling. */
544
    //@{
545
    /**
546
     * Returns the duration of the given expanded event. Called by the event
547
     * scheduler to determine the overlapping of expanded events. The user may
548
     * perform any computation on the expanded event (except for deleting it)
549
     * to calculate the event duration.
550
     */
551
    virtual simtime_t getProcessingDelay(cMessage* msg)
552
    {
553
        return 0.0;
554
    }
555

  
556
    /*
557
     * By default non-expanded events are not executed in parallel. The
558
     * option "parallelize-zero-duration-events" globally enables or disables
559
     * parallel execution. This method allows users to overwrite either behavior
560
     * on a per module (and per event) basis. Should return true if parallel
561
     * execution is allowed, false otherwise.
562
     */
563
    virtual bool mayParallelize(cMessage* msg, simtime_t duration) const
564
    {
565
        return duration == SimTime::simTimeZero ? parZeroDur : true;
566
    }
567
    /*
568
     * Initializes the local RNGs according to config options read from ini
569
     */
570
    void initLocalRNGs();
571
    //}@
572

  
573

  
574
    /** @name Support methods for asynchronous event handling. */
575
    //@{
576
    /**
577
     * Returns the duration of the currently processed event.
578
     */
579
    simtime_t getCurrentProcessingDelay() const {
580
        return t_end - simTime();
581
    }
582

  
583
    /** @name Wrapper functions for state keeping inside a module. */
584
    //@{
585
    /**
586
     * INTERNAL: Wrapper for asynchronous message handling.
587
     */
588
    void callHandleAsyncMessage(cMessage* msg);
589

  
590
    /**
591
     * INTERNAL: Wrapper for synchronous message handling.
592
     */
593
    void callHandleMessage(cMessage* msg);
594

  
595
    /*
596
     * INTERNAL: Check if a worker thread is already busy inside this module
597
     * and if so, wait until the worker is done.
598
     */
599
    inline void waitIfBusy() {
600
        while (AO_load_full(&busy) == BUSY) {
601
            __asm__("pause");
602
        }
603
    }
604

  
605
    /*
606
     * INTERNAL: Indicate that a worker is busy inside this module.
607
     */
608
	inline void setBusy() {
609
		AO_store_full(&busy, BUSY);
610
	}
611

  
612
	/**
613
	 * INTERNAL: Unset flag to indicate that a worker has finished.
614
	 */
615
	inline void unsetBusy() {
616
		AO_store_full(&busy, NOT_BUSY);
617
	}
618
    //}@r
619

  
620
   //@}
491 621
};
492 622

  
493 623
NAMESPACE_END

Also available in: Unified diff