手机操作系统 2016-12-27
前面讲到,使用非阻塞方式有许多的缺点。主要是单线程,一直占用CPU资源,其他程序无法执行,造成资源的浪费。只能用于较简单循环的场所。而线程灵活,CPU占用率小,适用于大部分场合。
1.条件变量的使用
条件变量是用来通知共享数据的状态信息的机制。由于涉及共享数据,所以一般和互斥量配合使用。
1.1创建和销毁条件变量
pthread_cond_t表示条件变量。在使用pthread_cond_t变量前对其进行初始化。使用默认属性,可以用PTHREAD_COND_INITIALIZER付给变量就可以完成初始化。
pthread_cond_desroy销毁一个条件变量。函数形式为
pthread_cond_desroy(pthread_cond_t * cond)
1.2等待和通知条件变量
条件变量与条件测试是一起调用的。如果测试失败,则调用pthread_cond_wait
int pthread_cond_wait(pthread_cond_t *restrict cond,pthread_mutex_t *restrict mutex)
如果测试成功,则调用pthread_cond_signal函数。
int pthread_cond_signal(pthread_cond_t *cond)
pthread_cond_signal函数只唤醒一个阻塞在cond指向的条件变量上的线程。
2条件变量的应用
2.1 在AllInputDevicesInit函数内创建线程
1 if (0 == ptTmp->DeviceInit()) 2 { 3 /* 创建子线程 */ 4 pthread_create(&ptTmp->tTreadID, NULL, InputEventTreadFunction, ptTmp->GetInputEvent); 5 iError = 0; 6 } 7 ptTmp = ptTmp->ptNext;
实现InputEventTreadFunction函数
1 static void *InputEventTreadFunction(void *pVoid) 2 { 3 T_InputEvent tInputEvent; 4 5 /* 定义函数指针 */ 6 int (*GetInputEvent)(PT_InputEvent ptInputEvent); 7 GetInputEvent = (int (*)(PT_InputEvent))pVoid; 8 9 while (1) 10 { 11 if(0 == GetInputEvent(&tInputEvent)) 12 { 13 /* 唤醒主线程, 把tInputEvent的值赋给一个全局变量 */ 14 /* 访问临界资源前,先获得互斥量 */ 15 pthread_mutex_lock(&g_tMutex); 16 g_tInputEvent = tInputEvent; 17 18 /* 唤醒主线程 */ 19 pthread_cond_signal(&g_tConVar); 20 21 /* 释放互斥量 */ 22 pthread_mutex_unlock(&g_tMutex); 23 } 24 } 25 26 return NULL; 27 }
2.2在Touchscreen.c里全改为阻塞方式
TouchScreenGetInputEvent函数修改如下:
1 static int TouchScreenGetInputEvent(PT_InputEvent ptInputEvent) 2 { 3 struct ts_sample tSamp; 4 struct ts_sample tSampPressed; 5 struct ts_sample tSampReleased; 6 int iRet; 7 int bStart = 0; 8 int iDelta; 9 10 static struct timeval tPreTime; 11 12 13 while (1) 14 { 15 iRet = ts_read(g_tTSDev, &tSamp, 1); /* 如果无数据则休眠 */ 16 if (iRet == 1) 17 { 18 if ((tSamp.pressure > 0) && (bStart == 0)) 19 { 20 /* 刚按下 */ 21 /* 记录刚开始压下的点 */ 22 tSampPressed = tSamp; 23 bStart = 1; 24 } 25 26 if (tSamp.pressure <= 0) 27 { 28 /* 松开 */ 29 tSampReleased = tSamp; 30 31 /* 处理数据 */ 32 if (!bStart) 33 { 34 return -1; 35 } 36 else 37 { 38 iDelta = tSampReleased.x - tSampPressed.x; 39 ptInputEvent->tTime = tSampReleased.tv; 40 ptInputEvent->iType = INPUT_TYPE_TOUCHSCREEN; 41 42 if (iDelta > giXres/5) 43 { 44 /* 翻到上一页 */ 45 ptInputEvent->iVal = INPUT_VALUE_UP; 46 } 47 else if (iDelta < 0 - giXres/5) 48 { 49 /* 翻到下一页 */ 50 ptInputEvent->iVal = INPUT_VALUE_DOWN; 51 } 52 else 53 { 54 ptInputEvent->iVal = INPUT_VALUE_UNKNOWN; 55 } 56 return 0; 57 } 58 } 59 } 60 else 61 { 62 return -1; 63 } 64 } 65 66 return 0; 67 }
上述程序主要实现:触摸点在x方向上的位移差值超过X分辨率的1/5,就翻页,从而实现滑动翻页。