前面講到,使用非阻塞方式有許多的缺點。主要是單線程,一直占用CPU資源,其他程式無法執行,造成資源的浪費。只能用於較簡單迴圈的場所。而線程靈活,CPU占用率小,適用於大部分場合。 1.條件變數的使用 條件變數是用來通知共用數據的狀態信息的機制。由於涉及共用數據,所以一般和互斥量配合使用。 1.1創建 ...
前面講到,使用非阻塞方式有許多的缺點。主要是單線程,一直占用CPU資源,其他程式無法執行,造成資源的浪費。只能用於較簡單迴圈的場所。而線程靈活,CPU占用率小,適用於大部分場合。
1.條件變數的使用
條件變數是用來通知共用數據的狀態信息的機制。由於涉及共用數據,所以一般和互斥量配合使用。
1.1創建和銷毀條件變數
pthread_cond_t表示條件變數。在使用pthread_cond_t變數前對其進行初始化。使用預設屬性,可以用PTHREAD_COND_INITIALIZER付給變數就可以完成初始化。
pthread_cond_desroy銷毀一個條件變數。函數形式為
1 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函數。
1 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,就翻頁,從而實現滑動翻頁。