Oment++3.3源码分析1

    从今天开始分析OMNET的原代码结构,首先分析一些预定的文件。
1. def.h
 
Def.h代码分析
// OPP_DLLIMPORT/EXPORT are empty if not needed
#if defined(__WIN32__)
# define OPP_DLLEXPORT __declspec(dllexport)
# if defined(WIN32_DLL)
#    define OPP_DLLIMPORT __declspec(dllimport)
# else
#     define OPP_DLLIMPORT
# endif
#else
# define OPP_DLLIMPORT
# define OPP_DLLEXPORT
#endif
 
// SIM_API, ENVIR_API etc are also empty if not needed
#ifdef BUILDING_SIM
# define SIM_API OPP_DLLEXPORT
#else
# define SIM_API OPP_DLLIMPORT
#endif
 
// we need this because cenvir.h is in our directory
#ifdef BUILDING_ENVIR
# define ENVIR_API OPP_DLLEXPORT
#else
# define ENVIR_API OPP_DLLIMPORT
#endif
 
//=== NULL的定义
#ifndef NULL
#define NULL ((void*)0)
#endif
 
// maximum lengths for className(), fullPath() and old info(buf) strings
#define MAX_CLASSNAME        100
#define MAX_OBJECTFULLPATH 1024
#define MAX_OBJECTINFO       500
 
// in case someone still needs the old name
#define FULLPATHBUF_SIZE MAX_OBJECTFULLPATH
#ifndef NDEBUG
#define ASSERT(expr) /
 ((void) ((expr) ? 0 : /
           (opp_error("ASSERT: condition %s false, %s line %d", /
                             #expr, __FILE__, __LINE__), 0)))
#else
#define ASSERT(expr) ((void)0)
#endif
/**
 * Modelled time.
 */
typedef double       simtime_t;
#define MAXTIME   HUGE_VAL
/*HUGE_VAL是double类型所能代表的最大值,当数学函数在运行的时候发生错误的时候返回此值,有些函数返回的是-HUGE_VAL
*/
/*
这个函数的原型是用来清除用户定义的数据结构,通过调用一些对象,比如( cPar,cLinkedList
*/
typedef void (* VoidDelFunc)(void *);
typedef void *(* VoidDupFunc)(void *);//用来复制用户定义的数据结构
 
还定义了几个数学 函数原型的指针:MathFunc、MathFunc NoArg、MathFunc 1Arg、MathFunc 2Args、MathFunc 3Args、MathFunc 4Args
typedef double (*MathFunc)(...);
typedef double (*MathFuncNoArg)();
/**
 * Prototype for mathematical functions taking one argument
 * that can be used in reverse Polish expressions (see ExprElem).
 * @ingroup EnumsTypes
 */
typedef double (*MathFunc1Arg)(double);
void opp_error(int errc...)
{
    va_list va;
    va_start(va, errc);
    char message[512];
    vsprintf(message,emsg[errc],va);
    va_end(va);
    throw new cRuntimeError(errc, message);
}
void opp_error(const char *msgformat...)
{
    va_list va;
    va_start(va, msgformat);
    char message[512];
    vsprintf(message,msgformat,va);
    va_end(va);
    throw new cRuntimeError(eUSER,message);
}

 

2.NODE.H
/**
 * Represents a data element in an output vector file. Processing nodes
 * (Node) process elements of this type.
 *代表output vector 中的一个数据元素。处理节点是处理这类型的数据
 * @see Node, Channel, Port
 */
struct Datum
{
    double x;  ///< usually t simulation time
    double y;  ///< usually the value at t
};

/**
 * Connection point of channels in processing nodes.
 *信道中处理节点的连接点
 * @see Datum, Node, Channel
 */
class Port
{
    private:
        Node *ownernode;
        Channel *chan;
    public:
        Port(Node *owner) {ownernode = owner; chan = 0;}
        Port(const Port& p) {ownernode = p.ownernode; chan = p.chan;}
        ~Port() {}
        void setChannel(Channel *channel) {ASSERT(!chan); chan = channel;}
        Node *node() {return ownernode;}
        Channel *channel() const  {return chan;}
        Channel *operator()() const {ASSERT(chan); return chan;}
};

/**
 * Processing node. Processing nodes can be connected via ports and channels
 * to form a data flow network.
 *
 * @see DataflowManager, Port, Channel, Datum, NodeType
 */
class Node
{
        friend class DataflowManager;

    private:
        DataflowManager *mgr;
        NodeType *nodetype;
        bool alreadyfinished;
部分重要的函数:
 /** Execution and scheduling */
        //@{
        /**
         * Do some amount of work, then return
         */
        virtual void process() = 0;
        /**
         * Are more invocations if process() necessary()?
         */
        virtual bool finished() const = 0;
       /**
         * Provided it has not finished() yet, can process() be invoked
         * right now? (finished() is called first -- isReady() is only
         * invoked if finished() returns false. So isReady() doesn't need
         * to check for eof.)
         */
        virtual bool isReady() const = 0;
        //@}

        /**
         * Invoked by the dataflow manager when the node's finished() first
         * returns true. It sets a status flag so that further invocations
         * of finished() can be avoided.
         */
        void setAlreadyFinished() {alreadyfinished = true;}

        /**
         * Used by the dataflow manager. Returns true if setAlreadyFinished()
         * has already been invoked.
         */
        bool alreadyFinished() {return alreadyfinished;}

 

3.CHANNEL.H
这个文件基本上是模拟生产者和消费者问题写的。
/**
 * Does buffering between two processing nodes (Node).
 *
 * @see Node, Port, Datum,Datum的定义是在node.h中
 */
class Channel
{
    private:
        // note: a Channel should *never* hold a pointer back to its Ports
        // because ports may be copied after having been assigned to channels
        // (e.g. in VectorFileReader which uses std::vector). Node ptrs are OK.
        std::deque<Datum> buffer;   //注意,如果这里定义的是std::deque<Datum *>buffer的话,删除时要小心(删除容器中的指针是一个必须非常小心的事情
        Node *producernode;
        Node *consumernode;
        bool producerfinished;
        bool consumerfinished;
    public:
       Node *producerNode() const {return producernode;}
        void setProducerNode(Node *node) {producernode = node;}

        Node *consumerNode() const {return consumernode;}
        void setConsumerNode(Node *node) {consumernode = node;}

        /**
         * Returns ptr to the first buffered data item (next one to be read), or NULL
         */
        const Datum *peek() const
        {
             if (buffer.size()==0)
                 return NULL;
             return &(buffer.front());
        }
        int Channel::read(Datum *a, int max)
        {
                ASSERT(!consumerfinished);
               int n = buffer.size();
              if (n>max)
                    n = max;
              for (int i=0; i<n; i++)
              {
                   a[i] = buffer.front();
                   buffer.pop_front();
             }
              return n;
         }
        void Channel::write(Datum *a, int n)
        {
               ASSERT(!producerfinished);
              if (consumerfinished)
                        return;  // discard data if consumer finished
              for (int i=0; i<n; i++)
                    buffer.push_back(a[i]);
        }
        /**
         * Returns true if producer has already called close() which means
         * there won't be any more data except those already in the buffer
         */
        bool closing()  {return producerfinished;}

        /**
         * Returns true if close() has been called and there's no buffered data
         */
        bool eof()  {return producerfinished && length()==0;}

        /**
         * Called by the producer to declare it will not write any more --
         * if also there's no more buffered data (length()==0), that means EOF.
         */
        void close()  {producerfinished=true;}

        /**
         * Called when consumer has finished. Causes channel to ignore
         * further writes (discard any data written).
         */
        void consumerClose() {buffer.clear();consumerfinished=true;}

        /**
         * Returns true when the consumer has closed the channel, that is,
         * it will not read any more data from the channel.
         */
        bool consumerClosed() {return consumerfinished;}

        /**
         * Number of currently buffered items.
         */
        int length() {return buffer.size();}
};

4.NODETYPE
class Node;
class Port;
typedef std::map<std::string,std::string> StringMap;  //这是一个全局变量
/**
 * Describes properties of a node class.
 *
 * @see Node, NodeTypeRegistry
 */
class NodeType
{
    protected:
        void checkAttrNames(const StringMap& attr) const
        {
               StringMap allowedAttrs;
               getAttributes(allowedAttrs);
               // are there illegal attributes?
              for (StringMap::const_iterator it=attrs.begin(); it!=attrs.end(); ++it)
              {
                    const char *attr = it->first.c_str();
                    StringMap::iterator j = allowedAttrs.find(attr);
                    if (j==allowedAttrs.end())
                           throw new Exception("illegal attribute `%s'", attr);
              }
              // do we have all attributes?
              for (StringMap::const_iterator i=allowedAttrs.begin(); i!=allowedAttrs.end(); ++i)
              {
                    const char *attr = i->first.c_str();
                    StringMap::const_iterator it = attrs.find(attr);
                    if (it==attrs.end())
                          throw new Exception("missing attribute `%s'", attr);
              }
    public:
        NodeType() {}
        virtual ~NodeType() {}
        /**
         * Returns type name as displayed on the UI (e.g. "mean" or "winavg")
         *返回显示在UI上的类型的名字
         */
        virtual const char *name() const = 0;
        /**
         * Returns the category of the node (source, sink, filter, etc.)
        * 返回节点类型的种类(比如source, sink, filter等等)
         */
        virtual const char *category() const = 0;

        /**
         * Returns the description of the node (this can be displayed on the UI.)
         */
        virtual const char *description() const = 0;

        /**
         * Returns true if this node should appear in the UI.
         * 如果节点是显示在UI上的,那么返回真
         */
        virtual bool isHidden() const = 0;

        /**
         * Fills the string map with attribute names and their descriptions.
         */
        virtual void getAttributes(StringMap& attrs) const = 0;

        /**
         * Fills the string map with attribute names and their default values.
         * (Doesn't necessarily supply default value for every attribute).
         */
        virtual void getAttrDefaults(StringMap& attrs) const {}

        /**
         * Throws exception if something is not OK. The message in the
         * exception is shown to the user.
         */
        virtual void validateAttrValues(const StringMap& attrs) const {}

        /**
         * Create a node instance of this type.
         */
        virtual Node *create(DataflowManager *, StringMap& attrs) const = 0;

        /**
         * Get the named port of the give node instance.
         */
        virtual Port *getPort(Node *node, const char *portname) const = 0;
};

你可能感兴趣的:(Oment++3.3源码分析1)