Libevent——event_base

Creating an event_base

Each event_base structure holds a set ofevents and can poll to determine which events are active.

f an event_base is set up to use locking, it is safe to access it betweenmultiple threads. Its loop can only be run in a single thread, however. Ifyou want to have multiple threads polling for IO, you need to have anevent_base for each thread.

Tip [A future version of Libevent may have support for event_bases that runevents across multiple threads.]

Each event_base has a "method", or a backend that it uses to determine whichevents are ready. The recognized methods are:
  • select

  • poll

  • epoll

  • kqueue

  • devpoll

  • evport

  • win32

The user can disable specific backends with environment variables. If youwant to turn off the kqueue backend, set the EVENT_NOKQUEUE environmentvariable, and so on. If you want to turn off backends from within theprogram, see notes on event_config_avoid_method() below.

Setting up a default event_base

The event_base_new() function allocates and returns a new event base withthe default settings.

It examines the environment variables and returnsa pointer to a new event_base. If there is an error, it returns NULL.

When choosing among methods, it picks the fastest method that the OSsupports.

Interface
struct event_base *event_base_new(void);

Setting up a complicated event_base

If you want more control over what kind of event_base you get, you need touse an event_config. An event_config is an opaque structure that holdsinformation about your preferences for an event_base. When you want anevent_base, you pass the event_config to event_base_new_with_config().

Interface
struct event_config   *event_config_new( void );
struct event_base     *event_base_new_with_config( const  struct  event_config  *cfg );
void   event_config_free( struct  event_config  *cfg );
To allocate an event_base with these functions, you call event_config_new()to allocate a new event_config.

Then, you call other functions on theevent_config to tell it about your needs.

Finally, you call event_base_new_with_config() to get a new event_base.

When you are done,you can free the event_config with event_config_free().

Calling event_config_avoid_method tells Libevent to avoid a specificavailable backend by name.

Calling event_config_require_feature() tellsLibevent not to use any backend that cannot supply all of a set of features.

Calling event_config_set_flag() tells Libevent to set one or more ofthe run-time flags below when constructing the event base.

The recognized feature values for event_config_require_features are:

EV_FEATURE_ET

Requires a backend method that supports edge-triggered IO.//边沿触发IO方式

EV_FEATURE_O1

Requires a backend method where adding or deleting a single event, or having a single event become active, is an O(1) operation.

EV_FEATURE_FDS

Requires a backend method that can support arbitrary file descriptor types, and not just sockets.

The recognized option values for event_config_set_flag() are:

EVENT_BASE_FLAG_NOLOCK

Do not allocate locks for the event_base. Setting this option may save a little time for locking and releasing the event_base, but will make it unsafe and nonfunctional to access it from multiple threads.

EVENT_BASE_FLAG_IGNORE_ENV

Do not check the EVENT_* environment variables when picking which backend method to use. Think hard before using this flag: it can make it harder for users to debug the interactions between your program and Libevent.//忽略event环境变量

EVENT_BASE_FLAG_STARTUP_IOCP

On Windows only, this flag makes Libevent enable any necessary IOCP dispatch logic on startup, rather than on-demand.

EVENT_BASE_FLAG_NO_CACHE_TIME

Instead of checking the current time every time the event loop is ready to run timeout callbacks, check it after every timeout callback.

This can use more CPU than you necessarily intended, so watch out!

//当发生timeout callback信号时,先检测当前时间(默认);执行完timeout callback后,在再去检测当前时间(当前关键字设置 

EVENT_BASE_FLAG_EPOLL_USE_CHANGELIST

Tells Libevent that, if it decides to use the epoll backend, it is safe to use the faster "changelist"-based backend. The epoll-changelist backend can avoid needless system calls in cases where the same fd has its status modified more than once between calls to the backend’s dispatch function, but it also trigger a kernel bug that causes erroneous results if you give Libevent any fds cloned by dup() or its variants. This flag has no effect if you use a backend other than epoll. You can also turn on the epoll-changelist option by setting the EVENT_EPOLL_USE_CHANGELIST environment variable.

EVENT_BASE_FLAG_PRECISE_TIMER

By default, Libevent tries to use the fastest available timing mechanism that the operating system provides. If there is a slower timing mechanism that provides more fine-grained timing precision, this flag tells Libevent to use that timing mechanism instead. If the operating system provides no such slower-but-more-precise mechanism, this flag has no effect.

The above functions that manipulate an event_config all return 0 on success,-1 on failure.

Note
It is easy to set up an event_config that requires a backend that yourOS does not provide. For example, as of Libevent 2.0.1-alpha, there is noO(1) backend for Windows, and no backend on Linux that provides bothEV_FEATURE_FDS and EV_FEATURE_O1. If you have made a configuration thatLibevent can’t satisfy, event_base_new_with_config() will return NULL.

Interface
int event_config_set_num_cpus_hint(struct event_config *cfg, int cpus)

This function is currently only useful with Windows when using IOCP, thoughit may become useful for other platforms in the future. Calling it tells theevent_config that the event_base it generates should try to make good use ofa given number of CPUs when multithreading. Note that this is only a hint:the event base may wind up using more or fewer CPUs than you select.

Interface
int event_config_set_max_dispatch_interval(struct event_config *cfg,
    const struct timeval *max_interval, int max_callbacks,
    int min_priority);

This function prevents priority inversion by limiting how many low-priorityevent callbacks can be invoked before checking for more high-priority events.If max_interval is non-null, the event loop checks the time after eachcallback, and re-scans for high-priority events if max_interval has passed.If max_callbacks is nonnegative, the event loop also checks for more eventsafter max_callbacks callbacks have been invoked. These rules apply to anyevent of min_priority or higher.

Example: Preferring edge-triggered backends
struct event_config *cfg;
struct event_base *base;
int i;

/* My program wants to use edge-triggered events if at all possible.  So
   I'll try to get a base twice: Once insisting on edge-triggered IO, and
   once not. */
for (i=0; i<2; ++i) {
    cfg = event_config_new();

    /* I don't like select. */
    event_config_avoid_method(cfg, "select");

    if (i == 0)
        event_config_require_features(cfg, EV_FEATURE_ET);

    base = event_base_new_with_config(cfg);
    event_config_free(cfg);
    if (base)
        break;

    /* If we get here, event_base_new_with_config() returned NULL.  If
       this is the first time around the loop, we'll try again without
       setting EV_FEATURE_ET.  If this is the second time around the
       loop, we'll give up. */
}
Example: Avoiding priority-inversion
struct event_config *cfg;
struct event_base *base;

cfg = event_config_new();
if (!cfg)
   /* Handle error */;

/* I'm going to have events running at two priorities.  I expect that
   some of my priority-1 events are going to have pretty slow callbacks,
   so I don't want more than 100 msec to elapse (or 5 callbacks) before
   checking for priority-0 events. */
struct timeval msec_100 = { 0, 100*1000 };
event_config_set_max_dispatch_interval(cfg, &msec_100, 5, 1);

base = event_base_new_with_config(cfg);
if (!base)
   /* Handle error */;

event_base_priority_init(base, 2);

These functions and types are declared in <event2/event.h>.

The EVENT_BASE_FLAG_IGNORE_ENV flag first appeared in Libevent 2.0.2-alpha.The EVENT_BASE_FLAG_PRECISE_TIMER flag first appeared in Libevent2.1.2-alpha. The event_config_set_num_cpus_hint() function was new in Libevent2.0.7-rc, and event_config_set_max_dispatch_interval() was new in 2.1.1-alpha.Everything else in this section first appeared in Libevent 2.0.1-alpha.

Examining an event_base’s backend method

Sometimes you want to see which features are actually available in anevent_base, or which method it’s using.

Interface
const char **event_get_supported_methods(void);

The event_get_supported_methods() function returns a pointer to an array ofthe names of the methods supported in this version of Libevent.

Thelast element in the array is NULL.

Example
int i;
const char **methods = event_get_supported_methods();
printf("Starting Libevent %s.  Available methods are:\n",
    event_get_version());
for (i=0; methods[i] != NULL; ++i) {
    printf("    %s\n", methods[i]);
}
Note
This function returns a list of the methods that Libevent was compiledto support. It is possible that your operating system will not in factsupport them all when Libevent tries to run. For example, you could be on aversion of OSX where kqueue is too buggy to use.
Interface
const char *event_base_get_method(const struct event_base *base);
enum event_method_feature event_base_get_features(const struct event_base *base);

The event_base_get_method() call returns the name of the actual method in useby an event_base.

The event_base_get_features() call returns a bitmask ofthe features that it supports.

Example
struct event_base *base;
enum event_method_feature f;

base = event_base_new();
if (!base) {
    puts("Couldn't get an event_base!");
} else {
    printf("Using Libevent with backend method %s.",
        event_base_get_method(base));
    f = event_base_get_features(base);
    if ((f & EV_FEATURE_ET))
        printf("  Edge-triggered events are supported.");
    if ((f & EV_FEATURE_O1))
        printf("  O(1) event notification is supported.");
    if ((f & EV_FEATURE_FDS))
        printf("  All FD types are supported.");
    puts("");
}

These functions are defined in <event2/event.h>. The event_base_get_method()call was first available in Libevent 1.4.3. The others first appeared inLibevent 2.0.1-alpha.

Deallocating an event_base

When you are finished with an event_base, you can deallocate it withevent_base_free().

Interface
void event_base_free(struct event_base *base);

Note that this function does not deallocate any of the events that arecurrently associated with the event_base, or close any of their sockets, orfree any of their pointers.

The event_base_free() function is defined in <event2/event.h>. It was firstimplemented in Libevent 1.2.

Setting priorities on an event_base

Libevent supports setting multiple priorities on an event. By default,though, an event_base supports only a single priority level. You can set thenumber of priorities on an event_base by calling event_base_priority_init().

Interface
int event_base_priority_init(struct event_base *base, int n_priorities);

This function returns 0 on success and -1 on failure. The base argument isthe event_base to modify, and n_priorities is the number of priorities tosupport. It must be at least 1. The available priorities for new eventswill be numbered from 0 (most important) to n_priorities-1 (least important).

There is a constant, EVENT_MAX_PRIORITIES, that sets the upper bound on thevalue of n_priorities. It is an error to call this function with a highervalue for n_priorities.

Note
You must call this function before any events become active. It isbest to call it immediately after creating the event_base.

To find the number of priorities currently supported by a base, you cancall event_base_getnpriorities().

Interface
int event_base_get_npriorities(struct event_base *base);

The return value is equal to the number of priorities configured in thebase. So if event_base_get_npriorities() returns 3, then allowable priorityvalues are 0, 1, and 2.

Example
For an example, see the documentation for event_priority_set below.

By default, all new events associated with this base will be initializedwith priority equal to n_priorities / 2.

The event_base_priority_init function is defined in <event2/event.h>. It hasbeen available since Libevent 1.0. The event_base_get_npriorities() functionwas new in Libevent 2.1.1-alpha.

Reinitializing an event_base after fork()

Not all event backends persist cleanly after a call to fork(). Thus, if yourprogram uses fork() or a related system call in order to start a new process,and you want to continue using an event_base after you have forked, you mayneed to reinitialize it.

Interface
int event_reinit(struct event_base *base);

The function returns 0 on success, -1 on failure.

Example
struct event_base *base = event_base_new();

/* ... add some events to the event_base ... */

if (fork()) {
    /* In parent */
    continue_running_parent(base); /*...*/
} else {
    /* In child */
    event_reinit(base);
    continue_running_child(base); /*...*/
}

The event_reinit() function is defined in <event2/event.h>. It was firstavailable in Libevent 1.4.3-alpha.

Obsolete event_base functions

Older versions of Libevent relied pretty heavily on the idea of a"current" event_base. The "current" event_base was a global settingshared across all threads. If you forgot to specify which event_baseyou wanted, you got the current one. Since event_bases weren’tthreadsafe, this could get pretty error-prone.

Instead of event_base_new(), there was:

Interface
struct event_base *event_init(void);

This function worked like event_base_new(), and set the current base to the allocated base. There was no other way to change thecurrent base.

Some of the event_base functions in this section had variants thatoperated on the current base.

These functions behaved as the currentfunctions, except that they took no base argument.

Current functionObsolete current-base version

event_base_priority_init()

event_priority_init()

event_base_get_method()

event_get_method()



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值