全部博文(685)
分类: LINUX
2014-09-26 17:30:47
/* * calloc_a(size_t len, [void **addr, size_t len,...], NULL) * * allocate a block of memory big enough to hold multiple aligned objects. * the pointer to the full object (starting with the first chunk) is returned, * all other pointers are stored in the locations behind extra addr arguments. * the last argument needs to be a NULL pointer * * 分配一段连续内存给多个指针对象使用,多个指针对象必须保证同时进行free()操作 */ #define calloc_a(len, ...) __calloc_a(len, ##__VA_ARGS__, NULL)
/** * 计算对象数组个数 */ #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
#define USOCK_TCP 0 #define USOCK_UDP 1 #define USOCK_SERVER 0x0100 #define USOCK_NOCLOEXEC 0x0200 #define USOCK_NONBLOCK 0x0400 #define USOCK_NUMERIC 0x0800 #define USOCK_IPV6ONLY 0x2000 #define USOCK_IPV4ONLY 0x4000 #define USOCK_UNIX 0x8000
/** * 创建一个新的网络sock * * @param type - 类型标志 * @param host - 作为server表示绑定本地地址;作为client表示需连接的地址 * @param service - 端口 * @return - sock fd > 0; 错误 < 0 */ int usock(int type, const char *host, const char *service)
struct list_head { struct list_head *next; struct list_head *prev; };
#define LIST_HEAD_INIT(name) { &(name), &(name) } #undef LIST_HEAD #define LIST_HEAD(name) struct list_head name = LIST_HEAD_INIT(name) static inline void INIT_LIST_HEAD(struct list_head *list)
/** * 加入链表头部 */ list_add(struct list_head *_new, struct list_head *head) /** * 加入链表尾部 */ list_add_tail(struct list_head *_new, struct list_head *head)
/** * 把指定节点移动到链表头部 */ list_move(struct list_head *list, struct list_head *head) /** * 把指定节点移动到链表尾部 */ list_move_tail(struct list_head *entry, struct list_head *head)
/** * 将list链表拼接到head链表头部 */ list_splice(const struct list_head *list, struct list_head *head) /** * 将list链表拼接到head链表尾部 */ list_splice_tail(struct list_head *list, struct list_head *head) /** * 将list链表拼接到head链表头部,并初始化list */ list_splice_init(struct list_head *list, struct list_head *head) /** * 将list链表拼接到head链表尾部,并初始化list */ list_splice_tail_init(struct list_head *list, struct list_head *head)
/** * 把指定节点从链表中删除 */ list_del(struct list_head *entry) /** * 把指定节点从链表中删除,并初始此节点 */ list_del_init(struct list_head *entry)
/** * 获取当前节点元素 */ list_entry(ptr, type, field) /** * 获取后一个节点元素 */ list_first_entry(ptr, type, field) /** * 获取前一个节点元素 */ list_last_entry(ptr, type, field)
/** * 是否为空链表 */ bool list_empty(const struct list_head *head) /** * 指定节点是否为链表第一个节点 */ bool list_is_first(const struct list_head *list, const struct list_head *head) /** * 指定节点是否为链表最后一个节点 */ bool list_is_last(const struct list_head *list, const struct list_head *head)
/** * 向后遍历链表,遍历过程不能操作链表,p为链表结构体 */ list_for_each(p, head) /** * 向后遍历链表,遍历过程可操作链表,p为链表结构体 */ list_for_each_safe(p, n, head) /** * 向前遍历链表,遍历过程不能操作链表,p为链表结构体 */ list_for_each_prev(p, h) /** * 向前遍历链表,遍历过程可操作链表,p为链表结构体 */ list_for_each_prev_safe(p, n, h) /** * 向后遍历链表,遍历过程不能操作链表,p为节点元素结构体 */ list_for_each_entry(p, h, field) /** * 向后遍历链表,遍历过程可操作链表,p为节点元素结构体 */ list_for_each_entry_safe(p, n, h, field) /** * 向前遍历链表,遍历过程不能操作链表,p为节点元素结构体 */ list_for_each_entry_reverse(p, h, field)
/** * This element is a member of a avl-tree. It must be contained in all * larger structs that should be put into a tree. */ struct avl_node { /** * Linked list node for supporting easy iteration and multiple * elments with the same key. * * this must be the first element of an avl_node to * make casting for lists easier */ struct list_head list; /** * Pointer to parent node in tree, NULL if root node */ struct avl_node *parent; /** * Pointer to left child */ struct avl_node *left; /** * Pointer to right child */ struct avl_node *right; /** * pointer to key of node */ const void *key; /** * balance state of AVL tree (0,-1,+1) */ signed char balance; /** * true if first of a series of nodes with same key */ bool leader; };
/** * This struct is the central management part of an avl tree. * One of them is necessary for each avl_tree. */ struct avl_tree { /** * Head of linked list node for supporting easy iteration * and multiple elments with the same key. */ struct list_head list_head; /** * pointer to the root node of the avl tree, NULL if tree is empty */ struct avl_node *root; /** * number of nodes in the avl tree */ unsigned int count; /** * true if multiple nodes with the same key are * allowed in the tree, false otherwise */ bool allow_dups; /** * pointer to the tree comparator * * First two parameters are keys to compare, * third parameter is a copy of cmp_ptr */ avl_tree_comp comp; /** * custom pointer delivered to the tree comparator */ void *cmp_ptr; };
#define AVL_TREE_INIT(_name, _comp, _allow_dups, _cmp_ptr) \ { \ .list_head = LIST_HEAD_INIT(_name.list_head), \ .comp = _comp, \ .allow_dups = _allow_dups, \ .cmp_ptr = _cmp_ptr \ }
#define AVL_TREE(_name, _comp, _allow_dups, _cmp_ptr) \ struct avl_tree _name = \ AVL_TREE_INIT(_name, _comp, _allow_dups, _cmp_ptr)
/** * Initialize a new avl_tree struct * @param tree pointer to avl-tree * @param comp pointer to comparator for the tree * @param allow_dups true if the tree allows multiple elements with the same * @param ptr custom parameter for comparator */ void avl_init(struct avl_tree *tree, avl_tree_comp comp, bool allow_dups, void *ptr)
/** * Inserts an avl_node into a tree * @param tree pointer to tree * @param new pointer to node * @return 0 if node was inserted successfully, -1 if it was not inserted * because of a key collision */ int avl_insert(struct avl_tree *tree, struct avl_node *new)
/** * Remove a node from an avl tree * @param tree pointer to tree * @param node pointer to node */ void avl_delete(struct avl_tree *tree, struct avl_node *node)
/** * Finds a node in an avl-tree with a certain key * @param tree pointer to avl-tree * @param key pointer to key * @return pointer to avl-node with key, NULL if no node with * this key exists. */ struct avl_node * avl_find(const struct avl_tree *tree, const void *key)
/** * Finds the first node in an avl-tree with a key greater or equal * than the specified key * @param tree pointer to avl-tree * @param key pointer to specified key * @return pointer to avl-node, NULL if no node with * key greater or equal specified key exists. */ struct avl_node * avl_find_greaterequal(const struct avl_tree *tree, const void *key)
/** * Finds the last node in an avl-tree with a key less or equal * than the specified key * * @param tree pointer to avl-tree * @param key pointer to specified key * @return pointer to avl-node, NULL if no node with * key less or equal specified key exists. */ struct avl_node * avl_find_lessequal(const struct avl_tree *tree, const void *key)
/** * @param tree pointer to avl-tree * @param key pointer to key * @param element pointer to a node element(don't need to be initialized) * @param node_element name of the avl_node element inside the larger struct * return pointer to tree element with the specified key, * NULL if no element was found */ #define avl_find_element(tree, key, element, node_element)
/** * @param tree pointer to avl-tree * @param key pointer to specified key * @param element pointer to a node element (don't need to be initialized) * @param node_element name of the avl_node element inside the larger struct * return pointer to last tree element with less or equal key than specified key, * NULL if no element was found */ #define avl_find_le_element(tree, key, element, node_element)
/** * @param tree pointer to avl-tree * @param key pointer to specified key * @param element pointer to a node element (don't need to be initialized) * @param node_element name of the avl_node element inside the larger struct * return pointer to first tree element with greater or equal key than * specified key, NULL if no element was found */ #define avl_find_ge_element(tree, key, element, node_element)
/** * This function must not be called for an empty tree * * @param tree pointer to avl-tree * @param element pointer to a node element (don't need to be initialized) * @param node_member name of the avl_node element inside the larger struct * @return pointer to the first element of the avl_tree * (automatically converted to type 'element') */ #define avl_first_element(tree, element, node_member)
/** * @param tree pointer to tree * @param element pointer to a node struct that contains the avl_node * (don't need to be initialized) * @param node_member name of the avl_node element inside the * larger struct * @return pointer to the last element of the avl_tree * (automatically converted to type 'element') */ #define avl_last_element(tree, element, node_member)
/** * This function must not be called for the last element of an avl tree * * @param element pointer to a node of the tree * @param node_member name of the avl_node element inside the larger struct * @return pointer to the node after 'element' * (automatically converted to type 'element') */ #define avl_next_element(element, node_member)
/** * This function must not be called for the first element of * an avl tree * * @param element pointer to a node of the tree * @param node_member name of the avl_node element inside the larger struct * @return pointer to the node before 'element' * (automatically converted to type 'element') */ #define avl_prev_element(element, node_member)
/** * @param tree pointer to avl-tree * @param node pointer to node of the tree * @return true if node is the first one of the tree, false otherwise */ static inline bool avl_is_first(struct avl_tree *tree, struct avl_node *node)
/** * @param tree pointer to avl-tree * @param node pointer to node of the tree * @return true if node is the last one of the tree, false otherwise */ static inline bool avl_is_last(struct avl_tree *tree, struct avl_node *node)
/** * @param tree pointer to avl-tree * @return true if the tree is empty, false otherwise */ static inline bool avl_is_empty(struct avl_tree *tree)
/** * Loop over all elements of an avl_tree, used similar to a for() command. * This loop should not be used if elements are removed from the tree during * the loop. * * @param tree pointer to avl-tree * @param element pointer to a node of the tree, this element will * contain the current node of the tree during the loop * @param node_member name of the avl_node element inside the * larger struct */ #define avl_for_each_element(tree, element, node_member)
/** * Loop over all elements of an avl_tree backwards, used similar to a for() command. * This loop should not be used if elements are removed from the tree during * the loop. * * @param tree pointer to avl-tree * @param element pointer to a node of the tree, this element will * contain the current node of the tree during the loop * @param node_member name of the avl_node element inside the * larger struct */ #define avl_for_each_element_reverse(tree, element, node_member)
/** * Loop over all elements of an avl_tree, used similar to a for() command. * This loop can be used if the current element might be removed from * the tree during the loop. Other elements should not be removed during * the loop. * * @param tree pointer to avl-tree * @param element pointer to a node of the tree, this element will * contain the current node of the tree during the loop * @param node_member name of the avl_node element inside the * larger struct * @param ptr pointer to a tree element which is used to store * the next node during the loop */ #define avl_for_each_element_safe(tree, element, node_member, ptr)
/** * Loop over all elements of an avl_tree backwards, used similar to a for() command. * This loop can be used if the current element might be removed from * the tree during the loop. Other elements should not be removed during * the loop. * * @param tree pointer to avl-tree * @param element pointer to a node of the tree, this element will * contain the current node of the tree during the loop * @param node_member name of the avl_node element inside the * larger struct * @param ptr pointer to a tree element which is used to store * the next node during the loop */ #define avl_for_each_element_reverse_safe(tree, element, node_member, ptr)
/** * A special loop that removes all elements of the tree and cleans up the tree * root. The loop body is responsible to free the node elements of the tree. * * This loop is much faster than a normal one for clearing the tree because it * does not rebalance the tree after each removal. Do NOT use a break command * inside. * You can free the memory of the elements within the loop. * Do NOT call avl_delete() on the elements within the loop, * * @param tree pointer to avl-tree * @param element pointer to a node of the tree, this element will * contain the current node of the tree during the loop * @param node_member name of the avl_node element inside the * larger struct * @param ptr pointer to a tree element which is used to store * the next node during the loop */ #define avl_remove_all_elements(tree, element, node_member, ptr)
查找操作时被调用,此函数在初始化由调用者设置
/** * Prototype for avl comparators * @param k1 first key * @param k2 second key * @param ptr custom data for tree comparator * @return +1 if k1>k2, -1 if k1
平衡二叉树Key比较 - avl-cmp.c/h
/** * 用于初始化平衡二叉树,将k1和k2进行字符串比较 */ int avl_strcmp(const void *k1, const void *k2, void *ptr)
struct vlist_tree { struct avl_tree avl; vlist_update_cb update; /** 初始化时调用者设置 */ bool keep_old; /** true-加入相同节点时不删除旧节点,false-删除 bool no_delete; /** true-加入相同节点时不删除旧节点, * 删除节点时不做删除操作 * false-加入相同节点时删除旧节点 * 删除节点时做删除操作 */ int version; };
struct vlist_node { struct avl_node avl; int version; };
void vlist_init(struct vlist_tree *tree, avl_tree_comp cmp, vlist_update_cb update)
void vlist_add(struct vlist_tree *tree, struct vlist_node *node, const void *key)
void vlist_delete(struct vlist_tree *tree, struct vlist_node *node)
void vlist_flush(struct vlist_tree *tree) void vlist_flush_all(struct vlist_tree *tree)
#define vlist_find(tree, name, element, node_member)
#define vlist_for_each_element(tree, element, node_member)
增加和删除节点被回调
typedef void (*vlist_update_cb)(struct vlist_tree *tree, struct vlist_node *node_new, struct vlist_node *node_old);
struct kvlist { struct avl_tree avl; int (*get_len)(struct kvlist *kv, const void *data); };
struct kvlist_node { struct avl_node avl; char data[0] __attribute__((aligned(4))); };
void kvlist_init(struct kvlist *kv, int (*get_len)(struct kvlist *kv, const void *data)) void kvlist_free(struct kvlist *kv)
void kvlist_set(struct kvlist *kv, const char *name, const void *data)
bool kvlist_delete(struct kvlist *kv, const char *name)
void *kvlist_get(struct kvlist *kv, const char *name)
#define kvlist_for_each(kv, name, value)
加入操作时被回调,初始化时由调用者设置,用于计算data的内存空间大小
int (*get_len)(struct kvlist *kv, const void *data)
struct blob_attr { uint32_t id_len; /** 高1位为extend标志,高7位存储id, * 低24位存储data的内存大小 */ char data[]; } __packed;
struct blob_attr_info { unsigned int type; unsigned int minlen; unsigned int maxlen; bool (*validate)(const struct blob_attr_info *, struct blob_attr *); };
struct blob_buf { struct blob_attr *head; bool (*grow)(struct blob_buf *buf, int minlen); int buflen; void *buf; };
/** * 返回指向BLOB属性数据区指针 */ static inline void * blob_data(const struct blob_attr *attr)
/** * 返回BLOB属性ID */ static inline unsigned int blob_id(const struct blob_attr *attr)
/** * 判断BLOB属性扩展标志是否为真 */ static inline bool blob_is_extended(const struct blob_attr *attr)
/** * 返回BLOB属性有效存储空间大小 */ static inline unsigned int blob_len(const struct blob_attr *attr)
/* * 返回BLOB属性完全存储空间大小(包括头部) */ static inline unsigned int blob_raw_len(const struct blob_attr *attr)
/* * 返回BLOB属性填补后存储空间大小(包括头部) */ static inline unsigned int blob_pad_len(const struct blob_attr *attr)
static inline uint8_t blob_get_u8(const struct blob_attr *attr) static inline uint16_t blob_get_u16(const struct blob_attr *attr) static inline uint32_t blob_get_u32(const struct blob_attr *attr) static inline uint64_t blob_get_u64(const struct blob_attr *attr) static inline int8_t blob_get_int8(const struct blob_attr *attr) static inline int16_t blob_get_int16(const struct blob_attr *attr) static inline int32_t blob_get_int32(const struct blob_attr *attr) static inline int64_t blob_get_int64(const struct blob_attr *attr) static inline const char * blob_get_string(const struct blob_attr *attr)
static inline struct blob_attr * blob_put_string(struct blob_buf *buf, int id, const char *str) static inline struct blob_attr * blob_put_u8(struct blob_buf *buf, int id, uint8_t val) static inline struct blob_attr * blob_put_u16(struct blob_buf *buf, int id, uint16_t val) static inline struct blob_attr * blob_put_u32(struct blob_buf *buf, int id, uint32_t val) static inline struct blob_attr * blob_put_u64(struct blob_buf *buf, int id, uint64_t val)
#define blob_put_int8 blob_put_u8 #define blob_put_int16 blob_put_u16 #define blob_put_int32 blob_put_u32 #define blob_put_int64 blob_put_u64
struct blob_attr * blob_put(struct blob_buf *buf, int id, const void *ptr, unsigned int len) /** * ptr - 指向struct blob_attr */ struct blob_attr * blob_put_raw(struct blob_buf *buf, const void *ptr, unsigned int len)
#define __blob_for_each_attr(pos, attr, rem) #define blob_for_each_attr(pos, attr, rem)
struct blob_attr * blob_memdup(struct blob_attr *attr)
enum { BLOB_ATTR_UNSPEC, BLOB_ATTR_NESTED, /** 嵌套 */ BLOB_ATTR_BINARY, BLOB_ATTR_STRING, BLOB_ATTR_INT8, BLOB_ATTR_INT16, BLOB_ATTR_INT32, BLOB_ATTR_INT64, BLOB_ATTR_LAST }; bool blob_check_type(const void *ptr, unsigned int len, int type)
void * blob_nest_start(struct blob_buf *buf, int id) Void blob_nest_end(struct blob_buf *buf, void *cookie)
bool blob_attr_equal(const struct blob_attr *a1, const struct blob_attr *a2)
/** * 初始化BLOB buffer */ int blob_buf_init(struct blob_buf *buf, int id) /** * 销毁BLOB buffer */ void blob_buf_free(struct blob_buf *buf)
/** * 从attr串中根据info策略过滤,得到的结果存储在data属性数组中 * * @param attr 输入BLOB属性串 * @param data 输出BLOB属性数组 * @param info 属性过滤策略 * @param max data数组大小 */ int blob_parse(struct blob_attr *attr, struct blob_attr **data, const struct blob_attr_info *info, int max)
struct blobmsg_hdr { uint16_t namelen; uint8_t name[]; } __packed; struct blobmsg_policy { const char *name; enum blobmsg_type type; };
enum blobmsg_type { BLOBMSG_TYPE_UNSPEC, BLOBMSG_TYPE_ARRAY, BLOBMSG_TYPE_TABLE, BLOBMSG_TYPE_STRING, BLOBMSG_TYPE_INT64, BLOBMSG_TYPE_INT32, BLOBMSG_TYPE_INT16, BLOBMSG_TYPE_INT8, __BLOBMSG_TYPE_LAST, BLOBMSG_TYPE_LAST = __BLOBMSG_TYPE_LAST - 1, BLOBMSG_TYPE_BOOL = BLOBMSG_TYPE_INT8, };
/** * 根据BLOB消息名字长度计算出blobmsg头部大小 */ static inline int blobmsg_hdrlen(unsigned int namelen) /** * 获取BLOB消息名字 */ static inline const char *blobmsg_name(const struct blob_attr *attr) /** * 获取BLOB消息类型 */ static inline int blobmsg_type(const struct blob_attr *attr) /** * 获取BLOB消息数据内容 */ static inline void *blobmsg_data(const struct blob_attr *attr) /** * 获取BLOB消息数据内容大小 */ static inline int blobmsg_data_len(const struct blob_attr *attr) static inline int blobmsg_len(const struct blob_attr *attr)
/** * 判断BLOBMSG属性类型是否合法 */ bool blobmsg_check_attr(const struct blob_attr *attr, bool name)
int blobmsg_add_field(struct blob_buf *buf, int type, const char *name, const void *data, unsigned int len) static inline int blobmsg_add_u8(struct blob_buf *buf, const char *name, uint8_t val) static inline int blobmsg_add_u16(struct blob_buf *buf, const char *name, uint16_t val) static inline int blobmsg_add_u32(struct blob_buf *buf, const char *name, uint32_t val) static inline int blobmsg_add_u64(struct blob_buf *buf, const char *name, uint64_t val) static inline int blobmsg_add_string(struct blob_buf *buf, const char *name, const char *string) static inline int blobmsg_add_blob(struct blob_buf *buf, struct blob_attr *attr) /** * 格式化设备BLOGMSG */ void blobmsg_printf(struct blob_buf *buf, const char *name, const char *format, ...)
static inline uint8_t blobmsg_get_u8(struct blob_attr *attr) static inline bool blobmsg_get_bool(struct blob_attr *attr) static inline uint16_t blobmsg_get_u16(struct blob_attr *attr) static inline uint32_t blobmsg_get_u32(struct blob_attr *attr) static inline uint64_t blobmsg_get_u64(struct blob_attr *attr) static inline char *blobmsg_get_string(struct blob_attr *attr)
/** * 创建BLOBMSG,返回数据区开始地址 */ void *blobmsg_alloc_string_buffer(struct blob_buf *buf, const char *name, unsigned int maxlen) /** * 扩大BLOGMSG,返回数据区开始地址 */ void *blobmsg_realloc_string_buffer(struct blob_buf *buf, unsigned int maxlen) void blobmsg_add_string_buffer(struct blob_buf *buf)
#define blobmsg_for_each_attr(pos, attr, rem)
static inline void * blobmsg_open_array(struct blob_buf *buf, const char *name) static inline void blobmsg_close_array(struct blob_buf *buf, void *cookie) static inline void *blobmsg_open_table(struct blob_buf *buf, const char *name) static inline void blobmsg_close_table(struct blob_buf *buf, void *cookie)
/** * 从data BLOGMSG串中根据policy策略过滤,得到的结果存储在tb BLOGATTR数组中 * * @param policy 过滤策略 * @param policy_len 策略个数 * @param tb 返回属性数据 * @param len data属性个数 */ int blobmsg_parse(const struct blobmsg_policy *policy, int policy_len, struct blob_attr **tb, void *data, unsigned int len)
/** * 初始化事件循环 */ int uloop_init(void) /** * 事件循环主处理入口 */ void uloop_run(void) /** * 销毁事件循环 */ void uloop_done(void)
/** * 注册一个新描述符到事件处理循环 */ int uloop_fd_add(struct uloop_fd *sock, unsigned int flags) /** * 从事件处理循环中销毁指定描述符 */ int uloop_fd_delete(struct uloop_fd *sock)
/** * 注册一个新定时器 */ int uloop_timeout_add(struct uloop_timeout *timeout) /** * 设置定时器超时时间(毫秒),并添加 */ int uloop_timeout_set(struct uloop_timeout *timeout, int msecs) /** * 销毁指定定时器 */ int uloop_timeout_cancel(struct uloop_timeout *timeout) /** * 获取定时器还剩多长时间超时 */ int uloop_timeout_remaining(struct uloop_timeout *timeout)
/** * 注册新进程到事件处理循环 */ int uloop_process_add(struct uloop_process *p) /** * 从事件处理循环中销毁指定进程 */ int uloop_process_delete(struct uloop_process *p)
struct uloop_fd { uloop_fd_handler cb; /** 文件描述符,调用者初始化 */ int fd; /** 文件描述符,调用者初始化 */ bool eof; bool error; bool registered; uint8_t flags; };
struct uloop_timeout { struct list_head list; bool pending; uloop_timeout_handler cb; /** 文件描述符, 调用者初始化 */ struct timeval time; /** 文件描述符, 调用者初始化 */ };
struct uloop_process { struct list_head list; bool pending; uloop_process_handler cb; /** 文件描述符, 调用者初始化 */ pid_t pid; /** 文件描述符, 调用者初始化 */ };
typedef void (*uloop_fd_handler)(struct uloop_fd *u, unsigned int events)
typedef void (*uloop_timeout_handler)(struct uloop_timeout *t)
typedef void (*uloop_process_handler)(struct uloop_process *c, int ret)
#define ULOOP_READ (1 << 0) #define ULOOP_WRITE (1 << 1) #define ULOOP_EDGE_TRIGGER (1 << 2) #define ULOOP_BLOCKING (1 << 3) #define ULOOP_EVENT_MASK (ULOOP_READ | ULOOP_WRITE)
struct ustream_buf { struct ustream_buf *next; char *data; /** 指向上次操作buff开始地址 */ char *tail; /** 指向未使用buff开始地址 */ char *end; /** 指向buf结束地址 */ char head[]; /** 指向buf开始地址 */ };
struct ustream_buf_list { struct ustream_buf *head; /** 指向第1块ustream_buf */ struct ustream_buf *data_tail; /** 指向未使用的ustream_buf */ struct ustream_buf *tail; /** 指向最后的ustream_buf */ int (*alloc)(struct ustream *s, struct ustream_buf_list *l); int data_bytes; /** 已用存储空间大小 */ int min_buffers; /** 可存储最小的ustream_buf块个数 */ int max_buffers; /** 可存储最大的ustream_buf块个数 */ int buffer_len; /** 每块ustream_buf块存储空间大小 */ int buffers; /** ustream_buf块个数 */ };
struct ustream { struct ustream_buf_list r, w; struct uloop_timeout state_change; struct ustream *next; /* * notify_read: (optional) * called by the ustream core to notify that new data is available * for reading. * must not free the ustream from this callback */ void (*notify_read)(struct ustream *s, int bytes_new); /* * notify_write: (optional) * called by the ustream core to notify that some buffered data has * been written to the stream. * must not free the ustream from this callback */ void (*notify_write)(struct ustream *s, int bytes); /* * notify_state: (optional) * called by the ustream implementation to notify that the read * side of the stream is closed (eof is set) or there was a write * error (write_error is set). * will be called again after the write buffer has been emptied when * the read side has hit EOF. */ void (*notify_state)(struct ustream *s); /* * write: * must be defined by ustream implementation, accepts new write data. * 'more' is used to indicate that a subsequent call will provide more * data (useful for aggregating writes) * returns the number of bytes accepted, or -1 if no more writes can * be accepted (link error) */ int (*write)(struct ustream *s, const char *buf, int len, bool more); /* * free: (optional) * defined by ustream implementation, tears down the ustream and frees data */ void (*free)(struct ustream *s); /* * set_read_blocked: (optional) * defined by ustream implementation, called when the read_blocked flag * changes */ void (*set_read_blocked)(struct ustream *s); /* * poll: (optional) * defined by the upstream implementation, called to request polling for * available data. * returns true if data was fetched. */ bool (*poll)(struct ustream *s); /* * ustream user should set this if the input stream is expected * to contain string data. the core will keep all data 0-terminated. */ bool string_data; /** 此ustream是否为字符串,true-是;false-否 */ bool write_error; /** 写出错,true-是;false-否 */ bool eof, eof_write_done; enum read_blocked_reason read_blocked; };
struct ustream_fd { struct ustream stream; struct uloop_fd fd; };
/** * ustream_fd_init: create a file descriptor ustream (uses uloop) */ void ustream_fd_init(struct ustream_fd *s, int fd) /** * ustream_init_defaults: fill default callbacks and options */ void ustream_init_defaults(struct ustream *s) /** * ustream_free: free all buffers and data associated with a ustream */ void ustream_free(struct ustream *s)
/* * ustream_reserve: allocate rx buffer space * 分配len大小的read buffer可用内存空间,与ustream_fill_read()配合使用 * * len: hint for how much space is needed (not guaranteed to be met) * maxlen: pointer to where the actual buffer size is going to be stored */ char *ustream_reserve(struct ustream *s, int len, int *maxlen)
/** * ustream_fill_read: mark rx buffer space as filled * 设置被ustream_reseve()分配read buffer后写入的数据大小, * 回调notify_read()接口,表示有数据可读 */ void ustream_fill_read(struct ustream *s, int len)
一般在notify_read()回调接口使用
/* * ustream_get_read_buf: get a pointer to the next read buffer data * 获取新一次写入的内容,与ustream_consume()配置使用 */ char *ustream_get_read_buf(struct ustream *s, int *buflen)
/** * ustream_consume: remove data from the head of the read buffer */ void ustream_consume(struct ustream *s, int len)
尽最大能力调用write()回调用接口写入,如果超出能力将把未写入的数据存储在write buffer中
/* * ustream_write: add data to the write buffer */ int ustream_write(struct ustream *s, const char *buf, int len, bool more) int ustream_printf(struct ustream *s, const char *format, ...) int ustream_vprintf(struct ustream *s, const char *format, va_list arg)
把在write buffer中的数据写入实际地方,调用write()回调接口和notify_write()回调接口。一般在描述符的poll操作中调用,表示当描述符变为可写时立即把上一次未写入的内容进行写入操作。
/* * ustream_write_pending: attempt to write more data from write buffers * returns true if all write buffers have been emptied. */ bool ustream_write_pending(struct ustream *s)
struct runqueue { struct safe_list tasks_active; /** 活动任务队列 */ struct safe_list tasks_inactive; /** 不活动任务队列 */ struct uloop_timeout timeout; int running_tasks; /** 当前活动任务数目 */ int max_running_tasks; /** 允许最大活动任务数目 */ bool stopped; /** 是否停止任务队列 */ bool empty; /** 任务队列(包括活动和不活动)是否为空 */ /* called when the runqueue is emptied */ void (*empty_cb)(struct runqueue *q); };
struct runqueue_task_type { const char *name; /* * called when a task is requested to run * * The task is removed from the list before this callback is run. It * can re-arm itself using runqueue_task_add. */ void (*run)(struct runqueue *q, struct runqueue_task *t); /* * called to request cancelling a task * * int type is used as an optional hint for the method to be used when * cancelling the task, e.g. a signal number for processes. Calls * runqueue_task_complete when done. */ void (*cancel)(struct runqueue *q, struct runqueue_task *t, int type); /* * called to kill a task. must not make any calls to runqueue_task_complete, * it has already been removed from the list. */ void (*kill)(struct runqueue *q, struct runqueue_task *t); };
struct runqueue_task { struct safe_list list; const struct runqueue_task_type *type; struct runqueue *q; void (*complete)(struct runqueue *q, struct runqueue_task *t); struct uloop_timeout timeout; int run_timeout; /** >0表示规定此任务执行只有run_timeout毫秒 */ int cancel_timeout; /** >0表示规则任务延取消操作执行只有run_timeout毫秒*/ int cancel_type; bool queued; /** 此任务是否已加入任务队列中 */ bool running; /** 此任务是否活动,即已在活动队列中 */ bool cancelled; /** 此任务是否已被取消 */ };
struct runqueue_process { struct runqueue_task task; struct uloop_process proc; };
/** * 初始化任务队列 */ void runqueue_init(struct runqueue *q) /** * 取消所有任务队列 */ void runqueue_cancel(struct runqueue *q); /** * 取消活动中的任务 */ void runqueue_cancel_active(struct runqueue *q); /** * 取消不活动的任务 */ void runqueue_cancel_pending(struct runqueue *q); /** * 杀死所有任务 */ void runqueue_kill(struct runqueue *q); /** * 停止所有任务 */ void runqueue_stop(struct runqueue *q); /** * 重新开始任务 */ void runqueue_resume(struct runqueue *q);
/** * 添加新任务到队列尾 * * @running true-加入活动队列;false-加入不活动队列 */ void runqueue_task_add(struct runqueue *q, struct runqueue_task *t, bool running); /** * 添加新任务到队列头 * * @running true-加入活动队列;false-加入不活动队列 */ void runqueue_task_add_first(struct runqueue *q, struct runqueue_task *t, bool running); /** * 完全任务 */ void runqueue_task_complete(struct runqueue_task *t); /** * 取消任务 */ void runqueue_task_cancel(struct runqueue_task *t, int type); /** * 杀死任务 */ void runqueue_task_kill(struct runqueue_task *t);