POCO C++庫學習和分析 -- 通知和事件 (一) 1. 信息交流的方法 在討論Poco中事件與通知之前,先來聊一聊信息交流的方法,這樣或許有助於理解接下去的討論。我們都知道數據之間存在關系。在數據庫模型裡,關系被分為一對一,一對多,多對多。在用計算機去解決數據關系的時候,多對多關系往往被分解成為數個一對多,而一對多的關系最終被分解成為數個一對一關系。 如果用關系的觀點去看消息流動,消息存在一個或多個發起者,即消息源Source;消息也存在一個或多個接收者,即目標對象Target;同時消息Message本身具有內容,即多種消息。簡化成為最終的一對一模型,來描述消息的,那麼這個模型裡的三個要素就是,Source,Message,Target。 把這個模型放到C++語言中,Source,Message,Target分別被抽象成為三個類。那麼消息傳送的方式可以被寫成如下兩種方式: 1.1 放置模型於編程語言 從消息源的角度來考慮問題,整個消息發送的流程是: a) 目標向消息源注冊, Source.Register(Target) 函數實現大致是這樣的 [cpp] Source.Register(Target) { source.vec.add(Target); } b) 消息產生 Source create a msg c) 消息發送,Soucre.Send(Msg) 上面這個函數大致如下: [cpp] Soucre.Send(Msg) { Target.Receive(Msg); } Target.Receive(Msg)的函數實現大致是這樣的, [cpp] Target.Receive(Msg) { switch(Msg) { case Msg1: doing something; case Msg2: doing something; default: doing something; } } 這種方式的調用可以說是最常見能夠想到的方法了。最早寫C代碼的時候,就開始使用了,到C++時代也是。 換個角度,在C++時代一切都是對象,從消息的角度來考慮這個問題呢,於是整個消息發送流程變成為: a) 目標向消息注冊, Msg.Register(Target); Msg.Register(Target)函數實現大致是這樣的 [cpp] Msg.Register(Target) Msg.vec.add(Target); b) 消息產生 a msg create by some one source c) 消息發送,Msg.Send(Source) Msg.Send(Source)函數實現大致是這樣的, [cpp] Msg.Send(Source) { switch(Source) { case Source1: doing something; case Source2: doing something; default: doing something; } } 上面就是Poco中通知與事件的大致思路。其中通知是站在消息源的角度來考慮問題,而事件是站在消息的角度來考慮問題。插一句話,Poco中的事件和代理來自於C#。也就是說,分析Poco中的事件,其實是在解釋C#的代理和事件的實現。 1.2 放置模型於多線程環境 讓我們拋開語言吧,把消息傳遞的過程放到多線程當中去。用多線程干嗎?消息的產生就是為了最終的處理,假如消息處理很耗時間怎麼辦? 沒辦法,兜裡沒銀子。那句話怎麼說來著,高富帥猛升硬件,窮挫矮死搞算法。畢竟大家不全是鐵道部,是不?於是乎把消息的產生和處理放在兩個線程中不是挺好的一個主意嗎,這樣毫無疑問消息處理的效率得到了提升。這也就是生產者和消費者模式。www.2cto.com 如果從這個角度考慮的問題的話,那麼我們得到了消息傳遞的另外一種劃分。同步處理消息和異步處理消息。 於是我們可以把消息的傳遞過程分為下面4種: 通知 | 事件 | 同步 (支持) | (支持) ——————————— 異步 (支持) | (支持) |