• <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>
            隨筆-159  評論-223  文章-30  trackbacks-0
               在《基于stl序列容器實現的通用集合類》一文中,已經講到了具體實現,近來因再次用到它又改進完善了,主要體現在以下幾點:1)增加了查找操作方法,支持按值類型和謂詞條件兩種方式。2)增加重載了按值類型和謂詞條件2種方式刪除元素的方法。3)增加了2個模板參數以支持線程安全,一個是線程模型模板類,一個是互斥鎖類,使用loki庫來實現,因此所有方法現在都是線程安全的,當需要在多線程環境使用時,注意這里是對象級別鎖而不是類級別鎖,只需定義loki中的宏LOKI_OBJECT_LEVEL_THREADING即可;當在單線程環境使用時,LOKI_CLASS_LEVEL_THREADING和LOKI_OBJECT_LEVEL_THREADING兩個宏都不要定義。代碼如下:
              1#ifndef _STL_COLLECTION_H
              2#define _STL_COLLECTION_H
              3
              4#include <memory>
              5#include <vector>
              6#include <loki/Threads.h>
              7
              8  /**
              9    @class STLCollection
             10    @brief 基于STL容器(vector,list,deque)實現的數據結構通用集合類
             11
             12    * 提供以索引作為外參的以下公共通用接口
             13    *  add    --- 向前或向后增加單個元素
             14    *  insert --- 插入單個元素
             15    *  erase  --- 刪除單個或多個元素
             16    *  set    --- 修改某個元素
             17    *  get    --- 獲取某個元素
             18    *  find   --- 查找某個元素
             19    *  front  --- 獲取第一個元素
             20    *  back   --- 獲取最后一個元素
             21*/

             22
             23template<typename T,
             24         template <classclass> class ThreadModel = LOKI_DEFAULT_THREADING,
             25         class MutexPolicy = LOKI_DEFAULT_MUTEX,
             26         template<class T,class U > class C = std::vector,
             27         template <class T> class U = std::allocator
             28         >
             29class STLCollection : public C<T,U<T> >
             30{
             31    typedef U<T> Allocator;
             32    typedef C<T,Allocator> base;
             33    typedef STLCollection<T,ThreadModel,MutexPolicy,C,U> self;
             34
             35public:
             36    STLCollection()
             37    {
             38    }

             39    explicit STLCollection(const Allocator& al)
             40        :base(al)
             41    {
             42    }

             43    explicit STLCollection(size_t n)
             44        :base(n)
             45    {
             46    }

             47    STLCollection(size_t n,const T& t)
             48        :base(n,t)
             49    {
             50    }

             51    STLCollection(size_t n,const T& t,const Allocator& al)
             52        :base(n,t,al)
             53    {
             54    }

             55    STLCollection(const STLCollection& right)
             56        :base(right)
             57    {
             58    }

             59
             60    template<class InputIterator>
             61    STLCollection(InputIterator first,InputIterator last)
             62        :base(first,last)
             63    {
             64    }

             65
             66    template<class InputIterator>
             67    STLCollection(InputIterator first,InputIterator last,const Allocator& al)
             68        :base(first,last,al)
             69    {
             70    }

             71    ~STLCollection()
             72    {
             73        typename ThreadModel<self,MutexPolicy>::Lock guard(lock_);
             74    }

             75
             76public:
             77    using base::erase;
             78    using base::insert;
             79    using base::front;
             80    using base::back;
             81
             82    void add(const T& t,bool append = true)
             83    {
             84        typename ThreadModel<self,MutexPolicy>::Lock guard(lock_);
             85        if (append)
             86            base::insert(base::end(),t);
             87        else
             88            base::insert(base::begin(),t);
             89    }

             90    void insert(size_t index,const T& t)
             91    {
             92        typename ThreadModel<self,MutexPolicy>::Lock guard(lock_);
             93        insert_impl(index,t,typename std::iterator_traits<typename base::iterator>::iterator_category());
             94    }

             95
             96    void erase(size_t index)
             97    {
             98        typename ThreadModel<self,MutexPolicy>::Lock guard(lock_);
             99        erase_impl(index,typename std::iterator_traits<typename base::iterator>::iterator_category());
            100    }

            101    void erase(size_t beg,size_t end)
            102    {
            103        typename ThreadModel<self,MutexPolicy>::Lock guard(lock_);
            104        erase_impl(beg,end,typename std::iterator_traits<typename base::iterator>::iterator_category());
            105    }

            106    void erase(const T& val)
            107    {
            108        typename ThreadModel<self,MutexPolicy>::Lock guard(lock_);
            109        typename base::iterator it = std::find(base::begin(),base::end(),val);
            110        if (it != base::end()) base::erase(it);
            111    }

            112    template<class Predicate>
            113    void erase(const Predicate& Pred)
            114    {
            115        typename ThreadModel<self,MutexPolicy>::Lock guard(lock_);
            116        typename base::iterator it = std::find_if(base::begin(),base::end(),Pred);
            117        if (it != base::end()) base::erase(it);
            118    }

            119
            120    void set(size_t index,const T& t)
            121    {
            122        typename ThreadModel<self,MutexPolicy>::Lock guard(lock_);
            123        T* p = get(index);
            124        if (p) *= t;
            125    }

            126
            127    T* get(size_t index) 
            128    {
            129        typename ThreadModel<self,MutexPolicy>::Lock guard(lock_);
            130        return get_impl(index,typename std::iterator_traits<typename base::iterator>::iterator_category());
            131    }

            132    const T* get(size_t index) const
            133    {
            134        typename ThreadModel<self,MutexPolicy>::Lock guard(lock_);
            135        return get_impl(index,typename std::iterator_traits<typename base::iterator>::iterator_category());
            136    }

            137
            138    T* find(const T& val,size_t* index)
            139    {
            140        typename ThreadModel<self,MutexPolicy>::Lock guard(lock_);
            141
            142        typename base::iterator it = std::find(base::begin(),base::end(),val);
            143        if (it == base::end()) return NULL;
            144        if (index) *index = std::distance(base::begin(),it);
            145        return &it;
            146    }

            147    const T* find(const T& val,size_t* index) const
            148    {
            149        typename ThreadModel<self,MutexPolicy>::Lock guard(lock_);
            150
            151        typename base::const_iterator it = std::find(base::begin(),base::end(),val);
            152        if (it == base::end()) return NULL;
            153        if (index) *index = std::distance(base::begin(),it);
            154        return &it;
            155    }

            156    template<class Predicate>
            157    T* find(const Predicate& Pred,size_t* index)
            158    {
            159        typename ThreadModel<self,MutexPolicy>::Lock guard(lock_);
            160
            161        typename base::iterator it = std::find_if(base::begin(),base::end(),Pred);
            162        if (it == base::end()) return NULL;
            163        if (index) *index = std::distance(base::begin(),it);
            164        return &it;
            165    }

            166    template<class Predicate>
            167    const T* find(const Predicate& Pred,size_t* index) const
            168    {
            169        typename ThreadModel<self,MutexPolicy>::Lock guard(lock_);
            170
            171        typename base::const_iterator it = std::find_if(base::begin(),base::end(),Pred);
            172        if (it == base::end()) return NULL;
            173        if (index) *index = std::distance(base::begin(),it);
            174        return &it;
            175    }

            176
            177    T* front()
            178    {
            179        typename ThreadModel<self,MutexPolicy>::Lock guard(lock_);
            180
            181        if (base::empty()) return NULL;
            182        return &base::front();
            183    }

            184    const T* front() const
            185    {
            186        typename ThreadModel<self,MutexPolicy>::Lock guard(lock_);
            187
            188        if (base::empty()) return NULL;
            189        return &base::front();
            190    }

            191
            192    T* back()
            193    {
            194        typename ThreadModel<self,MutexPolicy>::Lock guard(lock_);
            195
            196        if (base::empty()) return NULL;
            197        return &base::back();
            198    }

            199    const T* back() const
            200    {
            201        typename ThreadModel<self,MutexPolicy>::Lock guard(lock_);
            202
            203        if (base::empty()) return NULL;
            204        return &base::back();
            205    }

            206
            207    bool is_empty() const
            208    {
            209        typename ThreadModel<self,MutexPolicy>::Lock guard(lock_);
            210        return base::empty();
            211    }

            212
            213private:
            214    void insert_impl(size_t index,const T& t,std::random_access_iterator_tag tag)
            215    {
            216        if (index < base::size())
            217        {
            218            base::insert(base::begin()+index,t);
            219        }

            220    }

            221    void insert_impl(size_t index,const T& t,std::input_iterator_tag tag)
            222    {
            223        if (index < base::size())
            224        {
            225            typename base::iterator it = base::begin();
            226            while(index--++it;
            227            base::insert(it,t);
            228        }

            229    }

            230    void erase_impl(size_t index,std::random_access_iterator_tag tag)
            231    {
            232        if (index < base::size())
            233        {
            234            base::erase(base::begin()+index);
            235        }

            236    }

            237    void erase_impl(size_t index,std::input_iterator_tag tag)
            238    {
            239        if (index < base::size())
            240        {
            241            typename base::iterator it = base::begin();
            242            while(index--++it;
            243            base::erase(it);
            244        }

            245    }

            246    void erase_impl(size_t beg,size_t end,std::random_access_iterator_tag tag)
            247    {
            248        end = std::min(end,base::size());
            249        if (beg < end)
            250        {
            251            base::erase(base::begin()+beg,base::begin()+end);
            252        }

            253    }

            254    void erase_impl(size_t beg,size_t end,std::input_iterator_tag tag)
            255    {
            256        end = std::min(end,base::size());
            257        if (beg < end)
            258        {
            259            typename base::iterator it = base::begin();
            260            while(beg++ < end) it = base::erase(it);
            261        }

            262    }

            263    T* get_impl(size_t index,std::random_access_iterator_tag tag)
            264    {
            265        if (index>=base::size())
            266            return NULL;
            267        return &(*(base::begin()+index));
            268    }

            269    const T* get_impl(size_t index,std::random_access_iterator_tag tag) const
            270    {
            271        if (index>=base::size())
            272            return NULL;
            273        return &(*(base::begin()+index));
            274    }

            275    T* get_impl(size_t index,std::input_iterator_tag tag)
            276    {
            277        if (index>=base::size())
            278            return NULL;
            279        typename base::iterator it = base::begin();
            280        while (index--++it;
            281        return &(*it);
            282    }

            283    const T* get_impl(size_t index,std::input_iterator_tag tag) const
            284    {
            285        if (index>=base::size())
            286            return NULL;
            287        typename base::const_iterator it = base::begin();
            288        while(index--++it;
            289        return &(*it);
            290    }

            291private:
            292    ThreadModel<STLCollection,MutexPolicy> lock_;
            293}
            ;
            294
            295#endif
               
               現在來看一下它的應用,一個網絡通訊項目,由UI客戶端(gsoap & c++開發)和服務端(java開發)構成,服務端已實現了一些web service的同步方法,客戶端需要調用它實現相關功能,為了不阻塞界面,因此需要轉化成異步方式調用,調用的結果使用PostMessage API 發自定義消息給窗口,因此發送消息方new 了一個結果的拷貝給窗口,窗口收到后再delete這個結果,但有個問題是post消息可能會丟失導致結果得不到釋放,產生內存泄露。因此設計一個智能指針容器而且是線程安全的,在發消息時將結果拷貝加到容器中,在接收方處理結果后再從容器中刪除它,這樣就可保證無內存泄露問題了。關于智能指針容器,boost中有ptr_vector,ptr_list,ptr_set等現成的,但是它們不是按照指針本身而是指針指向的對象來對待的,也就是說你要刪除其中的指針,是按照指針指向的對象來比較查找的,原因是其內部迭代器的訪問作了特殊處理,因此這點不符合上面應用的需求,當然可以在指針指向的對象中做點手腳,但是這方法有點勉強,應用要的只是刪除指針,而不必關心它指向的對象。為了達到目的又能最大程度地復用代碼,因此改進了STLCollection,簡單地實現了智能指針容器,代碼如下:
             1#ifndef _PTR_CONTAINER_H
             2#define _PTR_CONTAINER_H
             3
             4#include "stl_collection.h"
             5#include <boost/smart_ptr.hpp>
             6
             7class raw_ptr_compare
             8{
             9public:
            10    raw_ptr_compare(void* ptr):m_ptr(ptr)
            11    {
            12    }

            13    bool operator()(const boost::shared_ptr<void>& sp) const
            14    {
            15        return sp.get()==m_ptr;
            16    }

            17private:
            18    void* m_ptr;
            19}
            ;
            20
            21typedef STLCollection<boost::shared_ptr<void> > ptr_container;
            22typedef boost::weak_ptr<ptr_container> wp_ptr_container;
            23
            24#ifdef _LOKI_SINGLETON
            25#include <loki/Singleton.h>
            26
            27template<class T>
            28struct Loki::CreateUsingNew<boost::weak_ptr<T> >
            29{
            30    static boost::weak_ptr<T>* Create()
            31    {
            32        static boost::shared_ptr<T> sp(new T);
            33        static boost::weak_ptr<T> wp = sp;
            34        return &wp;
            35    }

            36
            37    static void Destroy(boost::weak_ptr<T>* p)
            38    {
            39    }

            40}
            ;
            41typedef ::Loki::SingletonHolder<wp_ptr_container> SingletonSmartPointerContainer;
            42#endif
            43
            44#endif
             
               應用的示例代碼如下:   
             1//在工作線程中,執行調用同步webservice方法login
             2void login_task::Run(const volatile BOOL& bExit)
             3{
             4    assert(m_client);
             5    login_output out;
             6    if (m_client->login(*this,out))
             7    {
             8        boost::shared_ptr<void> sp(new login_output(out));
             9        boost::shared_ptr<ptr_container> sp_ptr = SingletonSmartPointerContainer::Instance().lock();
            10        if (sp_ptr) 
            11        {
            12            sp_ptr->add(sp);
            13            ::PostMessage(m_hWnd,WM_LOGIN,0,(LPARAM)sp.get());
            14        }

            15    }

            16    else
            17    {
            18        ::PostMessage(m_hWnd,WM_LOGIN,1,0);
            19    }

            20}

            21//在UI線程中,異步回調WM_LOGIN消息處理
            22LRESULT Cvpn_ca_clientDlg::OnLoginCallback(WPARAM wParam,LPARAM lParam)
            23{
            24    if (0==wParam)
            25    {
            26        login_output* p_out = (login_output*)lParam;
            27        boost::shared_ptr<ptr_container> sp = SingletonSmartPointerContainer::Instance().lock();
            28        if (sp) 
            29        {
            30            sp->erase(raw_ptr_compare(p_out));
            31        }

            32    }

            33    else if (1==wParam)
            34    {
            35
            36    }

            37    return S_OK;
            38}
            posted on 2011-10-21 18:43 春秋十二月 閱讀(3173) 評論(1)  編輯 收藏 引用 所屬分類: Opensrc

            評論:
            # re: 基于stl序列容器實現的通用集合類 (線程安全版)[未登錄] 2011-10-21 23:26 | 菜鳥
            我比較菜啊,請教個問題:

            這么做后,如果接收方仍然丟失了Post過來的消息,就不會有內存泄露了?  回復  更多評論
              
            欧美日韩精品久久久久| 久久天天躁狠狠躁夜夜躁2O2O | 久久综合久久综合亚洲| av无码久久久久久不卡网站| 伊人久久精品无码av一区| 亚洲性久久久影院| 久久精品成人影院| 国产免费福利体检区久久| 91精品国产91久久久久福利| 亚洲乱码精品久久久久..| 99久久这里只精品国产免费| 99久久99久久精品国产| 久久亚洲高清观看| 久久久国产精品福利免费| 狠狠色丁香久久综合婷婷| 国产一区二区三区久久| 久久精品国产精品青草app| 国产成人无码久久久精品一| 成人综合伊人五月婷久久| 狠狠色婷婷久久一区二区三区| 久久Av无码精品人妻系列| 国产精品岛国久久久久| 曰曰摸天天摸人人看久久久| 国内精品久久久久久久coent| 久久人人爽人爽人人爽av| 久久人人爽人人澡人人高潮AV| 一本一道久久a久久精品综合| 久久午夜无码鲁丝片秋霞| 性做久久久久久久| 久久综合久久综合久久| 久久国产免费| 久久中文字幕人妻熟av女| 欧美噜噜久久久XXX| 中文精品久久久久国产网址| 久久久久久极精品久久久| 久久精品国产日本波多野结衣 | 国内精品久久久久久99| 精品久久久久久无码免费| 狠狠色丁香久久婷婷综合蜜芽五月| 久久综合狠狠综合久久| 93精91精品国产综合久久香蕉|