Sofia的同步與多線程

        本文介紹Sofia的同步與多線程接口。

        Sofia工具庫提供了簡單的,不依賴操作系統的同步接口。同步接口包含用於管理 事件、消息、時間和多線程的原語。

克隆對象

        通過克隆,可以把進程分爲多個任務。

        幾個任務可以運行在一個線程的上下文中,也可以每個任務運行自己的線程。但是,只有一個任務中的代碼,只能由一個線程執行。線程與任務間的關係是1對N的。軟件中的多任務,既可以由多線程環境中的多個線程執行;也可以由單線程環境中的單一線程執行。

        克隆有利於使用獨立線程處理多任務又不造成過多阻塞。當多線程不可用或不需要時,也可以在單線程模式下運行克隆。在單線程模式下進行debug調試是特別有幫助的。

        通過 su_clone_start()函數任務創建克隆。每次克隆都有它的根對象(su_root_t),它持有一個上下文指針(su_root_magic_t *)。上下文對象可以不同於父任務的對象。

        當任務克隆開始時,調用克隆初始化函數。初始化函數執行所有需要初始化的東西,註冊IO事件和定時器,然後返回。如果初始化成功,克隆任務返回運行事件循環並調用事件回調函數,直到其父任務調用 su_clone_wait()才停止,它還會調用清理函數。克隆任務在清理函數返回時被銷燬。

        公共API包含以下函數:

注意:

        每個線程只有一個事件循環,它可以共享給多個克隆任務。因此,克隆任務不能顯式運行或設置事件循環,它們僅限於事件回調。克隆任務不能調用su_root_break()su_root_run() 或 su_root_step()這些函數。

任務與根(root)對象

        在Sofia的事件驅動編程模型中,任務是基本的執行單元。

        根據模型,程序可以要求事件循環在某個特定事件觸發時調用回調函數。這類事件包括:I/O活動、定時器,或其它任務的消息。事件循環通過su_root_run() 或 su_root_step()函數執行。

        Root 對象可以訪問任務控件。root對象代理在任務中執行的任務代碼。通過root,任務代碼可以訪問它的context對象和線程同步功能,比如說等待對象、定時器,還有消息。

        在任務之間發消息時,使用任務引用 su_task_r 描述任務的地址。引用計數器可以保證任務引用的有效性。

        公用API包含以下函數:

        通過su_clone_start() 函數可以創建新的任務。

註冊等待對象

        當應用程序希望捕獲I/O事件時,它可以使用 su_root_register() 函數創建並註冊一個等待對象,這時需要一個回調函數指針和一個指向su_root_t 對象的context指針。當等待對象收到相應事件時,會調用註冊的回調函數。

        註冊成功時, su_root_register()返回一個非負小整數描述註冊本身。可以通過su_root_eventmask()函數操作註冊,例如:通過socket發送數據時,應用程序可以向掩碼是添加SU_WAIT_OUT事件。

        可以使用 su_root_deregister() 函數刪除之前的註冊信息。

定時器對象

        用定顯示器安排在特定時間或間隔多少時間後執行給定任務。

The default interval is specified when the timer is created. We call timer activation "setting the timer", and deactivation "resetting the timer" (as in SDL). When the given time has arrived or the default interval has elapsed, the timer expires and it is ready for execution.

        創建定時器時指定默認時間間隔。 我們把定時器激活稱爲“設置計時器”,把取消激活稱爲“重置定時器”(如SDL)。 當給定時間到達或默認間隔過去時,定時器到期觸發,執行給定任務。

        以下是用於創建、銷燬、激活,管理定時器的相關函數:

注意:

        定時器使用poll()喚醒等待線程。在Linux環境下,定時器的精度是由HZ內核參數決定的,它取決於內核編譯時的參數設定。內核2.4版本中,默認精度是10毫秒,定時器的最小持續時間間隔是20毫秒。當然,使用RTC可以獲得更高的精度,但使用64Hz以上的RTC是一種特權操作。

        在Windows環境中,定時器的精度取決於實時時鐘定時器。默認條件下,它使用18.78 Hz的精度。使用Windows多媒體庫時,時鐘精度可以調整爲1000 Hz。

 

使用定時器

        調用su_timer_create()函數創建一個定時器:

   timer = su_timer_create(su_root_task(root), 200);

        時間間隔的單件是毫秒。

        通常,應該定期調用定時器的喚醒函數。這時,使用su_timer_set_for_ever()函數激活定時器。當定時器被激活時,它被賦予了喚醒函數和指向上下文數據的指針:

   su_timer_set_for_ever(timer, timer_wakeup, args);

        當指定的時間間隔過去時,root事件循環調用喚醒函數:

   timer_wakeup(root, timer, args);

        如果調用回調函數的次數很重要,請使用su_timer_run()。run timer會嘗試補償錯過的時間,並在需要時多次調用回調函數。(因爲可以調整實時時鐘,或者把程序掛起,比如說在調試時,可以連續調用數千次回調函數。)請注意,雖然定時器嘗試補償回調之前和期間發生的延遲,但它不能用作計時信息的確切來源

        調用su_timer_reset() ,定時器停止運行。

        或者,可以將定時器設置爲一次事件調用。設置定時器時,它綁定喚醒函數和上下文相關數據。也可以使用using su_timer_set_at()指定實際持續時間。

 su_timer_set(timer, timer_wakeup, args);

        定時器超時觸發時,root事件循環會調用喚醒函數:

   timer_wakeup(root, timer, args);

        如果不再需要定時器事件,可以重置定時器:

   su_timer_reset(timer);

        如果希望定期調用定時器,可以通過su_timer_run()設置ro爲持續運行。當持續運行的定時器激活時,不能調用 su_timer_set() 或 su_timer_set_at()進行設置。

        如果不再需要定時器,應當銷燬定時器對象本身:

   su_timer_destroy(timer);

等待對象

      可以使用等待對象信進程發送I/O事件信號。

以下是事件類型:

  • SU_WAIT_IN - 輸入數據在socket上可用
  • SU_WAIT_OUT - 數據可以通過socket發送
  • SU_WAIT_ERR - socket錯誤
  • SU_WAIT_HUP - socket連接關閉
  • SU_WAIT_ACCEPT - 監聽中的socket接受一個新的連接嘗試

        可以通過管道符|,二進制數或操作符將幾個事件組合。

        可以通過以下幾個函數管理等待對象:

注意:

在Unix平臺下,,等待對象是個poll結構體。它包含一個文件描述符,一個描述預期事件的掩碼,還有一個容納su_wait()調用之後發生事件的掩碼,比如說poll()。

Windows平臺下,等待對象是一個HANDLE (Windows 內核實體的描述符)。


變量文檔

int su_root_size_hint

包含su_root_t所支持的socket的數量的提示。

提示在su_root是已註冊的fd的數量。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章