• <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>

            #ant

            The dreams in which I'm dying are the best I've ever had...

            從Win32 API封裝Thread類[2]

            在上一篇中介紹了創建Thread的兩種方法:從Thread類繼承或者實現Runnable接口。有時候這并不是特別方便,我們需要的是更靈活的方法,比如像boost庫中的Thread一樣可以用普通函數和函數對象
            (functor?and function object)作為構造函數參數。如果你熟悉STL,你應該熟悉bind1st和bind2nd這兩個函數配接器(function adapter),bind1st和bind2nd可以將一個二元函數(binary function)轉換成一元函數(unary function)。為了使Thread類能夠用普通函數和函數對象作為參數,我們需要一個bind將一元函數轉換成無參函數:
            bind.h
            ?1?#ifndef?BIND_H
            ?2?
            #define?BIND_H
            ?3?

            ?4?template?<class?_Result>
            ?5?struct?trivial_function?{
            ?6?
            ????typedef?_Result?result_type;
            ?7?
            };
            ?8?

            ?9?template?<class?_Operation>
            10?class?binder?:?public?trivial_function<typename?_Operation::result_type>?{
            11?public
            :
            12?????binder(const?_Operation& x,?const?typename?_Operation::argument_type&
            y)
            13?
            ????????:op(x),?value(y)?{}
            14?????typename?_Operation::result_type?operator()()?const
            ?{
            15?????????return
            ?op(value);
            16?
            ????}
            17?protected
            :
            18?
            ????_Operation?op;
            19?
            ????typename?_Operation::argument_type?value;
            20?
            };
            21?

            22?template?<class?_Operation,?class?_Tp>
            23?inline?binder<_Operation>?
            24?bind(const?_Operation&?__fn,?const?_Tp&
            ?__x)?
            25?
            {
            26?
            ????typedef?typename?_Operation::argument_type?_Arg_type;
            27?????return?binder<_Operation>
            (__fn,?_Arg_type(__x));
            28?
            }
            29?

            30?#endif/*BIND_H*/

            有了bind我們還需要修改Thread類的構造函數,顯然我們必須將構造函數聲明為成員模板(還有一種方法也可以達到同樣的目的,就是把Thread類聲明為模板,但是這樣的設計好像不太好),這樣才能夠讓Thread類的構造函數可以接受各種類型的參數,修改后的構造函數應該能夠使用如下三種類型的參數:
            1.Runnable *
            2.no argument function
            3.no argument functor
            下面是修改后的頭文件:
            runnable.h
            ?1?#ifndef?RUNNABLE_H
            ?2?
            #define?RUNNABLE_H
            ?3?

            ?4?struct?Runnable?{
            ?5?????virtual?void?run()?=?0
            ;
            ?6?????virtual?~
            Runnable()?{}
            ?7?
            };
            ?8?

            ?9?template?<class?T>
            10?class?RunnableFunctor?:?public?Runnable?{
            11?public
            :
            12?????RunnableFunctor(const?T&
            f)?:_func(f)?{}
            13?????virtual?void
            ?run()?{?_func();?}
            14?private
            :
            15?
            ????T?_func;
            16?
            };
            17?

            18?//base?template?for?no?argument?functor
            19?template?<class?T>
            20?struct?FuncImpl?{
            21?????static?Runnable*?transfer(const?T&
            t)?{
            22?????????return?new?RunnableFunctor<T>
            (t);
            23?
            ????}
            24?
            };
            25?

            26?//partial?specialization?for?T*
            27?template?<class?T>
            28?struct?FuncImpl<T*>?{
            29?????static?Runnable*?transfer(T*
            t)?{
            30?????????return
            ?t;
            31?
            ????}
            32?
            };
            33?

            34?//partial?specialization?for?no?argument?function
            35?template?<class?T>
            36?struct?FuncImpl<T?(*)()>?{
            37?????static?Runnable*?transfer(T?(*
            t)())?{
            38?????????return?new?RunnableFunctor<T?(*)()>
            (t);
            39?
            ????}
            40?
            };
            41?

            42?template?<class?T>
            43?inline?Runnable*?transfer(const?T& t)?{
            44?????return?FuncImpl<T>
            ::transfer(t);
            45?
            }
            46?

            47?#endif/*RUNNABLE_H*/

            thread.h
            ?1?#ifndef?THREAD_H
            ?2?
            #define?THREAD_H
            ?3?

            ?4?#include?<windows.h>
            ?5?#include?"bind.h"
            ?6?#include?"runnable.h"
            ?7?
            ?8?#define?CLASS_UNCOPYABLE(classname)?\
            ?9?????private
            :?\
            10?????classname(const?classname&
            );?\
            11?????classname&?operator=(const?classname&
            );
            12?

            13?class?Thread?:?public?Runnable?{
            14?
            ????CLASS_UNCOPYABLE(Thread)
            15?public
            :
            16?
            ????Thread()
            17?????????:_target(0
            )
            18?????????,_handle(0
            )?{
            19?

            20?????}
            21?????template?<class?T>

            22?????explicit?Thread(const?T& op)
            23?
            ????????:_target(transfer(op))
            24?????????,_handle(0
            )?{
            25?

            26?????}
            27?????virtual?~
            Thread();
            28?????virtual?void
            ?run()?{}
            29?????void
            ?start();
            30?????void
            ?join();
            31?private
            :
            32?????static?unsigned?__stdcall?threadProc(void*
            param);
            33?private
            :
            34?????Runnable*
            _target;
            35?
            ????HANDLE?_handle;
            36?
            };
            37?

            38?#endif/*THREAD_H*/

            thread.cpp和前一篇的幾乎一樣,唯一的不同是去掉了構造函數Thread(Runnable *),因為現在的構造函數改成了成員模板,實現也放在thread.h中了。現在的構造函數能夠接受各種類型的參數,主要歸功于模板函數transfer,實現代碼在runnable.h中,主要技巧是用類的偏特化模擬函數模板的偏特化,不明白的請看為什么不要特化函數模版

            下面是測試代碼:
            test.cpp
            ?1?#include?"thread.h"
            ?2?#include?<iostream>
            ?3?#include?<functional>
            ?4?
            ?5?using?namespace?std;
            ?6?

            ?7?//no?argument?function
            ?8?void?print()?{
            ?9?????cout?<<?"print"?<<
            ?endl;
            10?
            }
            11?

            12?//unary?function
            13?void?print1(int?n)?{
            14?????cout?<<?"print1"?<<
            ?endl;
            15?
            }
            16?

            17?//binary?function
            18?void?print2(int?m,?int?n)?{
            19?????cout?<<?"print2"?<<
            ?endl;
            20?
            }
            21?

            22?
            23?//no?argument?functor
            24?struct?PrintFunctor?{
            25?????void?operator()()?const
            ?{
            26?????????cout?<<?"PrintFunctor"?<<
            ?endl;
            27?
            ????}
            28?
            };
            29?

            30?//unary?functor
            31?struct?PrintFunctor1?:?public?unary_function<int,?void>?{
            32?????void?operator()(int?n)?const
            ?{
            33?????????cout?<<?"PrintFunctor1"?<<
            ?endl;
            34?
            ????}
            35?
            };
            36?

            37?//binary?functor
            38?struct?PrintFunctor2?:?public?binary_function<int,?int,?void>?{
            39?????void?operator()(int?m,?int?n)?const
            ?{
            40?????????cout?<<?"PrintFunctor2"?<<
            ?endl;
            41?
            ????}
            42?
            };
            43?

            44?int?main()?{
            45?

            46?????//construct?Thread?with?no?argument?function
            47?????Thread?thread1(&print);
            48?
            ????thread1.start();
            49?

            50?????//construct?Thread?with?unary?function
            51?????Thread?thread2(bind(ptr_fun(print1),?5));
            52?
            ????thread2.start();
            53?

            54?????//construct?Thread?with?binary?function
            55?????Thread?thread3(bind(bind1st(ptr_fun(print2),?1),?2));
            56?
            ????thread3.start();
            57?

            58?
            59?????//construct?Thread?with?no?argument?functor
            60?????Thread?thread4((PrintFunctor()));
            61?
            ????thread4.start();
            62?

            63?????//construct?Thread?with?unary?functor
            64?????Thread?thread5(bind(PrintFunctor1(),?5));
            65?
            ????thread5.start();
            66?

            67?????//construct?Thread?with?binary?functor
            68?????Thread?thread6(bind(bind1st(PrintFunctor2(),?1),?2));
            69?
            ????thread6.start();
            70?

            71?????thread1.join();
            72?
            ????thread2.join();
            73?
            ????thread3.join();
            74?
            ????thread4.join();
            75?
            ????thread5.join();
            76?
            ????thread6.join();
            77?

            78?????return?0;
            79?}

            當然了,上面的并不是全部,修改后的Thread類不僅能夠使用原先的從Thread類繼承或者實現Runnable接口的方法,還可以使用任何無參函數或無參函數對象。除了test.cpp里示范的,你甚至可以用bind,bind1st,bind2st,mem_fun,mem_fun_ref的組合來用某個類的成員函數作為參數,具有超強的靈活性。

            目前實現的這些都是Thread類最基本的功能,其他功能如設置線程優先級,掛起或恢復線程,異常處理等具體實現都比較簡單,這這里就不一一實現了。
            源代碼下載:點擊下載

            posted on 2007-08-31 11:58 螞蟻終結者 閱讀(3281) 評論(7)  編輯 收藏 引用 所屬分類: C++

            Feedback

            # re: 從Win32 API封裝Thread類[2] 2007-08-31 12:26 haskell

            不錯,支持
            介紹一個完美的c++多線程庫,intel的tbb。
            http://osstbb.intel.com/index.php  回復  更多評論   

            # re: 從Win32 API封裝Thread類[2] 2007-08-31 15:14 重劍

            我download了源碼,看了下,有 new 沒 delete, why?  回復  更多評論   

            # re: 從Win32 API封裝Thread類[2] 2007-08-31 15:26 螞蟻終結者

            @重劍
            oops!!!
            delete不小心忘記寫了。
            把析構函數改成這樣就行了:
            Thread::~Thread() {
            if (_handle != 0)
            CloseHandle(_handle);
            if (_target != 0)
            delete _target;
            }

            已經更新了下載鏈接,也可以重新下載。
            thanks!  回復  更多評論   

            # re: 從Win32 API封裝Thread類[2] 2007-08-31 21:03 C/C++面試題

            支持  回復  更多評論   

            # re: 從Win32 API封裝Thread類[2] 2007-09-03 12:37 shaker(太子)

            如果能使用boost::bind 代碼就漂亮多了  回復  更多評論   

            # re: 從Win32 API封裝Thread類[2] 2007-09-03 21:10 螞蟻終結者

            @shaker(太子)
            boost::bind確實優雅
            上面的bind修改一下應該也可以實現差不多的功能  回復  更多評論   

            久久天天躁狠狠躁夜夜2020一| 亚洲国产成人精品女人久久久 | 久久国产香蕉一区精品| 亚洲成人精品久久| 青青青青久久精品国产h久久精品五福影院1421| 精品久久久久久国产牛牛app| 中文字幕久久精品| 国产精品久久久久久| 久久久久亚洲精品中文字幕| 伊人久久综合精品无码AV专区| 久久久久人妻精品一区二区三区 | 久久久亚洲精品蜜桃臀| 亚洲午夜精品久久久久久app| 久久精品亚洲精品国产色婷| 久久99精品久久久久久齐齐| 天天爽天天狠久久久综合麻豆| 国产高清美女一级a毛片久久w| 亚洲精品无码久久毛片| 久久综合九色综合精品| 亚洲精品美女久久久久99小说| www性久久久com| 久久伊人精品一区二区三区| 久久国产成人午夜aⅴ影院| 三上悠亚久久精品| 亚洲国产精品狼友中文久久久 | 午夜精品久久久久久久| 久久av高潮av无码av喷吹| 久久久久99精品成人片试看| 久久亚洲AV成人无码软件| 久久久久久久综合日本| 国产99久久九九精品无码| 成人国内精品久久久久影院| 亚洲AV日韩精品久久久久| 久久无码国产专区精品| 97视频久久久| 久久久久久久91精品免费观看| 国内精品久久久久久久久| 青青国产成人久久91网| 久久91精品国产91久久小草| 97久久久精品综合88久久| 久久亚洲精品中文字幕|