多输入使用多线程
多输入使用多线程
https://computing.llnl.gov/tutorials/pthreads/ 这里有份英文文档,很详细的说明
具体的手册在man3 https://linux.die.net/man/3/ 搜索pthread
完整的pdf在 Unix_Linux_Windows_OpenMP多线程编程.pdf
代码仓库 https://gitee.com/layty/project_for_linux/tree/master/03-ebook/05_input_by_pthread
常用函数
头文件 #include <pthread.h>
POSIX 函数 | 描述 |
---|---|
pthread_cancel | 终止另一个线程 |
pthread_create | 创建一个线程 |
pthread_detach | 设置线程以释放资源 |
pthread_equal | 测试两个线程 ID 是否相等 |
pthread_exit | 退出线程,而不退出进程 |
pthread_join | 等待一个线程 |
pthread_self | 找出自己的线程 ID |
互斥锁线程控制 | |
---|---|
pthread_mutex_init | 互斥锁初始化 |
pthread_mutex_lock | 互斥锁上锁 ,默认是会阻塞的 |
pthread_mutex_trylock | 互斥锁判断上锁 |
pthread_mutex_unlock | 互斥锁接锁 |
pthread_mutex_destroy | 消除互斥锁 |
信号量线程控制 | |
---|---|
sem_init | 创建一个信号量,并初始化它的值 |
sem_wait | 将信号量的值减一,<0将会阻塞进程 |
sem_trywait | 将信号量的值减一,<0会立即返回 |
sem_post | 将信号量的值加一同时发出信号来唤醒等待的进程 |
sem_getvalue | 得到信号量的值 |
sem_destroy | 删除信号量 |
线程属性 | |
---|---|
绑定属性 | 保证在需要的时候总有一个内核线程与之对应 |
分离属性 | 它终止以后就可能将线程号和系统资源移交给其他的程使用,这时调用pthread_create()的线程就得到了错误的线程号 |
pthread_attr_init | 初始化 |
pthread_attr_setscope | 设置绑定属性 |
pthread_attr_setdetachstate | 设置分离属性 |
pthread_attr_setschedparam | 设置线程优先级 |
pthread_attr_destroy | 对分配的属性结构指针进行清理和回收 |
… | 相应函数获取属性 |
条件变量 | |
---|---|
pthread_cond_init | 初始化 |
pthread_cond_destroy | 销毁 |
pthread_cond_timedwait | 等待,含超时 |
pthread_cond_wait | 一直等待, 等待的时候会释放互斥量 |
pthread_cond_broadcast | 唤醒所有等待的线程 |
pthread_cond_signal | 唤醒1个等待的线程 |
简单使用
void *thrd_func(void *arg)
{
....
pthread_exit(NULL);
}
int main(void)
{
#define THREAD_NUMBER 1 /*线程数*/
pthread_t thread[THREAD_NUMBER];
/* 创建多线程 */
no = 0;
res = pthread_create(&thread[0], NULL, thrd_func, (void*)no);
res = pthread_join(thread[0], &thrd_ret);
if (!res)
{
printf("Thread %d joined\n", no);
}
else
{
printf("Thread %d join failed\n", no);
}
}
引入电子书
- 设置两个输入都为阻塞方式,这样没有输入的时候都会休眠了
- 主函数调用A()来获取输入
- A()就是主线程了,使用条件变量
pthread_cond_wait
等待唤醒 - B()为线程函数,具体调用的就是输入的阻塞输入,有数据后唤醒线程后再去唤醒主线程
// 主线程查询函数
int GetInputEvent(T_InputEvent * out)
{
pthread_mutex_lock(&g_mutex);
pthread_cond_wait(&g_tConVar, &g_mutex);
/* 被唤醒后,返回数据 */
*out = g_Input_Event_val;
pthread_mutex_unlock(&g_mutex);
return 0;
}
//创建的子线程
int AllInputDevicesInit(void)
{
T_InputOp* now=T_InputOp_list;
int iError = -1;
while (now)
{
if (0 == now->Init())
{
/* 创建子线程 */
pthread_create(&now->thread_id, NULL, GetInputThreadFun, now->GetInputEventOp);
iError = 0;
}
now = now->next;
}
return iError;
}
// 具体的子线程函数
static void * GetInputThreadFun(void *fun)
{
T_InputEvent out_tmp;
int (*ThisGetInputEventOp)(T_InputEvent* )=(int (*)(T_InputEvent* ))fun;
while (1)
{
if(0 == ThisGetInputEventOp(&out_tmp))
{
/* 唤醒主线程, 把tInputEvent的值赋给一个全局变量 */
/* 访问临界资源前,先获得互斥量 */
pthread_mutex_lock(&g_mutex);
g_Input_Event_val = out_tmp;
/* 唤醒主线程 */
pthread_cond_signal(&g_tConVar);
/* 释放互斥量 */
pthread_mutex_unlock(&g_mutex);
}
}
return NULL;
}
滑屏
滑动屏幕来达到翻页
思路: 记录第一次按下的位置,记录松开的位置,计算差值