Skip to content

Instantly share code, notes, and snippets.

@ahappyforest
Last active December 27, 2015 13:18
Show Gist options
  • Save ahappyforest/7331725 to your computer and use it in GitHub Desktop.
Save ahappyforest/7331725 to your computer and use it in GitHub Desktop.
/***********************************************************************
* Copyright (C) 2013 by wsn studio ***
***********************************************************************/
/**
* @file example.h
* @author Liu Peng
* @date 2013-11-06
* @brief 这是一个小例子, 目的是教你如何快速使用doxygen
*
* 注意doxygen使用反斜杠@\或者@@符号来定义一个标识
* @see http://www.stack.nl/~dimitri/doxygen/docblocks.html
* @see http://www.stack.nl/~dimitri/doxygen/commands.html
* @see https://gist.github.com/van9ogh/7331725
*/
#ifndef _EXAMPLE_H
#define _EXAMPLE_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/**< 这是一个定义enum的例子*/
/**
* @brief enum是个好东西!
*
* enum里面有三个变量, 我们会拿这三个变量表示物体的三种状态
*/
typedef enum STATUS_enum {
STATUS_OPEN, /**< 表示开关已经打开 */
STATUS_CLOSE, /**< 表示已经关闭运行 */
STATUS_RUNNING /**< 表示正在运行 */
} STATUSENUM;
/**
* @brief 结构体是个好东西
*
* 这个结构体用来盛放一些系统运行的变量
*/
typedef struct Example_s {
int a; /**< 变量1 */
int b; /**< 变量2 */
double c; /**< 变量3 */
} Example_t;
/**
* @brief 两个数相加
*
* 两个数相加, 我们需要两个整数变量, 然后将它们相加, 例如:
* @code{.c}
* int c;
* c = add(param1, param2);
* printf("1 + 1 = %d\n", c);
* @endcode
* @param a 第一个整数
* @param b 第二个整数
* @return 返回两个数相加后的整数
*/
int add(int a, int b);
#endif
@begeekmyfriend
Copy link

还要吐槽的是queue_get_length其实是不可重入的函数,因为q->length存在竞态,而return并非原子操作,很可能包含内存寻址,加载寄存器ax,pop以及iret等指令,期间只要另外一个线程改写了就欧了。保守的做法是赋值给局部变量,加锁,然后返回该局部变量,或者直接调用atomic_get之类的特殊系统服务函数。

@ahappyforest
Copy link
Author

我可能有点理解马力兄你的意思了。

你说的是生产消费者模型, 保证的是读写交替, 因此在读之前要wait, 读完后要signal, 写则是相反的过程。因此会出现读线程会唤醒读线程, 写线程会唤醒写线程的情况。

在queue.c的实现中, 这并不是一个生产消费者模型(至少在时序上不是), 因为写线程一直是可以写的, 没有读线程也可以写。 而且队列在不为空的情况下, 根本就不会wait, 只有当出现两种情况下才会使用pthread_cond_t。

1. queue.c的实现有一个buf pool, 每次put一个新的node都是从pool中取出一个未使用的node, 然后将其插入到单链表中, 于是put操作,当pool为空取不出node的时候, 会发生pthread_cond_wait。

2. 每次get一个新的node都是从单链表中取出一个node, 然后返回node中的key值, 于是get操作, 当单链表为空的时候, 会发生pthread_cond_wait

生产消费者模型的实现, 有使用信号量的(semaphore), 也有使用条件变量的(pthread_cond_t), 个人感觉信号量更合适, 而条件变量本身只是用来触发某种条件的, 它是0,1模型, 在多个读写线程的情况下, 只会把问题搞复杂。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment