• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            一動不如一靜

            C++博客 首頁 新隨筆 聯系 聚合 管理
              20 Posts :: 0 Stories :: 10 Comments :: 0 Trackbacks

            #

            前段時間用了ACE_TP_Reactor做了一個東西,但是對這塊東西不是很有底,所以借著假期仔細的看了一下這一塊的東西,又上網查了一下相關的資料。

            在Addison-Wesley - C++NetworkProgrammingVol2的4.3 The ACE_TP_Reactor Class中有這樣幾句話,讓我足足想了一天。

            1.Multiple threads running an ACE_TP_Reactor event loop can process events concurrently on different handles
            2.They can also dispatch timeout and I/O callback methods concurrently on the same event handler
            3.The only serialization in the ACE_TP_Reactor occurs when I/O events occur concurrently on the same handle
            4.After a thread obtains a set of active handles from select(), the other reactor threads dispatch from that handle set instead of calling select() again

            其實上面的3句話主要表達這樣的幾層含義
            1.并行處理不同handle上的事件
            2.并行處理同一event handler上的超時回調函數和I/O回調函數
            3.多個線程串行處理同一個handle上的I/O事件。
            4.雖然TP_Reactor是用leader/follow模式輪流調用select,但是如果一個select()獲得了多個激活的handle,那么其他的線程會分發這些handle ,而不是去再次調用select.
            ?(這點還沒有想通,也沒有看見是如何實現的?)

            “多個線程串行處理同一個handle上的I/O事件”
            ??? ?? 這個是如何達到的呢?ACE源碼中,當處理I/O事件的時候,會將HANDLE掛起,使得不再對該HANDLE做事件偵聽。來達到同一個handle上的I/O事件是被多個線程串行地處理。

            "并行處理同一event handler上的超時回掉函數和I/O回調函數"
            ??? ?? 這樣好像就比較麻煩了。因為這就意味著TP_Reactor只保證同一個handle下不會有多線程同時調用I/O事件,但是卻有可能同時調用超時回調函數和I/O回調函數。如果在這兩個函數中有對數據的訪問和操作,這就意味著需要有鎖的引入。例外,如果在定時器處理中,超過定時的事件間隔,就會有令一個線程再次調用定時器的處理函數,一下子引入了很多同步的問題。如何解決這個問題呢?

            方法一:

            ??? ??? ??? 更改ACE的源碼,象處理socket事件一樣,在處理定時事件的時候,也把HANDLE掛起。來自http://cpunion.cnblogs.com/archive/2005/08/09/210941.html

            int
            ACE_TP_Reactor::handle_timer_events?(
            int?&?/*event_count*/,
            ?????????????????????????????????????ACE_TP_Token_Guard?
            &guard)
            {
            ??
            //?Get?the?current?time
            ??ACE_Time_Value?cur_time?(this->timer_queue_->gettimeofday?()?+
            ???????????????????????????
            this->timer_queue_->timer_skew?());

            ??
            //?Look?for?a?node?in?the?timer?queue?whose?timer?<=?the?present
            ??
            //?time.
            ??ACE_Timer_Node_Dispatch_Info?info;

            ??
            if?(this->timer_queue_->dispatch_info?(cur_time,
            ?????????????????????????????????????????info))
            ????{
            ????????
            //?********?fixed?by?lijie?***********
            ????????if?(info.type_->get_handle?()?!=?ACE_INVALID_HANDLE)
            ????????{
            ????????????
            if?(this->is_suspended_i?(info.type_->get_handle?()))
            ????????????????
            return?0;

            ????????????
            this->suspend_handler?(info.type_->get_handle?());
            ????????}
            ????????
            //?********?end?**********************

            ??????
            const?void?*upcall_act?=?0;

            ??????
            //?Preinvoke.
            ??????this->timer_queue_->preinvoke?(info,
            ?????????????????????????????????????cur_time,
            ?????????????????????????????????????upcall_act);

            ??????

            ??????
            //?Release?the?token?before?dispatching?notifies
            ??????guard.release_token?();

            ??????
            //?call?the?functor
            ??????this->timer_queue_->upcall?(info,
            ??????????????????????????????????cur_time);

            ??????
            //?Postinvoke
            ??????this->timer_queue_->postinvoke?(info,
            ??????????????????????????????????????cur_time,
            ??????????????????????????????????????upcall_act);

            ??????
            //?We?have?dispatched?a?timer
            ??????return?1;
            ????}

            ??
            return?0;
            }

            handle_timer處理完以后,返回以前,加上這句話
            this->reactor ()->resume_handler (this->get_handle ());

            當然別忘了為Handler編寫get_handle()函數:
            ACE_HANDLE?Test_Handler::get_handle?()?const
            {
            ????
            return?this->peer?().get_handle?();
            }


            方法二:
            ??? ?? ?? ?? 利用ACE_PipeACE_Message_Queue把所有的事件都排隊到同一個I/O HANDLE上去,再由ACE_TP_Reactor通過多個線程順序串行地觸發我們舊的event_handler來處理這些已經排好隊的事件/消息。我比較贊成用這樣方法。該方法來自:http://blog.csdn.net/zhdaniel/archive/2006/06/29/850888.aspx
            ???

            ??? ??


            方法三:
            ??? ?? ?? ?? ^_^干脆就不要對同一個event? handler注冊I/O事件和其他事件。





            posted @ 2006-10-07 11:29 一動不如一靜 閱讀(3100) | 評論 (1)編輯 收藏

            來源:
            http://www.ociweb.com/products/mpc/faq.html#006

            Q :當生成工程文件名稱的時候,可以改變工程文件的名稱嗎?
            A:當用MPC生成工程文件的時候,可以用-name_modifier 選項來修改工程文件名稱.如果你也想修改工程的名稱,可以增加-apply_project.如下:
            mwc.pl -static -type vc6 -name_modifier *_Static -apply_project
            如果用了這些選項,所有的工作空間,工程文件和工程名都以_Static結尾.

            Q:怎樣用MPC在每個目錄生成一個工作空間?
            A:當運行mwc.pl的時候加上-hierarchy選項.對于所有基于'make'的工作空間是默認的.

            Q:怎樣告訴MPC在尋找mwc和mpc文件時,不要尋找某個特殊的路徑?
            A:-exclude可以用于這個目的.但是這個路徑必須是一個相對于MPC運行的路徑.如:
            mwc.pl -exclude this_dir,this_dir_too,and_another_dir

            Q:怎樣在我的工作空間中用-value_template
            A:在mwc文件中,你能用很多mwc.pl的命令行選項.要加上cmdline關鍵字.如果在命令行中需要有空格,必須包含在""之中.如:
            workspace {
            ? // Set the command line value to change the configurations with vc6, vc71 and vc8
            ? cmdline += -value_template "configurations='MFC Release' 'MFC Debug'"
            }

            Q:有沒有辦法在Solaris,工程中包含一個文件,但是在Linux上不包含該文件呢?
            A:你可以用feature定義一個base工程.如下:
            // config/default.features
            solaris_only = 0


            // some_base.mpb
            feature(solaris_only) {
            ? Source_Files {
            ??? source1.cpp
            ??? source2.cpp
            ? }
            }?


            // your_project.mpc
            project: some_base {
            ? Source_Files {
            ??? source3.cpp
            ??? source4.cpp
            ? }
            }?

            Q:可不可以一些選項用于某客戶文件,而另外一些用于其他的客戶文件呢?
            A:你可以為用戶的輸入文件創建多個部分.如下:
            project: foo {
            FOO_Files {
            foo.file
            }

            FOO_Files {
            commandflags += -QR
            bar.file
            }
            }
            Q:有沒有辦法表明編譯選項?
            A:可以用'specific' .如:
            project {

            ? specific(make) {
            ??? compile_flags += -fcheck-new
            ? }

            ? specific(vc71) {
            ??? compile_flags += /wd4103
            ? }
            }?

            Q:在一個工作空間中,想有靜態和動態的工程?
            A:在mwc文件中,建立一個域范圍.增加-static到命令行選項.如:
            workspace {
            ? // These projects will be static
            ? some_scope_name {
            ??? cmdline += -static
            ??? my_projects_dir??
            ??? my_other_projects_dir
            ? }

            ? // Anything outside the scope will have the command line options provided at the start of mwc.pl
            ? another_dir
            }

            Q:有沒有方法在mpc文件中表明這個庫必須是靜態庫,其他的庫不能把它用做動態庫?
            A:設置靜態庫名,而動態庫名為空.
            project {
            ? sharedname =
            ? staticname = foo
            }

            Q:MPC添加d.lib到所有的庫.有沒有辦法關掉它?
            A:在mpc文件中用'lit_libs'代替libs

            Q:為vc6和vc71生成靜態工程,可是卻沒有工程的依賴?
            A:可以通過設置MPC_DEPENDENCY_COMBINED_STATIC_LIBRARY環境變量,強迫MPC生成工程間相互依賴的的靜態庫.

            Q:有沒有方法可以強制在靜態庫名后有's'但是debug版本沒有'd'
            A:是的,你能設置lib_modifier,用這個配置座位域修改器.在下面的例子中,假設-static選項已經傳遞給了MPC
            project {
            ? // Override the values of 's' and 'sd' respectively.
            ? specific {
            ??? Release::lib_modifier =
            ??? Debug::lib_modifier = d
            ? }
            }?

            Q:由MPC生成的VC71工程,用release ,生成的執行文件在release目錄中.而debug是在"."目錄中,怎樣才能把執行文件放在debug目錄中. ???
            A: 增加改行到MPC工程中
            project {???????????????????
            ? specific(nmake, vc6, vc7, vc71, vc8) {
            ??? Debug::install = Debug
            ? }
            }

            Q:如何生成支持MFC的版本
            A:MPC的命令行增加下面一行
            -value_template "configurations='MFC Release' 'MFC Debug'"
            這個可以用于 em3, nmake, vc6, vc7, vc71 和 vc8 工程類型的配置
            提醒一下,別忘了創建config.h文件,內容類似如下:
            #include "config-win32.h"
            #include "config-win32-msvc-7.h"



            posted @ 2006-06-24 10:18 一動不如一靜 閱讀(1375) | 評論 (1)編輯 收藏

            ??? ?? ACE_WFMO_Reactor允許多個線程并發的調用handle_events(),這個能力的增加使得它的設計變的復雜,并且引入了一些同基于select的反應器不同的地方.不同點如下:
            • 注冊改變的協調.已注冊句柄集合的每一個改變,將會影響到所有執行事件循環的線程.在沒有同步的情況下允許這些改變的發生,會導致丟失事件,或不正確,不合法的句柄被分發.為了在多線程的情況下,正確的處理注冊發生改變的情況,ACE_WFMO_Reactor維持了三個句柄信息集合對象.
            1. 用作事件偵查和分發的當前句柄
            2. 新句柄, 除了當前句柄集合,新句柄也在等待
            3. 掛起句柄,是當前句柄中掛起的句柄
            當需要改變已注冊的句柄時,(例如:注冊,移除,掛起和恢復一個事件處理器),要記住句柄,事件處理器,事件類型信息,和相關信息的記錄.下一個完成handle_events的線程會注意到這個改變,獲取reactor的鎖,等待所有其他正在運行handle_events的線程完成.為了能讓這些線程及時的完成,等待的線程發送一個內部事件,該內部事件是分發句柄集合的一部分.喚醒所有阻塞在WaitForMultipleObjects的線程.這個時候,所有的事件處理線程將會阻塞在等待變化的發生.當原始的線程完成必要的信息和句柄改變后,釋放reactor的鎖.所有的事件處理線程重新開始在更新后的句柄集合上進行等待,分離和分發.
            • 推遲事件處理器的清除.ACE_WFMO_Reactor注冊改變的延遲引入了一些與基于select()的反應器的不同之處.當hanle_*()方法返回-1或者ACE_Reactor::remove_handler()被事件處理器調用時,它推遲事件處理器的移除和handle_close()鉤子函數的回調,直到上面說講的注冊改變發生.所以一個應用在請求ACE_WFMO_Reactor移除一個事件處理器之后,不能立即刪除該事件處理器,否則reator后來調用的handle_close()方法會分發一個無效的指針.
            posted @ 2006-06-23 20:48 一動不如一靜 閱讀(802) | 評論 (0)編輯 收藏

            1.修飾類的數據成員
            const數據成員只是在某個對象的生命周期內是常量.如果創建多個對象,那么每個對象的const數據成員可以不一樣.所以,不能在類聲明中初始化const數據成員.如:
            class A
            {
            ???const int size = 100;//?錯誤
            ???int array[size];//錯誤,未知的數組大小
            }
            const類數據成員,只能在類的構造函數的初始化列表中進行.要想建立整個類都是恒定的常量的數據,可以用類中的枚舉.如:
            class A
            {
            enum {size1 = 100, size2 = 200};
            int array[size1];
            }

            2.只有聲明為const的成員函數才能被一個const對象調用

            3.在另一連接文件中引用const常量.
            extern const int i

            4.對于const對象,c++既允許對其進行靜態初始化,也允許對其進行動態初始化.const對象具有從構造函數完成到析構函數執行之前的不變性.

            5.常量與數組的組合有什么特殊嗎?
            我們給出下面的代碼:
            const int size[3]={10,20,50};
            int array[size[2]];
            編譯通不過!為什么呢?const可以用于集合,但編譯器不能把一個集合存放在它的符號表里,所以必須分配內存。在這種情況下,const意味著“不能改變的一塊存儲”。然而,其值在編譯時不能被使用,因為編譯器在編譯時不需要知道存儲的內容。自然,作為數組的大小就不行了
            你再看看下面的例子:
            class A
            {
            public:
            A(int i=0):test[2]({1,2}) {} file://你/認為行嗎?
            private:
            const int test[2];
            };
            C++標準有一個規定,不允許無序對象在類內部初始化,數組顯然是一個無序的,所以這樣的初始化是錯誤的!對于他,只能在類的外部進行初始化,如果想讓它通過,只需要聲明為靜態的,然后初始化。
            這里我們看到,常量與數組的組合沒有什么特殊!一切都是數組惹的禍!

            (7)什么情況下為const分配內存?
            以下是我想到的可能情況,當然,有的編譯器進行了優化,可能不分配內存。
            A、作為非靜態的類成員時;
            B、用于集合時;
            C、被取地址時;
            D、在main函數體內部通過函數來獲得值時;
            E、const的 class或struct有用戶定義的構造函數、析構函數或基類時;。
            F、當const的長度比計算機字長還長時;
            G、參數中的const;
            H、使用了extern時。

            (8)與static搭配會不會有問題?
            假設有一個類:
            class A
            {
            public:
            ......
            static void f() const { ......}
            ......
            };
            我們發現編譯器會報錯,因為在這種情況下static不能夠與const共存!因為static沒有this指針,但是const修飾this指針.

            (9)如何修改常量?
            有時候我們卻不得不對類內的數據進行修改,但是我們的接口卻被聲明了const,那該怎么處理呢?我對這個問題的看法如下:
            1)標準用法:mutable
            class A
            {
            public:
            A(int i=0):test(i) { }
            void Setvalue(int i)const { test=i; }
            private:
            mutable int test; file://這/里處理!
            };
            2)強制轉換:const_cast
            class A
            {
            public:
            A(int i=0):test(i) { }
            void Setvalue(int i)const
            { const_cast <int>(test)=i; }//這里處理!
            private:
            int test;
            };

            (10)最后我們來討論一下常量對象的動態創建。
            既然編譯器可以動態初始化常量,就自然可以動態創建,例如:
            const int* pi=new const int(10);
            這里要注意2點:
            1)const對象必須被初始化!所以(10)是不能夠少的。
            2)new返回的指針必須是const類型的。
            那么我們可不可以動態創建一個數組呢?
            答案是否定的,因為new內置類型的數組,不能被初始化。
            posted @ 2006-06-14 17:49 一動不如一靜 閱讀(425) | 評論 (0)編輯 收藏

            c++中的引用又稱為別名.

            1. 引用必須被初始化,即必須指向一個對象.
            ?int nTemp = 10;
            int &refTemp = nTemp;

            2.初始化之后就不能再指向其他對象.如果用一個引用給另一個引用賦值,那么被改變的是被引用的對象而不是引用本身.
            int nOther = 20;
            refTemp = nOther; //此時nTemp中的值為20,但是&refTemp和&nTemp是相同的.

            3.用const修飾的引用可以用不同類型的對象初始化(只要能從一種類型轉換到另外一種類型),也可以是不可尋址的值.能夠這樣的原因是因為:編譯器做了手腳.
            double dTemp = 1024;
            const int &refTemp = dTemp; //&dTemp和&refTemp是不同的.

            編譯之后成為:
            double dTemp = 1024;
            int nTemp = dTemp;
            const int &refTemp = nTemp;

            4.不允許非const引用指向需要臨時對象的對象或值.


            posted @ 2006-06-14 15:55 一動不如一靜 閱讀(451) | 評論 (0)編輯 收藏

            兩本書的錯誤的更新
            http://www.cs.wustl.edu/~schmidt/ACE/book1/Errata.txt

            http://www.cs.wustl.edu/~schmidt/ACE/book2/Errata.txt

            英文討論組
            http://groups.google.com/group/comp.soft-sys.ace

            http://groups.google.com/group/comp.soft-sys.ace?lnk=oa

            中文討論區
            http://forum.huihoo.com/forumdisplay.php?fid=125

            相關文檔
            http://www.cs.wustl.edu/~schmidt/ACE.html

            有關mpc問題
            http://www.ociweb.com/products/mpc/faq.html#021

            源碼中標記的含義
            http://www.stack.nl/~dimitri/doxygen/commands.html
            posted @ 2006-06-13 15:23 一動不如一靜 閱讀(628) | 評論 (0)編輯 收藏

            ???????? #include <iostream>
            ???????? #include <string>

            ???????? std::cin.widen(1024);

            ???????? for (; ;)
            ???????? {
            ?????????????? std::string user_input;
            ?????????????? std::getline(std::cin, user_input, '\n');
            ??????????????
            ?????????????? if? (!std::cin || std::cin.eof()) break;
            ?????????????
            ?????????????? std::cerr << user_input;
            ?????????
            ???????? }

            posted @ 2006-06-13 10:01 一動不如一靜 閱讀(292) | 評論 (0)編輯 收藏

            這篇內容來自c++網絡編程卷1 第七章 ACE同步事件分離封裝.

            ????????????????????????????????????????????????????????????? Sidebar 14: Motivation for Nonblocking Acceptors

            ???????? 當把一個Acceptor socket傳遞給select(),如果收到一個鏈接,那么該socket被標識為激活狀態.很多服務器利用這個事件去表明可以調用accept(),不會引起阻塞.不幸的是,有來自TCP/IP異步行為的資源競爭.在實際中,select()之后就表明一個acceptor socket是激活的(但是在accept()調用之前),client可以關閉它的連接,一旦accept()阻塞潛在的掛起整個進程.為了避免這個問題,acceptor socket當和select()一起使用的時候,應該一直被設置為非阻塞的模式.在ACE中,這步工作很方便,只要傳遞ACE_NONBLOCK標識給enable()方法就可以了.enable()方法是ACE_IPC_SAP提供的,所以ACE_SOCK_Acceptor也擁有.
            posted @ 2006-06-12 11:18 一動不如一靜 閱讀(606) | 評論 (0)編輯 收藏

            1.最好先用ACE自身的例子,測試所編庫的正確性.
            2.確保ACE.lib或ACEd.lib能正確的鏈接到工程中.
            3.如果出現"__declspec(dllimport) int __cdecl ace_os_main_i"字樣的鏈接錯誤,可以考慮加上#include "ace/OS_main.h"
            posted @ 2006-06-11 23:18 一動不如一靜 閱讀(26296) | 評論 (5)編輯 收藏

            在類中聲明成員方法的時候,只有純虛函數才可以不用實現.
            虛函數必須實現,否則會出現error LNK2001的錯誤.

            posted @ 2006-06-11 23:06 一動不如一靜 閱讀(429) | 評論 (0)編輯 收藏

            僅列出標題
            共2頁: 1 2 
            国产精品永久久久久久久久久| 久久国产免费观看精品3| 久久精品国产精品亚洲艾草网美妙| 国内精品久久久久久久亚洲| 久久综合给合综合久久| 精品久久久久久国产| 久久99国产精品久久| 亚州日韩精品专区久久久| 国内精品久久久人妻中文字幕| 亚洲精品国产成人99久久| 精品久久久无码21p发布| 亚洲国产精品久久久久久| 久久综合九色综合网站| 国产亚州精品女人久久久久久| 久久精品国产久精国产思思| 久久综合久久伊人| 久久婷婷综合中文字幕| 亚洲va久久久噜噜噜久久天堂| 久久精品无码一区二区app| 精品国产一区二区三区久久| 国产美女亚洲精品久久久综合| 国产成人久久777777| 狠狠干狠狠久久| 久久精品中文闷骚内射| 亚洲精品无码久久千人斩| 久久伊人五月丁香狠狠色| 久久精品无码一区二区日韩AV| 青青草国产精品久久久久| MM131亚洲国产美女久久| 亚洲乱码中文字幕久久孕妇黑人| 天天综合久久一二三区| 亚洲v国产v天堂a无码久久| 久久精品国产精品亚洲下载| 国产精品成人99久久久久91gav| www性久久久com| 国产激情久久久久影院小草| 国产精品日韩深夜福利久久| 久久激情五月丁香伊人| 无码人妻久久一区二区三区蜜桃| 久久精品国产亚洲精品| 狠狠久久综合伊人不卡|