在事件驅動的應用中利用隊列來處理事件是一種常見的方法。 事件驅動的應用主要遵循實時事件發生的順序來執行。 例如,在java或windows中開發圖形用戶界面,應用程式的行為主要取決於鍵盤操作、滑鼠點擊等一些由用戶觸發的事件。其他一些數據驅動型的例子還包含飛機或工廠設備中的控制系統等。 在很多事件驅動 ...
在事件驅動的應用中利用隊列來處理事件是一種常見的方法。
事件驅動的應用主要遵循實時事件發生的順序來執行。
例如,在java或windows中開發圖形用戶界面,應用程式的行為主要取決於鍵盤操作、滑鼠點擊等一些由用戶觸發的事件。其他一些數據驅動型的例子還包含飛機或工廠設備中的控制系統等。
在很多事件驅動的應用中,事件可能隨時發生,因此在能夠處理這些已經發生的事件之前,有序地存儲和管理這些事件是非常重要的。由於系統處理事件的順序基本是按照事件發生的先後順序進行的,因此隊列是處理這種情況的較好的辦法。
示例1列舉了兩個用於事件處理的函數:receive_event和process_event。兩個函數都用於處理包含Event類型事件的隊列。Event在event.h中定義,在此沒有列舉出來。
一個應用程式調用receive_enent將一個將要處理的事件入隊。當應用程式認為是時候來處理一個事件時,它就會調用process_event函數。
在process_event函數內部,事件從隊列中出隊,並轉交由應用程式指定的具體的調度函數處理。調度函數作為參數dispatch傳遞給process_event。使用調度函數的目的是採取適當的行為來處理事件。
一般有兩種常用的調度方法:同步地處理事件,即在處理的事件未完成之前無法進行下一個操作;非同步地處理事件,即在事件處理的過程中,還能另外啟動獨立進程來處理其他事件。通常非同步處理效率更高,但在處理主從進程之間的關係時需要特別小心,以免衝突。
receive_event的運行時複雜度為O(1),因為它只調用了複雜度為O(1)的隊列操作queue_enqueue。process_event的運行時複雜度取決於它所調用的調度函數。process_event剩下部分運行固定的時間。
示例1: 處理事件函數的實現
/*events.c*/ #include <stdlib.h> #include <string.h> #include "event.h" #include "events.h" #include "queue.h" int receive_event(Queue *enents,const Event *event) { Event *new_event; if((new_event = (Event*)malloc(sizeof(Event))) == NULL) return -1; memcpy(new_event,event,sizeof(Event)); if(queue_enqueue(events,new_event) != 0) return -1; return 0; } int process_event(Queue *events,int (*dispatch)(Event *event)) { Event *event; if(queue_size(events) == 0) return -1; else { if(queue_dequeue(events,(void**)&event) != 0) return -1; else { dispatch(event); free(event); } } return 0; }