Libevent参考手册第一章:设置libevent

Nick Mathewson  著

晨星           翻译

老衣           整理

 

libevent有一些被整个进程共享的、影响整个库的全局设置。必须在调用libevent库的任何其余部分以前修改这些设置,不然,libevent会进入不一致的状态。安全

1  Libevent中的日志消息

libevent能够记录内部错误和警告。若是编译进日志支持,还会记录调试信息。默认配置下这些信息被写到stderr。经过提供定制的日志函数能够覆盖默认行为。函数

接口

 

 

 

 

 

 

示例

  1. #include <event2/event.h>  
  2. #include <stdio.h>  
  3.   
  4. static void discard_cb(int severity, const char *msg)  
  5. {  
  6.     /* This callback does nothing. */  
  7. }  
  8.   
  9. static FILE *logfile = NULL;  
  10. static void write_to_file_cb(int severity, const char *msg)  
  11. {  
  12.     const char *s;  
  13.     if (!logfile)  
  14.         return;  
  15.     switch (severity) {  
  16.         case _EVENT_LOG_DEBUG: s = "debug"; break;  
  17.         case _EVENT_LOG_MSG:   s = "msg";   break;  
  18.         case _EVENT_LOG_WARN:  s = "warn";  break;  
  19.         case _EVENT_LOG_ERR:   s = "error"; break;  
  20.         default:               s = "?";     break; /* never reached */  
  21.     }  
  22.     fprintf(logfile, "[%s] %s/n", s, msg);  
  23. }  
  24.   
  25. /* Turn off all logging from Libevent. */  
  26. void suppress_logging(void)  
  27. {  
  28.     event_set_log_callback(discard_cb);  
  29. }  
  30.   
  31. /* Redirect all Libevent log messages to the C stdio file 'f'. */  
  32. void set_logfile(FILE *f)  
  33. {  
  34.     logfile = f;  
  35.     event_set_log_callback(write_to_file_cb);  
  36. }  

 

 

 

注意

在用户提供的event_log_cb回调函数中调用libevent函数是不安全的。好比说,若是试图编写一个使用bufferevent将警告信息发送给某个套接字的日志回调函数,可能会遇到奇怪而难以诊断的bug。将来版本libevent的某些函数可能会移除这个限制。工具

这个函数在<event2/event.h>中声明,在libevent 1.0c版本中首次出现。this

2 处理致命错误

libevent在检测到不可恢复的内部错误时的默认行为是调用exit()或者abort(),退出正在运行的进程。这类错误一般意味着某处有bug:要么在你的代码中,要么在libevent中。.net

若是但愿更优雅地处理致命错误,能够为libevent提供在退出时应该调用的函数,覆盖默认行为。线程

接口

 

  1. typedef void (*event_fatal_cb)(int err);  
  2. void event_set_fatal_callback(event_fatal_cb cb);  

 

 

 

 

 

 

 

 

 

3 内存管理

默认状况下,libevent使用C库的内存管理函数在堆上分配内存。经过提供malloc、realloc和free的替代函数,可让libevent使用其余的内存管理器。但愿libevent使用一个更高效的分配器时,或者但愿libevent使用一个工具分配器以便检查内存泄漏时,可能须要这样作。翻译

接口

 

[c-sharp] view plain copy
  1. void event_set_mem_functions(void *(*malloc_fn)(size_t sz),  
  2.                              void *(*realloc_fn)(void *ptr, size_t sz),  
  3.                              void (*free_fn)(void *ptr));  

这里有个替换libevent分配器函数的示例,它能够计算已经分配的字节数。实际应用中可能须要添加锁,以免运行在多个线程中时发生错误。debug

示例

 

 

  1. #include <event2/event.h>  
  2. #include <sys/types.h>  
  3. #include <stdlib.h>  
  4.   
  5. /* This union's purpose is to be as big as the largest of all the 
  6.  * types it contains. */  
  7. union alignment {  
  8.     size_t sz;  
  9.     void *ptr;  
  10.     double dbl;  
  11. };  
  12. /* We need to make sure that everything we return is on the right 
  13.    alignment to hold anything, including a double. */  
  14. #define ALIGNMENT sizeof(union alignment)  
  15.   
  16. /* We need to do this cast-to-char* trick on our pointers to adjust 
  17.    them; doing arithmetic on a void* is not standard. */  
  18. #define OUTPTR(ptr) (((char*)ptr)+ALIGNMENT)  
  19. #define INPTR(ptr) (((char*)ptr)-ALIGNMENT)  
  20.   
  21. static size_t total_allocated = 0;  
  22. static void *replacement_malloc(size_t sz)  
  23. {  
  24.     void *chunk = malloc(sz + ALIGNMENT);  
  25.     if (!chunk) return chunk;  
  26.     total_allocated += sz;  
  27.     *(size_t*)chunk = sz;  
  28.     return OUTPTR(chunk);  
  29. }  
  30. static void *replacement_realloc(void *ptr, size_t sz)  
  31. {  
  32.     size_t old_size = 0;  
  33.     if (ptr) {  
  34.         ptr = INPTR(ptr);  
  35.         old_size = *(size_t*)ptr;  
  36.     }  
  37.     ptr = realloc(ptr, sz + ALIGNMENT);  
  38.     if (!ptr)  
  39.         return NULL;  
  40.     *(size_t*)ptr = sz;  
  41.     total_allocated = total_allocated - old_size + sz;  
  42.     return OUTPTR(ptr);  
  43. }  
  44. static void replacement_free(void *ptr)  
  45. {  
  46.     ptr = INPTR(ptr);  
  47.     total_allocated -= *(size_t*)ptr;  
  48.     free(ptr);  
  49. }  
  50. void start_counting_bytes(void)  
  51. {  
  52.     event_set_mem_functions(replacement_malloc,  
  53.                             replacement_realloc,  
  54.                             replacement_free);  
  55. }  

注意

²  替换内存管理函数影响libevent随后的全部分配、调整大小和释放内存操做。因此,必须保证在调用任何其余libevent函数以前进行替换。不然,libevent可能用你的free函数释放用C库的malloc分配的内存。调试

²  你的malloc和realloc函数返回的内存块应该具备和C库返回的内存块同样的地址对齐。日志

²  你的realloc函数应该正确处理realloc(NULL,sz)(也就是看成malloc(sz)处理)

²  你的realloc函数应该正确处理realloc(ptr,0)(也就是看成free(ptr)处理)

²  你的free函数没必要处理free(NULL)

²  你的malloc函数没必要处理malloc(0)

²  若是在多个线程中使用libevent,替代的内存管理函数须要是线程安全的。

²  libevent将使用这些函数分配返回给你的内存。因此,若是要释放由libevent函数分配和返回的内存,而你已经替换malloc和realloc函数,那么应该使用替代的free函数。

event_set_mem_functions函数声明在<event2/event.h>中,在libevent 2.0.1-alpha版本中首次出现。

能够在禁止event_set_mem_functions函数的配置下编译libevent。这时候使用event_set_mem_functions将不会编译或者连接。在2.0.2-alpha及之后版本中,能够经过检查是否认义了EVENT_SET_MEM_FUNCTIONS_IMPLEMENTED宏来肯定event_set_mem_functions函数是否存在。

相关文章
相关标签/搜索