<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      threading

      概覽:

           Chromium是一個(gè)有著諸多線程的產(chǎn)品。我們盡量保證UI的快速響應(yīng),這就意味著不能有任何的堵塞的I/O或者耗時(shí)操作來堵塞UI線程。我們把在線程間傳遞消息作為線程間通信的方法。我們摒棄了鎖和線程安全對(duì)象,取而代之的是一個(gè)對(duì)象只生存在一個(gè)線程中,我們通過在線程間傳遞消息來通訊,并且我們使用回掉接口(由發(fā)送消息者實(shí)現(xiàn))來完成線程間的請(qǐng)求。

           Thread在base/thread.h中定義,我們已經(jīng)有很多線程以至難以跟蹤了,大體上你可以使用一個(gè)下面列表中已有的線程而不是新建一個(gè)線程。每個(gè)線程都有一個(gè)MessageLoop(參考:base/message_loop.h)為線程處理消息。你可以通過Thread.message_loop()來獲取消息循環(huán)。

           大部分的線程都是由BrowserProcess對(duì)象來管理的,BrowserProcess在“browser”主進(jìn)程中扮演者服務(wù)管理者的角色。一般情況下,所有事件都是發(fā)生在UI線程(應(yīng)用程序啟動(dòng)的主線程)。我么把具體的某個(gè)處理類內(nèi)置到了其他線程,它(BrowserProcess)具有以下線程的getter方法??:

      • io_thread:該線程并不名副其實(shí)。它其實(shí)是個(gè)派發(fā)線程,它負(fù)責(zé)瀏覽器主線程和其他子線程的通信。它也是所有資源請(qǐng)求(網(wǎng)頁加載)的來源。
      • file_thread:文件操作的線程。當(dāng)你要執(zhí)行一個(gè)阻塞的文件系統(tǒng)操作(例如,加載一個(gè)文件中的icon,或者寫入下載的文件),發(fā)送消息到該線程。
      • db_thread:數(shù)據(jù)庫操作的線程。例如,cookie服務(wù)會(huì)在該線程執(zhí)行數(shù)據(jù)庫操作。注意:歷史記錄數(shù)據(jù)庫不在該線程操作。
      • safe_browsing_thread

      幾個(gè)組建由他們自己的線程:

      • History:歷史記錄對(duì)象有自己的線程。看起來可以和上面的數(shù)據(jù)庫線程合并。然而,我們需要保證某些事件按照正確的順序執(zhí)行--例如:cookies由于第一次啟動(dòng)的時(shí)候需要比歷史先加載,并且加載歷史十分耗時(shí)會(huì)阻塞住。
      • ProxyServices:可以查閱net/http/http_proxy_service.cc。
      • Automation proxy:測試程序通過該線程與瀏覽器通信,控制瀏覽器行為。

       

      保持瀏覽器及時(shí)響應(yīng)

        正如在概述中提示的,我們極力的避免在UI線程做阻塞的I/O操作來保持UI的及時(shí)響應(yīng)。更加需要注意的是我們也需要盡量避免在IO線程做阻塞的I/O操作。如果我們阻塞住,意味著磁盤操作,然后IPC消息也無法得到處理。表現(xiàn)就是用戶無法與頁面交互。需要注意的是異步/重疊 IO是個(gè)不錯(cuò)的選擇。

        另外需要注意的是線程之間不要互相有阻塞的操作。索只有在多個(gè)線程共享交換數(shù)據(jù)的結(jié)構(gòu)中使用。這樣,如果一個(gè)線程更新有一個(gè)很耗計(jì)算的操作或者文件訪問就不會(huì)等待解鎖。只有當(dāng)結(jié)果是可預(yù)期的時(shí)候才可以用鎖來完成數(shù)據(jù)交換。一個(gè)例子是Plugin::LoadPlugins(src/webkit/glue/plugins/plugin_list.cc),如果你必須使用鎖,這里有很好的練習(xí)以防調(diào)入陷阱。

        為了寫出非阻塞的代碼,很多API在chromium都是異步的。通常情況下,這就意味著要么需要在特定的線程執(zhí)行然后通過定制的委托接口吧結(jié)果傳回來,要么在請(qǐng)求結(jié)束的時(shí)候調(diào)用base::CallBack<>對(duì)象。在指定線程執(zhí)行任務(wù)在PostTask的部分有具體描述。

       

      Getting stuff to other threads

      base::CallBack<>,Async APIs,and Currying

      base::CallBack<>(參見docs in callback.h)是一個(gè)模版類,內(nèi)部有個(gè)Run()方法。他是一個(gè)全局的函數(shù)指針,在調(diào)用base::Bind的時(shí)候創(chuàng)建。異步Apis經(jīng)常會(huì)把base::CallBack<>作為異步返回操作結(jié)果的方法。下面是一個(gè)假想的異步讀取文件的API:

      void ReadToString(const std::string& filename, const base::Callback<void(const std::string&)>& on_read);
      
      void DisplayString(const std::string& result) {
        LOG(INFO) << result;
      }
      
      void SomeFunc(const std::string& file) {
        ReadToString(file, base::Bind(&DisplayString));
      };

      在上面的例子中,base::Bind 以&DisplayString為參數(shù),并且轉(zhuǎn)化為一個(gè)base::Callback<void(const std::string& result)>.類型base::Callback<>是通過參數(shù)推斷的。為何不直接傳遞函數(shù)指針呢?原因就是base::Bind 允許調(diào)用者適應(yīng)函數(shù)接口通過Currying (http://en.wikipedia.org/wiki/Currying)增加一些額外的內(nèi)容。例如,如果有一個(gè)函數(shù)DisplayStringWithPrefix 有些額外的參數(shù)作為前綴,我們通過base::Bind適應(yīng)下面的接口:

      void DisplayStringWithPrefix(const std::string& prefix, const std::string& result) {
        LOG(INFO) << prefix << result;
      }
      
      void AnotherFunc(const std::string& file) {
        ReadToString(file, base::Bind(&DisplayStringWithPrefix, "MyPrefix: "));
      };

      這樣可以用來替代通過在類中以成員變量保存前綴變量并創(chuàng)建一個(gè)適配的函數(shù)的方法。另外要注意“MyPrifx:”參數(shù)實(shí)際上是一個(gè)const char *,然而DisplayStringWithPrefix 實(shí)際上是需要const std::string& 如同通常的函數(shù)派發(fā),如果可以的話base::bind會(huì)強(qiáng)制轉(zhuǎn)換參數(shù)類型。查閱下面“How arguments are handled by base::Bind()”關(guān)于詳細(xì)的參數(shù)保存,拷貝,引用。


      PostTask

        派發(fā)消息到其他線程最初級(jí)的方法就是使用MessageLoop.PostTask和MessageLoop.PostDelayTask(參閱base/message_loop.h) PostTask安排任務(wù)在指定的線程上執(zhí)行。任務(wù)需要定義成base::Closure類型,它是typedef的base::Callback<void(void)>.PostDelayedTask安排一個(gè)任務(wù)在指定線程延遲執(zhí)行。一個(gè)任務(wù)就是擁有一個(gè)Run()方法的base::Closure,通過調(diào)用base::Bind()創(chuàng)建。消息循環(huán)通過調(diào)用Run方法來執(zhí)行任務(wù),然后減少對(duì)task對(duì)象的引用。PostTask和PostDelayTask都有一個(gè)參數(shù)tracked_objects::Location,它用來實(shí)現(xiàn)一個(gè)輕量級(jí)的調(diào)試(統(tǒng)計(jì)刮起和任務(wù)完成的性能,在debug版本中通過url about:objects查看),通常該參數(shù)用FROME_HERE宏來代替。

        需要注意的是新的任務(wù)運(yùn)行在消息循環(huán)依賴的隊(duì)列中,所指定的任何延誤是操作系統(tǒng)的定時(shí)器決定的。這就意味著,在windows下,一個(gè)很短的延時(shí)(小于10ms)會(huì)不精確(實(shí)際上會(huì)更大一些)。使用PostDelayTask延遲0執(zhí)行和直接PostTask效果一樣。PostTask也經(jīng)常會(huì)用來給當(dāng)前線程投遞任務(wù)“有時(shí)候在當(dāng)前處理返回到消息循環(huán)的時(shí)候”這樣的一個(gè)延續(xù),可用于在當(dāng)前線程上,以確保其他時(shí)間的關(guān)鍵任務(wù)不會(huì)被餓死在此線程。

        下面是一個(gè)例子,掩飾如何創(chuàng)建一個(gè)任務(wù),然后發(fā)送到另外一個(gè)線程(本例中是file thread):
      void WriteToFile(const std::string& filename, const std::string& data);
      BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
      base::Bind(&WriteToFile, "foo.txt", "hello world!"))


        你可以使用BrowserThread來在線程間發(fā)送任務(wù)。永遠(yuǎn)不要緩存MessageLoop指針,因?yàn)闀?huì)導(dǎo)致bug,例如你還持有指針,但是它已經(jīng)被刪除了。更多內(nèi)容請(qǐng)參考這里


      base::Bind() and class method
      base::Bind() API也支持類成員函數(shù)。寫法類似普通函數(shù),除了第一個(gè)參數(shù)必須是該方法所屬的對(duì)象。一般情況向,這個(gè)對(duì)象必須是 thread-safe reference-counted。引用技術(shù)確保在其他線程調(diào)用的時(shí)候該對(duì)象依然或者,知道任務(wù)完成。

      class MyObject : public base::RefCountedThreadSafe<MyObject> {
      public:
      void DoSomething(const std::string16& name) {
      thread_->message_loop()->PostTask(
      FROM_HERE, base::Bind(&MyObject::DoSomethingOnAnotherThread, this, name));
        }

      void DoSomethingOnAnotherThread(const std::string16& name) {
      ...
      }
       private:
      // Always good form to make the destructor private so that only RefCountedThreadSafe can access it.
      // This avoids bugs with double deletes.
      friend class base::RefCountedThreadSafe<MyObject>;

      ~MyObject();
        Thread* thread_;
      };

      如果你有外部同步化的結(jié)構(gòu),它可以確保任務(wù)在執(zhí)行的時(shí)候保持對(duì)象存活,那么你可以使用base::Unretained()包裝對(duì)象指針,使得調(diào)用base::Bind()的時(shí)候禁用引用計(jì)數(shù)。這個(gè)也允許使用在非引用計(jì)數(shù)的類上,請(qǐng)小心使用!

      how arguments are handled by base::Bind()

        參數(shù)拷貝到了內(nèi)部的結(jié)構(gòu)體(InvokeStorage)中(base/bind_internal中定義)。函數(shù)調(diào)用的時(shí)候他會(huì)拷貝參數(shù)。如果方法中有參數(shù)是常引用,這個(gè)引用會(huì)指向拷貝的參數(shù)。如果需要只想原始參數(shù)的引用,可以使用base::ConstRef()。要小心使用,例如在傳遞參數(shù)的時(shí)候不能保證存活就很危險(xiǎn)。尤其是永遠(yuǎn)不要對(duì)棧上的變量使用base::ConstRef()除非你能保證在異步調(diào)用完成前棧幀保持有效。

        有時(shí)候你會(huì)想以一個(gè)引用計(jì)數(shù)的對(duì)象作為參數(shù)(保證使用的是從RefCountedThreadSafe集成的類型,而不是簡單的從RefCounted繼承的類型)。為了確保對(duì)象的生存期能夠覆蓋整個(gè)請(qǐng)求,Closure需要保有一個(gè)對(duì)象的指針。這可以通過scoped_refptr作為參數(shù)類型,或者用make_scoped_refptr()包裝一個(gè)原始的指針實(shí)現(xiàn):
        
      class SomeParamObject : public base::RefCountedThreadSafe<SomeParamObject> {
      ...
      };

      class MyObject : public base::RefCountedThreadSafe<MyObject> {
      public:
      void DoSomething() {
      scoped_refptr<SomeParamObject> param(new SomeParamObject);
      thread_->message_loop()->PostTask(FROM_HERE
      base::Bind(&MyObject::DoSomethingOnAnotherThread, this, param)); }
        void DoSomething2() {
      SomeParamObject* param = new SomeParamObject;
      thread_->message_loop()->PostTask(FROM_HERE
      base::Bind(&MyObject::DoSomethingOnAnotherThread, this, make_scoped_refptr(param)));
        }
        // Note how this takes a raw pointer. The important part is that
        // base::Bind() was passed a scoped_refptr; using a scoped_refptr
        // here would result in an extra AddRef()/Release() pair.
        void DoSomethingOnAnotherThread(SomeParamObject* param) {
      ...
      }
      };

        如果你想傳遞一個(gè)對(duì)象但是不想有任何引用相關(guān)的東西,可以用base::Unretained包裝參數(shù),再次提醒,這樣意味著外部要保證這個(gè)對(duì)象的生命期,所以請(qǐng)小心使用。
        
        如果你的對(duì)象有一個(gè)特殊的析構(gòu)函數(shù)需要運(yùn)行在指定線程,那么你可以使用下面的特性。這樣是必須的,因?yàn)闀r(shí)間競爭的關(guān)系,可能導(dǎo)致,發(fā)送任務(wù)的代碼在異常做棧展開之前,任務(wù)會(huì)完整執(zhí)行(這可能導(dǎo)致異常無法得到及時(shí)處理就因?yàn)橐呀?jīng)發(fā)送出去的任務(wù)還在執(zhí)行就崩潰了,我是這樣理解的不知道對(duì)不對(duì))。(This is needed since timing races could lead to a task completing execution before the code that posted it has unwound the stack.)
      class MyObject : public base::RefCountedThreadSafe<MyObject, BrowserThread::DeleteOnIOThread> {

      Callback cancellation

      取消任務(wù)有兩個(gè)主要的原因(在回調(diào)的形式中):
      • 你會(huì)像稍后做些什么事情,但是現(xiàn)在回調(diào)再運(yùn)行,你的對(duì)象可能已經(jīng)刪除了。
      • 當(dāng)輸入變更話(例如用戶輸入),舊的任務(wù)變得不再必須,為了表現(xiàn)好些,你需要取消掉它們。

      請(qǐng)看下面的幾個(gè)不同的取消任務(wù)的方法

       

      Important notes about cancellation

        使用owned parameters(其實(shí)就是非引用計(jì)數(shù)來管理對(duì)象生存期的參數(shù)).的時(shí)候取消任務(wù)是很危險(xiǎn)的,下面是個(gè)例子(例子中使用base::WeakPtr來做取消,但是問題是所有方法中都有的)

      class MyClass {
       public:
        // Owns |p|.
        void DoSomething(AnotherClass* p) {
          ...
        }
        WeakPtr<MyClass> AsWeakPtr() {
          return weak_factory_.GetWeakPtr();
        }
       private:
        base::WeakPtrFactory<MyObject> weak_factory_;
      };
      
      ...
      Closure cancelable_closure = Bind(object->AsWeakPtr(), p);
      Callback<void(AnotherClass*)> cancelable_callback = Bind(object->AsWeakPtr());
      ...
      
      void FunctionRunLater(const Closure& cancelable_closure,
                            const Callback<void(AnotherClass*)>& cancelable_callback) {
        ...
        // Leak memory!
        cancelable_closure.Run();
        cancelable_callback.Run(p);
      }
      在 FunctionRunLater中, 調(diào)用 Run()的時(shí)候如果對(duì)象已經(jīng)西溝會(huì)導(dǎo)致內(nèi)存泄露使用 scoped_ptr 可以解決這個(gè)問題.
      class MyClass {
      public: void DoSomething(scoped_ptr<AnotherClass> p) { ... } ... };


      base::WeakPtr and Cancellation[NOT THREAD SAFE]

        你可以使用base::WeakPtr和base::WeakPtrFactory (inbase/memory/weak_ptr.h)來去報(bào)任何調(diào)用都發(fā)生在對(duì)象的生存期內(nèi),而不使用引用計(jì)數(shù)。base::Bind的機(jī)制會(huì)在base::WeakPtr無效的時(shí)候禁止任務(wù)的執(zhí)行。 base::WeakPtrFactory對(duì)象可以用來創(chuàng)建base::WeakPtr實(shí)例,這些實(shí)例知道base::WeakPtrFactory對(duì)象,當(dāng)factory被刪除的時(shí)候所有它創(chuàng)建WeakPtr會(huì)在內(nèi)部設(shè)置為失效,這樣就使得所有綁定的相關(guān)任務(wù)都不會(huì)派發(fā)執(zhí)行。把factory對(duì)象設(shè)置成要派發(fā)任務(wù)的對(duì)象的成員,就會(huì)自動(dòng)取消了。

        注意:這只發(fā)生在把任務(wù)發(fā)送到本線程的情況。現(xiàn)在有另外一種解決方案可以解決發(fā)送任務(wù)到其他線程的情況,參閱下一節(jié)CancelableTaskTracker。

      class MyObject {
      public:
      MyObject() : ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) {
      }

      void DoSomething() {
      const int kDelayMS = 100;
      MessageLoop::current()->PostDelayedTask(FROM_HERE,
      base::Bind(&MyObject::DoSomethingLater, weak_factory_.GetWeakPtr()),
      kDelayMS);
      }

      void DoSomethingLater() {
      ...
      }

      private:
      base::WeakPtrFactory<MyObject> weak_factory_;
      };


      CancelableTaskTracker

        雖然base::WeakPtr對(duì)于取消任務(wù)很有用,但是它并不是線程安全的,所以不能用于在其它線程運(yùn)行的任務(wù)。有時(shí)侯是些特殊的要求,例如,我們需要在用戶輸入發(fā)生改變的時(shí)候取消掉之前的數(shù)據(jù)庫查詢?nèi)蝿?wù)。這種情況下CancelableTaskTracker更合適。
        
        你可以用CancelableTaskTracker取消單個(gè)任務(wù)通過任務(wù)ID,這個(gè)也是為啥即使在同一線程也要用它代替base::WeakPtr的原因。
        CancelableTaskTracker與base::TaskRunner類似有兩個(gè)方法做相同post task的事情,只是多了些支持取消任務(wù)的支持。
      class UserInputHandler : public base::RefCountedThreadSafe<UserInputHandler> {
        // Runs on UI thread.
        void OnUserInput(Input input) {
          CancelPreviousTask();
          DBResult* result = new DBResult();
          task_id_ = tracker_->PostTaskAndReply(
              BrowserThread::GetMessageLoopProxyForThread(BrowserThread::DB),
              FROM_HERE,
              base::Bind(&LookupHistoryOnDBThread, this, input, result),
              base::Bind(&ShowHistoryOnUIThread, this, base::Owned(result)));
        }
      void CancelPreviousTask() { tracker_->TryCancel(task_id_); }
      ... private: CancelableTaskTracker tracker_; // Cancels all pending tasks while destruction. CancelableTaskTracker::TaskId task_id_; ... };
      因?yàn)槿蝿?wù)在其他線程運(yùn)行,無法確保一定會(huì)成功取消。當(dāng)TryCancel()調(diào)用的時(shí)候:
      • 如果任務(wù)和回復(fù)都沒有運(yùn)行,他們都將被取消
      • 如果過任務(wù)已經(jīng)運(yùn)行或者已經(jīng)完成,恢復(fù)將被取消
      • 如果回復(fù)已經(jīng)運(yùn)行或者已經(jīng)完成,取消就只是個(gè)空操作

       base::WeakPtrFactory一樣CancelableTaskTracker也是在析構(gòu)的時(shí)候取消所有相關(guān)的任務(wù)。

       

      Cancelable request(DEPRECATED)

      因?yàn)檫@個(gè)以后就廢棄了就不翻譯了。。。。

      posted @ 2013-01-14 02:53  健忘豬  閱讀(2331)  評(píng)論(0)    收藏  舉報(bào)
      主站蜘蛛池模板: 好姑娘6电影在线观看| 亚洲国产精品男人的天堂| 亚洲大尺度一区二区三区| 国产白袜脚足j棉袜在线观看| 国产精品午夜福利视频| 久久久久国产精品人妻| 亚洲国产一区二区三区亚瑟| 国产中文字幕在线一区| 国产97色在线 | 免费| 亚洲中文字幕一区精品自 | 狠狠躁天天躁中文字幕无码| 国产精品七七在线播放| 亚洲男人的天堂在线观看| 成人av午夜在线观看| 精品少妇后入一区二区三区 | 免费无码又爽又刺激网站直播| 亚洲国产一区二区av| 日本边吃奶边摸边做在线视频| 成人啪精品视频网站午夜| 四虎影视库国产精品一区| 免费无码AV一区二区波多野结衣| 亚洲人成人网站色www| 亚洲精品一区二区动漫| 女人喷水高潮时的视频网站| 人妻少妇无码精品专区| 天堂中文最新版在线官网在线| 国产一区二区不卡在线| 麻豆av一区二区三区| 亚洲人成电影在线天堂色| 欧美深度肠交惨叫| 亚洲国产精品一区在线看| 国产成人亚洲精品狼色在线| 日韩亚洲国产综合高清| 亚洲岛国成人免费av| 99热成人精品热久久66 | 一面膜上边一面膜下边视频| 亚洲av日韩av永久无码电影| 亚洲欧美人成电影在线观看| 日韩欧美猛交xxxxx无码| 激情五月日韩中文字幕| 99人体免费视频|