C語言報錯:error: expected ‘while’ at end of input } ^


在建線程池過程當中遇見上圖所示錯誤;

解決方法:

Linux中定義:

  SYNOPSIS
  #include <pthread.h>

  void pthread_cleanup_push(void (*routine)(void *),void *arg);
  void pthread_cleanup_pop(int execute);

  Compile and link with -pthread.

  DESCRIPTION
  These functions manipulate the calling thread's stack of thread-cancellation clean-up handlers. A clean-up handler is a function that is automatically executed when a thread is canceled (or in various other circumstances described below); it might, for example, unlock a mutex so that it becomes avail‐able to other threads in the process.

  The pthread_cleanup_push() function pushes routine onto the top of the stack of clean-up handlers. When routine is later invoked, it will be given argas its argument.

  The pthread_cleanup_pop() function removes the routine at the top of the stack of clean-up handlers, and optionally executes it if execute is nonzero.

  

  一般來說,Posix的線程終止有兩種情況:正常終止和非正常終止。線程主動調用pthread_exit()或者從線程函數中return都將使線程正常退出,這是可預見的退出方式;非正常終止是線程在其他線程的干預下,或者由於自身運行出錯(比如訪問非法地址)而退出,這種退出方式是不可預見的。

  不論是可預見的線程終止還是異常終止,都會存在資源釋放的問題,在不考慮因運行出錯而退出的前提下,如何保證線程終止時能順利的釋放掉自己所占用的資源,特別是鎖資源,就是一個必須考慮解決的問題。

  最經常出現的情形是資源獨占鎖的使用:線程為了訪問臨界資源而為其加上鎖,但在訪問過程中被外界取消,如果線程處於響應取消狀態,且采用異步方式響應,或者在打開獨占鎖以前的運行路徑上存在取消點,則該臨界資源將永遠處於鎖定狀態得不到釋放。外界取消操作是不可預見的,因此的確需要一個機制來簡化用於資源釋放的編程。

  在POSIX線程API中提供了一個pthread_cleanup_push()/pthread_cleanup_pop()函數對用於自動釋放資源 --從pthread_cleanup_push()的調用點到pthread_cleanup_pop()之間的程序段中的終止動作(包括調用 pthread_exit()和取消點終止)都將執行pthread_cleanup_push()所指定的清理函數。API定義如下:

  void pthread_cleanup_push(void (*routine) (void *), void *arg)
  void pthread_cleanup_pop(int execute)
  pthread_cleanup_push()/pthread_cleanup_pop()采用先入后出的棧結構管理,void routine(void *arg)函數在調用pthread_cleanup_push()時壓入清理函數棧,多次對pthread_cleanup_push()的調用將在清理函數棧中形成一個函數鏈,在執行該函數鏈時按照壓棧的相反順序彈出。execute參數表示執行到pthread_cleanup_pop()時是否在彈出清理函數的同時執行該函數,為0表示不執行,非0為執行;這個參數並不影響異常終止時清理函數的執行。

  pthread_cleanup_push()/pthread_cleanup_pop()是以宏方式實現的,這是pthread.h中的宏定義:  #define pthread_cleanup_push(routine,arg)   { struct _pthread_cleanup_buffer _buffer; 

  _pthread_cleanup_push (&_buffer, (routine), (arg));
  #define pthread_cleanup_pop(execute)
  _pthread_cleanup_pop (&_buffer, (execute)); }
  可見,pthread_cleanup_push()帶有一個"{",而pthread_cleanup_pop()帶有一個"}",因此這兩個函數必須成對出現,且必須位於程序的同一級別的代碼段中才能通過編譯。在下面的例子里,當線程在"do some work"中終止時,將主動調用pthread_mutex_unlock(mut),以完成解鎖動作。
  work"中終止時,將主動調用pthread_mutex_unlock(mut),以完成解鎖動作。
  pthread_cleanup_push(pthread_mutex_unlock, (void *) &mut);
  pthread_mutex_lock(&mut);
  /* do some work */
  pthread_mutex_unlock(&mut);
  pthread_cleanup_pop(0);
  必須要注意的是,如果線程處於PTHREAD_CANCEL_ASYNCHRONOUS狀態,上述代碼段就有可能出錯,因為CANCEL事件有可能在
pthread_cleanup_push()和pthread_mutex_lock()之間發生,或者在pthread_mutex_unlock()和pthread_cleanup_pop()之間發生,從而導致清理函數unlock一個並沒有加鎖的
mutex變量,造成錯誤。因此,在使用清理函數的時候,都應該暫時設置成PTHREAD_CANCEL_DEFERRED模式。為此,POSIX的
Linux實現中還提供了一對不保證可移植的pthread_cleanup_push_defer_np()/pthread_cleanup_pop_defer_np()擴展函數,功能與以下
代碼段相當:
{ int oldtype;
pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldtype);
pthread_cleanup_push(routine, arg);
...
pthread_cleanup_pop(execute);
pthread_setcanceltype(oldtype, NULL);
}

pthread_cleanup_push(pthread_mutex_unlock, (void *) &mut);
pthread_mutex_lock(&mut);
/* do some work */
pthread_mutex_unlock(&mut);
pthread_cleanup_pop(0);
  本來do some work之后是有pthread_mutex_unlock(&mut);這句,也就是有解鎖操作,但是在do some work時會出現非正常終止,那樣的話,系統會根據pthread_cleanup_push中提供的函數,和參數進行解鎖操作或者其他操作,以免造成死鎖!
  在線程宿主函數中主動調用return,如果return語句包含在pthread_cleanup_push()/pthread_cleanup_pop()對中,則不會引起清理函數的執行,反而會導致segment fault。
  簡單的說就是:

    

  pthread_cleanup_push()帶有一個"{",而pthread_cleanup_pop()帶有一個"}",因此這兩個函數必須成對出現,且必須位於程序的同一級別的代碼段中才能通過編譯。在下面的例子里,當線程在"do some work"中終止時,將主動調用pthread_mutex_unlock(mut),以完成解鎖動作。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM