实现信号量(一) 开篇
2014-01-05 16:02
211 查看
这系列文章是用管道、消息队列、条件变量来模拟实现信号量的功能。如果有bug,还望各位读者不吝指出。
这里实现的信号量都是只能用于一个进程内多个线程进行通信的,并不能用于进程间的通信。这里的所有函数的返回值同POSIX标准中的线程那些函数一样,如果函数执行成功,返回0,否则返回错误编号。不会设置errno变量。
测试的代码是《UNIX网络编程 卷2:进程间通信》中10.10和10.11节的结合,即多个生产者、多个消费者,多个缓冲区。为了测试方便,我还写了一个线程结构体。
这里先贴出线程代码。
Thread.hpp文件
Thread.cpp 文件
这里实现的信号量都是只能用于一个进程内多个线程进行通信的,并不能用于进程间的通信。这里的所有函数的返回值同POSIX标准中的线程那些函数一样,如果函数执行成功,返回0,否则返回错误编号。不会设置errno变量。
测试的代码是《UNIX网络编程 卷2:进程间通信》中10.10和10.11节的结合,即多个生产者、多个消费者,多个缓冲区。为了测试方便,我还写了一个线程结构体。
这里先贴出线程代码。
Thread.hpp文件
#ifndef THREAD_HPP #define THREAD_HPP #include<pthread.h> #include<semaphore.h> typedef void* (threadFun)(void*); typedef struct Thread_tag { pthread_t tid; sem_t sem; pthread_mutex_t mutex; void* parameter; //线程执行函数的参数 threadFun* realFun; //线程的执行函数 int isRunning; //判断线程是否还在运行 int valid; //用于判断这个结构体有没有被初始化,将赋值一个魔数 }Thread_t; void* thread_temp_fun(void* arg); int thread_init(Thread_t* thread); int thread_create(Thread_t* thread, pthread_attr_t *attr, threadFun* fun ); //创建一个线程的时候并不会马上运行线程函数,而是要等到调用thread_start函数 //这类似于Java中的线程,需要显示调用start方法才会运行线程。 int thread_start(Thread_t* thread, void* arg); int thread_join(Thread_t* thread, void **value); int thread_cancel(Thread_t* thread); int thread_destroy(Thread_t* thread); #endif // THREAD_HPP
Thread.cpp 文件
#include"Thread.hpp" #include<errno.h> #define THREAD_VALID 0xfabc //临时函数。当一个调用thread_create创建一个线程时,线程将运行这个函数 //然后在这个函数里面停留,休眠。等待用户调用thread_start函数将线程唤醒 //然后线程进入到用户提供的线程运行函数。 //正是通过这种方式,造成一种假象:线程在调用thread_create后,并不会马上运行 //直到调用了thread_start函数后才会运行 void* thread_temp_fun(void* arg) { void* status; Thread_t* thread = (Thread_t*)arg; sem_wait(&thread->sem); //等待另外一个线程调用thread_start唤醒 thread->isRunning = 1; status = ((thread->realFun))(thread->parameter); //调用线程的执行函数 thread->isRunning = 0; return status; } //这个函数不会线程安全的。 int thread_init(Thread_t* thread) { int status; if( thread == NULL ) return EINVAL; status = sem_init(&thread->sem, 0, 0); if( status != 0 ) return status; status = pthread_mutex_init(&thread->mutex, NULL); if( status != 0 ) return status; thread->isRunning = 0; thread->valid = THREAD_VALID; //赋值一个魔数 return 0; } //make this process Atomically int thread_create(Thread_t* thread, pthread_attr_t* attr, threadFun *fun ) { int status; if( thread == NULL || thread->valid != THREAD_VALID ||fun == NULL ) return EINVAL; status = pthread_mutex_lock(&thread->mutex); if( status != 0 ) return status; thread->realFun = fun; status = pthread_create(&thread->tid, attr, thread_temp_fun, thread); //ignore the error. if status == 0 and unlock return not 0. //we cann't return this message to user. it will confuse the user //the thread's creation is sucessful, but return error code pthread_mutex_unlock(&thread->mutex); return status; } int thread_start(Thread_t* thread, void *arg) { int status; if( thread == NULL || thread->valid != THREAD_VALID) return EINVAL; status = pthread_mutex_lock(&thread->mutex); if( status != 0 ) return status; if( thread->isRunning )//now, this thread is running { pthread_mutex_unlock(&thread->mutex); return EBUSY; } //将线程运行时的参数传递给线程执行函数 thread->parameter = arg; status = sem_post(&thread->sem); return status; } int thread_join(Thread_t* thread, void** value) { if( thread == NULL || thread->valid != THREAD_VALID) return EINVAL; return pthread_join(thread->tid, value); } int thread_cancel(Thread_t* thread) { if( thread == NULL || thread->valid != THREAD_VALID ) return EINVAL; return pthread_cancel(thread->tid); } int thread_destroy(Thread_t* thread) { int status1, status2; if( thread == NULL || thread->valid != THREAD_VALID) return EINVAL; status1 = pthread_mutex_lock(&thread->mutex); if( status1 != 0 ) return status1; if( thread->isRunning ) { pthread_mutex_unlock(&thread->mutex); return EBUSY; } status1 = pthread_mutex_unlock(&thread->mutex); if( status1 != 0 ) return status1; status1 = pthread_mutex_destroy(&thread->mutex); status2 = sem_destroy(&thread->sem); if( status1 != 0 ) return status1; return status2; }
相关文章推荐
- CreateTextFile 文件的使用
- 投影字DropShadow
- MySQL 5.1.73升级为MySQL 5.5.35详解 推荐
- js实现web网页版台球游戏
- 黑马程序员-Java基础,Java集合Collection和Iterator接口
- 【黑马程序员】Java基础09:File类和递归
- android编译时生成了一个 main.out.xml文件,无法编译的解决办法
- 新中文乱码问题
- Android TextView 设置滚动条(纯xml)
- install arm-linux-gcc
- 实现Google AdSense广告自适应设计
- UML 基础: 组件图
- JAVA环境变量的设置
- 3M找到大规模生产柔性屏新方法
- Socket通信——Android手机客户端和电脑服务器通信小例子
- WIN8: 80端口被SYSTEM占用的解决方法
- 赶集网、58同城二手手机交易区水货手机泛滥
- WiKi上关于USRP使用的一些问答(二)
- 自适应网页设计的方法
- js对象转到字符串