POSIX清理函數的調用時機:
調用pthread_exit()時,會調用清理函數;通過return返回的線程不會調用。
被別的線程取消的時候,會調用。
pthread_cleanup_pop()參數為非零時,會調用。
- #include <stdio.h>
- #include <pthread.h>
- #include <windows.h> // Sleep
-
- pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
- pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
-
- struct Node
- {
- int number;
- struct Node *next;
- } *head = NULL;
-
- // 清理函數
- void cleanup_handler(void *node)
- {
- printf("Cleanup handler of second thread.\n");
- free(node);
- pthread_mutex_unlock(&mtx);
- }
-
- void* thread_func(void *arg)
- {
- struct Node *p = NULL;
- // 清理函數入棧,此demo只需一個清理函數
- pthread_cleanup_push(cleanup_handler, p);
-
- while (true)
- {
- pthread_mutex_lock(&mtx);
- if (head == NULL)
- {
- pthread_cond_wait(&cond, &mtx);
- }
- p = head;
- head = head->next;
- printf("Got %d from front of queue\n", p->number);
- free(p);
- pthread_mutex_unlock(&mtx);
- }
- /* 若從此處終止線程,則屬於正常退出,無需清理。所以,只需將清理函數出棧。故而用
- 參數零。若是從上面的“取消點”退出,則清理函數出棧時被調用:鎖被打開,同時釋放資源。*/
- pthread_cleanup_pop(0);
- return 0;
- }
-
- int main(int argc, char* argv[])
- {
- pthread_t tid;
- pthread_create(&tid, NULL, thread_func, NULL);
- for (int i = 0; i < 10; i++)
- {
- struct Node* p = (Node *)malloc(sizeof(struct Node));
- p->number = i;
-
- // <!-- 對head操作屬於臨界區
- pthread_mutex_lock(&mtx);
- p->next = head;
- head = p;
- pthread_cond_signal(&cond);
- pthread_mutex_unlock(&mtx);
- // 所以要用互斥鎖保護起來--!>
-
- Sleep(1);
- }
- printf("Main thread wants to cancel the 2nd thread.\n");
-
- /* 關於pthread_cancel,有一點額外的說明,它是從外部終止子線程,子線程會在
- 最近的取消點,退出線程。而在我們的代碼裡,最近的取消點是pthread_cond_wait()了。*/
- pthread_cancel(tid);
- pthread_join(tid, NULL);
- printf("All done -- exiting\n");
- return 0;
- }