cam_list、cam_queue

1. cam_list

#define member_of(ptr, type, member) ({ \
  const typeof(((type *)0)->member) *__mptr = (ptr); \
  (type *)((char *)__mptr - offsetof(type,member));})

struct cam_list {
  struct cam_list *next, *prev;
};

static inline void cam_list_init(struct cam_list *ptr)
{
  ptr->next = ptr;
  ptr->prev = ptr;
}

static inline void cam_list_add_tail_node(struct cam_list *item,
  struct cam_list *head)
{
  struct cam_list *prev = head->prev;

  head->prev = item;
  item->next = head;
  item->prev = prev;
  prev->next = item;
}

static inline void cam_list_insert_before_node(struct cam_list *item,
  struct cam_list *node)
{
  item->next = node;
  item->prev = node->prev;
  item->prev->next = item;
  node->prev = item;
}

static inline void cam_list_del_node(struct cam_list *ptr)
{
  struct cam_list *prev = ptr->prev;
  struct cam_list *next = ptr->next;

  next->prev = ptr->prev;
  prev->next = ptr->next;
  ptr->next = ptr;
  ptr->prev = ptr;
}

 

   链表就不说了,和内核链表的实现思想一致。

2. cam_queue

  为什么定义 queue?

    目的就是多线程使用,可以一个线程不断的读 queue ,其他线程不断的写 queue,这样可以实现事件的统一分发处理。常用机制。

#include "cam_list.h"

typedef struct {
    struct cam_list list;  // 用链表管理 queue 的结点
    void *data;
} cam_node_t;  // 定义 queue 的结点

typedef struct {
    cam_node_t head; /* dummy head */
    uint32_t size;
    pthread_mutex_t lock;
} cam_queue_t;

static inline int32_t cam_queue_init(cam_queue_t *queue)  // 初始化
{
    pthread_mutex_init(&queue->lock, NULL);
    cam_list_init(&queue->head.list);
    queue->size = 0;
    return 0;
}

static inline int32_t cam_queue_enq(cam_queue_t *queue, void *data)   // 入队
{
    cam_node_t *node =
        (cam_node_t *)malloc(sizeof(cam_node_t));
    if (NULL == node) {
        return -1;
    }

    memset(node, 0, sizeof(cam_node_t));
    node->data = data;

    pthread_mutex_lock(&queue->lock);                           // 天生为多线程存在,竞争资源必须加锁
    cam_list_add_tail_node(&node->list, &queue->head.list);
    queue->size++;
    pthread_mutex_unlock(&queue->lock);

    return 0;
}

static inline void *cam_queue_deq(cam_queue_t *queue)               // 出队
{
    cam_node_t *node = NULL;
    void *data = NULL;
    struct cam_list *head = NULL;
    struct cam_list *pos = NULL;

    pthread_mutex_lock(&queue->lock);
    head = &queue->head.list;
    pos = head->next;
    if (pos != head) {  // 内部链表不为空,获取链表头结点
        node = member_of(pos, cam_node_t, list);
        cam_list_del_node(&node->list);
        queue->size--;
    }
    pthread_mutex_unlock(&queue->lock);

    if (NULL != node) {  // 将 结点 内存释放,将用户内存指针返回
        data = node->data;
        free(node);
    }

    return data;
}

static inline int32_t cam_queue_flush(cam_queue_t *queue)  // 清空 queue。即遍历删除所有的 queue 结点,然后释放 结点 内存。
{
    cam_node_t *node = NULL;
    struct cam_list *head = NULL;
    struct cam_list *pos = NULL;

    pthread_mutex_lock(&queue->lock);
    head = &queue->head.list;
    pos = head->next;

    while(pos != head) {
        node = member_of(pos, cam_node_t, list);
        pos = pos->next;
        cam_list_del_node(&node->list);
        queue->size--;

        /* TODO later to consider ptr inside data */
        /* for now we only assume there is no ptr inside data
         * so we free data directly */
        if (NULL != node->data) {
            free(node->data);
        }
        free(node);

    }
    queue->size = 0;
    pthread_mutex_unlock(&queue->lock);
    return 0;
}

static inline int32_t cam_queue_deinit(cam_queue_t *queue)
{
    cam_queue_flush(queue);
    pthread_mutex_destroy(&queue->lock);
    return 0;
}

 

   优点:

    操作灵活,数据区域完全由用户自己定义。给用户的足够的操作空间。

  缺点:

    在多线程操作中,如果没有事件处理,就是 queue 为空时,必然要等待。以前我都会将等待做到队列里,由用户指定等待时间。

posted @ 2018-01-09 17:27  rain-dot  阅读(392)  评论(0编辑  收藏  举报