zoukankan      html  css  js  c++  java
  • Libev源码分析01:Libev中的监视器结构(C结构体实现继承)

             在Libev的源码中,用到了一种用C实现类似C++中继承的技巧,主要是用宏和结构体实现。

             在Libev中,最关键的数据结构就是各种监视器,比如IO监视器,信号监视器等等。这些监视器的多数成员都是一样的,只有少部分成员为各自独有。这就非常类似于C++中继承的使用场景了。废话少说,代码如下(略有改动,某些宏做了展开):

    # define EV_CB_DECLARE(type) void (*cb)(struct ev_loop *loop, struct type *w, int revents);
    
    #define EV_WATCHER(type)                    
      int active;           /* private */       
      int pending;          /* private */       
      int priority;         /* private */       
      void *data;           /* rw */            
      EV_CB_DECLARE (type)  /* private */
      
    #define EV_WATCHER_LIST(type)               
      EV_WATCHER (type)                         
      struct ev_watcher_list *next; /* private */  
      
    typedef struct ev_watcher
    {
      EV_WATCHER (ev_watcher)
    } ev_watcher;  
    
    typedef struct ev_watcher_list
    {
      EV_WATCHER_LIST (ev_watcher_list)
    } ev_watcher_list;
    
    typedef struct ev_io
    {
      EV_WATCHER_LIST (ev_io)
      int fd;     /* ro */
      int events; /* ro */
    } ev_io;
    
    typedef struct ev_signal
    {
      EV_WATCHER_LIST (ev_signal)
      int signum; /* ro */
    } ev_signal;
    

             ev_watcher是所有结构的“基类”,宏EV_WATCHER定义了它的所有成员。像IO监视器、信号监视器等是以链表的形式进行组织的,所以,在ev_watcher基类的基础上,定义了ev_watcher的子类ev_watcher_list,宏EV_WATCHER_LIST就定义了该基类的所有成员。

             ev_io和ev_signal相当于ev_watcher_list的子类,它们的前5个成员于ev_watcher相同,前6个成员与ev_watcher_list相同。

             上面的代码可能还不是太清楚,下面将上面代码中的所有宏都展开,代码如下:

    # define EV_CB_DECLARE(type) void (*cb)(struct ev_loop *loop, struct type *w, int revents);
    
    #define EV_WATCHER(type)                    
      int active;           /* private */       
      int pending;          /* private */       
      int priority;         /* private */       
      void *data;           /* rw */            
      EV_CB_DECLARE (type)  /* private */
      
    #define EV_WATCHER_LIST(type)               
      int active;           /* private */       
      int pending;          /* private */       
      int priority;         /* private */       
      void *data;           /* rw */            
      EV_CB_DECLARE (type)  /* private */       
      struct ev_watcher_list *next; /* private */  
      
    typedef struct ev_watcher
    {
      int active;
      int pending;
      int priority;
      void *data;
      EV_CB_DECLARE (ev_watcher)
    } ev_watcher;  
    
    typedef struct ev_watcher_list
    {
      int active;
      int pending;
      int priority;
      void *data;
      EV_CB_DECLARE (ev_watcher_list)
      struct ev_watcher_list *next; 
    } ev_watcher_list;
    
    typedef struct ev_io
    {
      int active;
      int pending;
      int priority;
      void *data;
      EV_CB_DECLARE (ev_io)
      struct ev_watcher_list *next;
    
      int fd;     /* ro */
      int events; /* ro */
    } ev_io;
    
    typedef struct ev_signal
    {
      int active;
      int pending;
      int priority; 
      void *data;
      EV_CB_DECLARE (ev_signal)
      struct ev_watcher_list *next;
      int signum;
    } ev_signal;
    

     

    下面是Libev中如何使用这些结构体的代码:

    void ev_start (struct ev_loop *loop, ev_watcher* w, int active)
    {
      ...
      w->active = active;
      ...
    }
    
    void wlist_add (ev_watcher_list **head, ev_watcher_list *elem)
    {
      elem->next = *head;
      *head = elem;
    }
    
    void ev_io_start (struct ev_loop *loop, ev_io *w)
    {
      ...
      ev_start (loop, (ev_watcher*)w, 1);
      ...
      wlist_add (&anfds[fd].head, (ev_watcher_list *)w);
    }
    

             在ev_io_start函数中,w是指向ev_io结构的指针,使用ev_start函数设置其成员active时,将其强制转换成基类ev_watcher,在将其添加进链表时,又将其强制转化为ev_watcher_list类型。

     

            下面的代码是模拟上面的方法,写出的例子代码:

    typedef struct 
    {
        char *color;
        int weight;
    }fruit;
    
    typedef struct fruitlist
    {
        char *color;
        int weight;
        struct fruitlist *next;
    }fruitlist;
    
    typedef struct
    {
        char *color;
        int weight;
        struct fruitlist *next;
        char *taste;
    }apple;
    
    void setcolorweight(fruit *f, char *color, int weight)
    {
        f->color = color;
        f->weight = weight;
    }
    
    void putinlist(fruitlist **head, fruitlist *ele)
    {
        ele->next = *head;
        *head = ele;
    }
    void testinherit()
    {
        fruitlist *head = NULL;
    
        apple ap1;
        setcolorweight((fruit *)&ap1, "red", 2);
        ap1.taste = "sweet";
        putinlist(&head, (fruitlist *)&ap1);
    
        apple ap2;
        setcolorweight((fruit *)&ap2, "yellow", 1);
        ap2.taste = "sour";
        putinlist(&head, (fruitlist *)&ap2);
    
        fruitlist *p = head;
        while(p != NULL)
        {
            printf("color is %s, weight is %d
    ", p->color, p->weight);
            p = (fruitlist *)(p->next);
        }
    }
    

            结果如下:

    color is yellow, weight is 1

    color is red, weight is 2

  • 相关阅读:
    localStorage cache
    webpack的学习过程
    npm install --save/--save-dev的区别
    .gitignore常见问题
    jQuery的优点与缺点
    JSONP是什么
    Node.js-Usage & Example
    【转】Swig Getting Started
    【转】使用Spring MVC统一异常处理实战
    C++-Qt【5】-QT的QString,char*,QByteArray转化以及中文乱码的问题
  • 原文地址:https://www.cnblogs.com/gqtcgq/p/7247119.html
Copyright © 2011-2022 走看看