C-libev learning notes - event library source code Reading-1

Posted by flhtc on Mon, 13 Sep 2021 23:24:02 +0200

features

libev is a lightweight event driven library written in C language, which supports a variety of IO reuse interfaces.
IO interfaces include: select, poll, epoll, kqueue, etc

Supported events:

ev_io; //IO read / write
ev_stat; //File properties
ev_signal;//signal
ev_timer;//timer
ev_periodic;//Absolute timer
ev_child;//Subprocess
ev_fork;//fork event
ev_cleanup;//ev_loop exit trigger
ev_idle;//ev_loop idle trigger
ev_embed;//Embedded background loop
ev_prepare;//ev_ Events before loop
ev_check;//ev_ Event after loop
ev_async;//Asynchronous events between threads

Please refer to the previous articles for examples. The comments are very detailed

monitor

libev encapsulates events in the monitor watcher, which is a structure that holds information related to events, including event properties.
You can use it by registering the watcher and specifying its callback function, and then registering the monitor with the drive.

Common macros

EV_P,EV_P_,EV_A,EV_A_
The following code is from ev. H < 171 >

  /* support multiple event loops? */
#if EV_MULTIPLICITY
struct ev_loop;
# define EV_P  struct ev_loop *loop               /* a loop as sole parameter in a declaration */
# define EV_P_ EV_P,                              /* a loop as first of multiple parameters */
# define EV_A  loop                               /* a loop as sole argument to a function call */
# define EV_A_ EV_A,                              /* a loop as first of multiple arguments */
# define EV_DEFAULT_UC  ev_default_loop_uc_ ()    /* the default loop, if initialised, as sole arg */
# define EV_DEFAULT_UC_ EV_DEFAULT_UC,            /* the default loop as first of multiple arguments */
# define EV_DEFAULT  ev_default_loop (0)          /* the default loop as sole arg */
# define EV_DEFAULT_ EV_DEFAULT,                  /* the default loop as first of multiple arguments */
#else
# define EV_P void
# define EV_P_
# define EV_A
# define EV_A_
# define EV_DEFAULT
# define EV_DEFAULT_
# define EV_DEFAULT_UC
# define EV_DEFAULT_UC_
# undef EV_EMBED_ENABLE
#endif

EV_MULTIPLICITY is obviously a condition, which literally means multiple events
Indicates when multiple EVs are allowed_ Loop sample exists
ev_loop is the main loop. In the previous examples, it is declared:

ev_loop* main_loop;

Look at the #if section, there are some wonderful macro definitions.

# define EV_P  struct ev_loop *loop ;// Use EV_P instead of struct ev_loop *loop
//In other words, it can be written as follows:
void fun(EV_P, ev_io io_w);

# define EV_P_ EV_P,  ;// This definition should pay special attention to the comma ',' 
//In other words, add a comma and write as follows:
void fun(EV_P_ ev_io io_w); //Yes, it just saves a comma and looks more like a veteran

Other parts are similar.
For #else the part, it is a normal macro definition. The first parameter is to replace it with null, that is, delete it

Event related macros

libev defines events that are easy to understand. They are all shaped like ev_xxx, xxx is the event name, such as ev_io,ev_timer
Because C language does not have the concept of class, what do you want to do to realize polymorphism?
The concept of polymorphism will not be repeated, and the realization of C is nothing more than some miscellaneous struct s and some macro definitions.

These monitors all contain the same macro EV_WATCHER(type)
The specific definition of this macro is as follows:

/* shared by all watchers */
#define EV_WATCHER(type)			\
  int active; /* private */			\
  int pending; /* private */			\
  EV_DECL_PRIORITY /* private */		\
  EV_COMMON /* rw */				\
  EV_CB_DECLARE (type) /* private */

#define EV_WATCHER_LIST(type)			\
  EV_WATCHER (type)				\
  struct ev_watcher_list *next; /* private */

#define EV_WATCHER_TIME(type)			\
  EV_WATCHER (type)				\
  ev_tstamp at;     /* private */

Understanding these macros requires some #define advanced knowledge.

Never mind what these three lines mean

  EV_DECL_PRIORITY /* private */		\
  EV_COMMON /* rw */				\
  EV_CB_DECLARE (type) /* private */

Understandably, ev_ Watch (type) contains five items:

  int active; /* private */			\
  int pending; /* private */			\
  EV_DECL_PRIORITY /* private */		\
  EV_COMMON /* rw */				\
  EV_CB_DECLARE (type) /* private */

Let's look at the specific monitor. The definition of watcher:

/* base class, nothing to see here unless you subclass */
typedef struct ev_watcher
{
  EV_WATCHER (ev_watcher)
} ev_watcher;

Comments on the header of this Code: / * base class, nothing to see here unless you subclass * /, it can be seen that this is an abstract implementation class, so to understand the source code, you must learn the idea of object-oriented.

Visible ev_ The watcher contains ev_ Watch (type), in fact, the combination of the two is as follows:

typedef struct ev_watcher
{
    int active; 
    int pending;
    EV_DECL_PRIORITY /* private */		\
  	EV_COMMON /* rw */				\
  	EV_CB_DECLARE (ev_watcher) /* private */
} ev_watcher;

What does the last three digits mean? You should also find the specific macro definition.

The first macro is defined here:

#if EV_MINPRI == EV_MAXPRI
# define EV_DECL_PRIORITY
#elif !defined (EV_DECL_PRIORITY)
# define EV_DECL_PRIORITY int priority;
#endif

Two more macro EVs came out_ MINPRI,EV_ Maxpri, no matter what, this statement is read as if else
Overall, EV_DECL_PRIORITY is int priority;

I won't go into detail. Go straight to code

#ifndef EV_COMMON
# define EV_COMMON void *data;
#endif

#ifndef EV_CB_DECLARE
# define EV_CB_DECLARE(type) void (*cb)(EV_P_ struct type *w, int revents);
#endif

So finally, the watcher is legendary!: This thing is just a structure that defines some content.

typedef struct ev_watcher
{
    int active; 
    int pending;
    int priority;
    void *data;    
    void (*cb)(struct ev_loop *loop, struct ev_watcher *w, int revents);
} ev_watcher;

ok, after analyzing the contents of the watcher monitor, the EV_ Watch also comes with a macro definition of list and time. Let's analyze it again, ev_ The list and time parts are also defined in the watcher, as follows:

/* base class, nothing to see here unless you subclass */
typedef struct ev_watcher_list
{
  EV_WATCHER_LIST (ev_watcher_list)
} ev_watcher_list;

/* base class, nothing to see here unless you subclass */
typedef struct ev_watcher_time
{
  EV_WATCHER_TIME (ev_watcher_time)
} ev_watcher_time;

According to the above example, the expansion is as follows:

typedef struct ev_watcher_list
{
    int active; 
    int pending;
    int priority;
    void *data;    
    void (*cb)(struct ev_loop *loop, struct ev_watcher_list *w, int revents);
    struct ev_watcher_list *next;
} ev_watcher_list;

typedef struct ev_watcher_time
{
    int active; 
    int pending;
    int priority;
    void *data;    
    void (*cb)(struct ev_loop *loop, struct ev_watcher_time *w, int revents);

    ev_tstamp at;
} ev_watcher_time;

The following macros are analyzed:

Topics: C C++