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

            szwolf

            專注于C++技術,再用1年的時間努力學C++!
            隨筆 - 2, 文章 - 0, 評論 - 2, 引用 - 0
            數據加載中……

            STL學習之一:構建自己的內存配置器

            ???使用STL已經有一段時間了,對里面的運作方式一直不了解。這幾天突發其想,找了一些關于STL源碼的書看了一下,覺得其內部實現非常精妙。作為進一步學習,我打算把STL中的主要組件自己動手實現一下。
            ???首先從空間配置器開始,從內部逐漸了解STL中各種容器的實現細節。
            ???根據STL的規范,allocator必須有以下接口:
            ???

            typedef????size_t????????size_type;
            typedef????T????????value_type;
            typedef????T
            * ????????pointer;
            typedef????ptrdiff_t????difference_type;
            typedef????
            const ?T * ????const_pointer;
            typedef????T
            & ????????reference;
            typedef????
            const ?T & ????const_reference;

            rebind
            allocator(
            const ?allocator < U >& ?)
            ~ allocator()?
            pointer?address(reference?x)
            const_pointer?address(const_pointer?x)
            T
            * ?allocate(size_type?n,? void * ?p? = ? 0 )
            void ?deallocate(pointer?p,?size_type?n)
            size_type?max_size()
            void ?construct(pointer?p,?const_reference?val)
            void ?destroy(pointer?p)

            ?SGI STL并沒有按C++ STD的說沒直接做一個Allocator出來,而是先做出兩個Allocator template及以內存池的形式來構?//造Allocator比STD::allocator效率更高且減少了內存碎片。下面是sgi_allocator.h的代碼:

            #ifndef?SGI_ALLOCATOR
            #define ?SGI_ALLOCATOR
            #include?
            < iostream >
            #include?
            < cstddef > ???????? // for?size_t
            using ? namespace ?std;

            namespace ?SGI
            {
            ????template < int ?inst >
            ????
            class ?malloc_alloc_template???? // 一級空間配置器
            ???? {
            ????
            public :
            ????????
            static ? void * ?allocate(size_t?n)
            ????????
            {
            ????????????
            void * ?result? = ?malloc(n);
            ????????????
            if ?(result? == ?NULL)
            ????????????
            {
            ????????????????result?
            = ?oom_malloc(n);???????? // 內存不足調用oom_malloc()進行處理
            ????????????}


            ????????????
            return ?result;
            ????????}


            ????????
            static ? void ?deallocate( void * ?p,?size_t)???? // 第二個參數無所謂,只要一進來就把它干掉..
            ???????? {
            ????????????free(p);
            ????????}


            ????????
            static ? void * ?reallocate( void * ?p,?size_t /* old?size */ ,?size_t?new_size)
            ????????
            {
            ????????????
            void * ?result? = ?realloc(p,?new_size);
            ????????????
            if (result? == ?NULL)
            ????????????
            {
            ????????????????result?
            = ?oom_realloc(p,?new_size);
            ????????????}


            ????????????
            return ?result;
            ????????}


            ????????
            static ? void ?( * set_malloc_handler( void ?( * f)()))()
            ????????
            {
            ????????????
            void ?( * old)()? = ?oom_malloc_handler;
            ????????????oom_malloc_handler?
            = ?f;

            ????????????
            return ?old;
            ????????}

            ????
            private :
            ????????
            static ? void * ?oom_malloc(size_t);???????? // 內存不足時調用這個函數(因為里面有處理函數)
            ???????? static ? void * ?oom_realloc( void * ,?size_t); // 同上
            ???????? static ? void ?( * oom_malloc_handler)();???? // 內存不足時的處理函數
            ????}
            ;
            ????template
            < int ?inst >
            ????
            void * ?malloc_alloc_template < inst > ::oom_malloc(size_t?size)
            ????
            {
            ????????
            void * ?result;
            ????????
            ????????
            while ( true )???????????? // 反得調用處理函數,直到申請成功.如果沒有定義處理函數則拋出異常
            ???????? {
            ????????????
            if ?(oom_malloc_handler? == ?NULL)
            ????????????
            {
            ????????????????
            throw ?bad_alloc();
            ????????????}

            ????????????(
            * oom_malloc_handler)();
            ????????????
            if ?(?(result? = ?malloc(size))? != ?NULL)
            ????????????
            {
            ????????????????
            return ?result;
            ????????????}

            ????????}

            ????}


            ????template
            < int ?inst >
            ????
            void * ?malloc_alloc_template < inst > ::oom_realloc( void * ?p,?size_t?new_size)
            ????
            {
            ????????
            void * ?result;

            ????????
            while ( true )
            ????????
            {
            ????????????
            if ?(oom_malloc_handler? == ?NULl)
            ????????????
            {
            ????????????????
            throw ?bad_alloc();
            ????????????}

            ????????????(
            * oom_alloc_handler)();
            ????????????
            if ?(?(result? = ?realloc(p,?new_size))? != ?NULL)
            ????????????
            {
            ????????????????
            return ?result;
            ????????????}

            ????????}

            ????}


            ????template
            < int ?inst >
            ????
            void ?( * malloc_alloc_template < inst > ::oom_malloc_handler)()? = ?NULL;

            ????typedef?malloc_alloc_template
            < 0 > ?malloc_alloc;???????? // 到此完成一級空間配置器的定義

            ????
            //////////////////////////////////////////////////////
            ???? // 下面是對一二級配置器的封裝,?其中Alloc即為空間配置器
            ????
            // 默認用的是二級配置器,當>128K或內存不足時會交給一級
            ????
            // 配置器處理
            ???? /////////////////////////////////////////////////// //j?
            ????template < typename?T,?typename?Alloc > ????????????
            ????
            class ?simple_alloc
            ????
            {
            ????
            public :
            ????????
            static ?T * ?allocate(size_t?n)
            ????????
            {
            ????????????
            return ?n? == ? 0 ? ? ? 0 ?:?(T * )Alloc::allocate(n? * ? sizeof (T));
            ????????}


            ????????
            static ?T * ?allocate()
            ????????
            {
            ????????????
            return ?(T * )Alloc::allocate( sizeof (T));
            ????????}


            ????????
            static ? void ?deallocate(T * ?p,?size_t?n)
            ????????
            {
            ????????????
            if ?(n? != ? 0 )
            ????????????
            {
            ????????????????Alloc::deallocate(p,?n?
            * ? sizeof (T));???????? // 這里要用兩個參數是為了與后面的二級配置器配合(這個問題郁悶了我好久,呵呵,菜啊!)
            ????????????}

            ????????}


            ????????
            static ? void ?deallocate(T * ?p)
            ????????
            {
            ????????????Alloc::deallocate(p,?
            sizeof (T));
            ????????}

            ????}
            ;

            ????
            enum {ALIGN? = ? 8 ,?MAX_BYTES? = ? 128 ,?NFREELISTS? = ? 16 } ;???? // ?其中NFREELISTS?=?MAX_BYTES?/?ALIGN
            ????
            ????template
            < bool ?threads,? int ?inst >
            ????
            class ?default_alloc_template???? // 定義二級配置器
            ???? {
            ????
            public :
            ????????
            static ? void * ?allocate(size_t?n)
            ????????
            {
            ????????????
            void * ?result;
            ????????????
            ????????????
            if ?(n? > ?(size_t)MAX_BYTES)
            ????????????
            {
            ????????????????result?
            = ?malloc_alloc::allocate(n);???????? // >128K交給一級配置器處理
            ????????????}

            ????????????
            else
            ????????????
            {
            ????????????????Obj
            * ? volatile * ?my_free_list???? = ?free_list? + ?free_list_index(n);
            ????????????????
            if ?(?(result? = ? * my_free_list)? == ?NULL)
            ????????????????
            {
            ????????????????????result????
            = ????refill(round_up(n));
            ????????????????}

            ????????????????
            else
            ????????????????
            {
            ????????????????????Obj
            * ?tmp???????? = ? * my_free_list;
            ????????????????????
            * my_free_list???? = ?tmp -> free_list_link;
            ????????????????????result????????????
            = ?tmp;
            ????????????????}

            ????????????}


            ????????????
            return ?result;
            ????????}


            ????????
            static ? void ?deallocate( void * ?p,?size_t?n)
            ????????
            {
            ????????????
            if ?(n? > ?(size_t)MAX_BYTES)
            ????????????
            {
            ????????????????malloc_alloc::deallocate(p,?n);
            ????????????}

            ????????????
            else
            ????????????
            {
            ????????????????Obj
            * ? volatile * ?my_free_list? = ?free_list? + ?free_list_index(n);
            ????????????????Obj
            * ?q? = ?(Obj * )?p;
            ????????????????q
            -> free_list_link???? = ? * my_free_list;
            ????????????????
            * my_free_list???????? = ?q;
            ????????????}

            ????????}


            ????????
            static ? void * ?reallocate( void * ?p,?size_t?old_size,?size_t?new_ize);

            ????
            private :
            ????????
            static ?size_t?round_up(size_t?bytes)
            ????????
            {
            ????????????
            return ?((bytes? + ?(size_t)ALIGN? - ? 1 )? & ? ~ ((size_t)ALIGN? - ? 1 ));
            ????????}

            ????????
            ????????union?Obj????????????
            // Trick,既可以作指針,又可以作為內存地址
            ???????? {
            ????????????union?Obj
            * ?free_list_link;
            ????????????
            char ?client_data[ 1 ];
            ????????}
            ;

            ????????
            static ?Obj * ? volatile ?free_list[NFREELISTS];

            ????????
            static ?size_t?free_list_index(size_t?size)
            ????????
            {
            ????????????
            return ?((size? + ?(size_t)ALIGN? - ? 1 )? / ?(size_t)ALIGN? - 1 );
            ????????}

            ????????
            ????????
            static ? void * ?refill(size_t?n);
            ????????
            static ? char * ?chunk_alloc(size_t?size,?size_t & ?objs);
            ????????
            ????????
            static ? char * ????chunk_start;???? // 內存池起始位置
            ???????? static ? char * ????chunk_end;???????? // 內存池結束位置
            ???????? static ?size_t????heap_size;???????? // 從開始至今在堆中申請的字節總數

            ????}
            ;

            ????template
            < bool ?threads,? int ?inst >
            ????
            char * ?default_alloc_template < threads,?inst > ::chunk_start? = ?NULL;

            ????template
            < bool ?threads,? int ?inst >
            ????
            char * ?default_alloc_template < threads,?inst > ::chunk_end? = ?NULL;

            ????template
            < bool ?threads,? int ?inst >
            ????size_t?default_alloc_template
            < threads,?inst > ::heap_size? = ? 0 ;
            ????
            ????template
            < bool ?threads,? int ?inst >
            ????typename?default_alloc_template
            < threads,?inst > ::Obj * ? volatile ?default_alloc_template < threads,?inst > ::free_list[NFREELISTS]? = ? { 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } ;


            ????
            // 核心部分,從內存池中申請空間
            ????template < bool ?threads,? int ?inst >
            ????
            char * ?default_alloc_template < threads,?inst > ::chunk_alloc(size_t?size,?size_t & ?nobjs)
            ????
            {
            ????????
            char * ????result???????? = ?NULL;
            ????????size_t????total_bytes????
            = ?size? * ?nobjs;????????????????????????
            ????????size_t????bytes_left????
            = ?chunk_end? - ?chunk_start;???????????? // 內存池所剩水量

            ????????
            if ?(?bytes_left? > ?total_bytes)???????????????????????????? // 內存池中有足夠空間可以分配
            ???????? {
            ????????????result????????
            = ????chunk_start;
            ????????????chunk_start?
            += ????total_bytes;

            ????????????
            return ?result;
            ????????}

            ????????
            else ? if (bytes_left? >= ?size)???????????????????????? // 內存池中空間至少可以分配一個塊
            ???????? {
            ????????????nobjs????????????
            = ????( int )bytes_left? / ?size;
            ????????????total_bytes????????
            = ????size? * ?nobjs;
            ????????????result????????????
            = ????chunk_start;
            ????????????chunk_start????
            += ????total_bytes;

            ????????????
            return ?result;
            ????????}

            ????????
            else ???????????????????????????????????????? // 內存池已山窮水盡一個塊都無法分配出來?T_T
            ???????? {
            ????????????size_t?bytes_to_get????
            = ?total_bytes? + ?round_up(heap_size? >> ? 4 );???????? // 申請總數兩位加上擴展

            ????????????
            if ?(bytes_left? > ? 0 )
            ????????????
            {
            ????????????????Obj
            * ? volatile * ?my_free_list???????????? = ?free_list? + ?free_list_index(bytes_left);
            ????????????????((Obj
            * )chunk_start) -> free_list_link???? = ? * my_free_list;
            ????????????????
            * my_free_list???????????????????????? = ?(Obj * )chunk_start;
            ????????????}

            ????????????chunk_start????
            = ????( char * )malloc(bytes_to_get);
            ????????????
            if ?(chunk_start? == ?NULL)???????? // 內存不足這下麻煩了,看看表中有沒有空間可以回收
            ???????????? {
            ????????????????Obj
            * ? volatile * ?my_free_list;
            ????????????????Obj
            * ?p;

            ????????????????
            for (size_t?i? = ?size;?i? <= ?MAX_BYTES;?i? += ?ALIGN)
            ????????????????
            {
            ????????????????????my_free_list????
            = ????free_list? + ?free_list_index(i);
            ????????????????????p????????????????
            = ???? * my_free_list;

            ????????????????????
            if ?(p? != ?NULL)???? // 找到適合的空間,進行回收
            ???????????????????? {????????????????????????
            ????????????????????????
            * my_free_list???? = ????p -> free_list_link;
            ????????????????????????chunk_start????????
            = ????( char * )p;
            ????????????????????????chunk_end????????
            += ????i;

            ????????????????????????
            return ?chunk_alloc(size,?nobjs);

            ????????????????????}

            ????????????????}

            ????????????????
            ????????????????
            // 完全走投無路了,只好看看內存不足的處理函數能不能幫上忙
            ????????????????chunk_end???? = ????NULL;
            ????????????????chunk_start????
            = ????( char * )malloc_alloc::allocate(bytes_to_get);
            ????????????}

            ????????????chunk_end????
            += ????bytes_to_get;
            ????????????heap_size????
            += ????bytes_to_get;

            ????????????
            return ?chunk_alloc(size,?nobjs);
            ????????}

            ????}


            ????
            /*
            ?????*?返回一個大小為n的塊,?并且可能適當地為free_list增加節點
            ?????*
            ?????
            */

            ????template
            < bool ?threads,? int ?inst >
            ????
            void * ?default_alloc_template < threads,?inst > ::refill(size_t?n)
            ????
            {
            ????????size_t????????nobjs?
            = ? 20 ;???????????????? // 默認申請塊的個數
            ????????Obj * ????????curr;
            ????????Obj
            * ????????next;
            ????????

            ????????
            char * ????result? = ?chunk_alloc(n,?nobjs);
            ????????
            if ?(nobjs? == ? 1 )???????? // 只申請到一塊空間則直接返回給調用者
            ???????? {
            ????????????
            return ?result;
            ????????}

            ????????
            else ???????????? // 申請到多于一個塊,將其它nobjs?-?1個塊加到free_list中?:?)
            ???????? {
            ????????????Obj
            * ? volatile * ?my_free_list???? = ?free_list? + ?free_list_index(n);;
            ????????????
            * my_free_list? = ?next? = ?(Obj * )(result? + ?n);
            ????????????
            for ( int ?i? = ? 1 ;?;? ++ i)
            ????????????
            {????????????????
            ????????????????curr????
            = ????next;
            ????????????????next????
            = ?(Obj * )(?( char * )next? + ?n);

            ????????????????
            if ?(i? == ?nobjs? - ? 1 )
            ????????????????
            {
            ????????????????????curr
            -> free_list_link???? = ????NULL;
            ????????????????????
            break ;
            ????????????????}

            ????????????????
            else
            ????????????????
            {
            ????????????????????curr
            -> free_list_link???? = ????next;
            ????????????????}

            ????????????}

            ????????????
            return ?result;
            ????????}

            ????}


            ????template
            < bool ?threads,? int ?inst >
            ????
            static ? void * ?default_alloc_template < threads,?inst > ::reallocate( void * ?p,?size_t?old_size,?size_t?new_size)
            ????
            {
            ????????
            if ?(old_size? > ?MAX_BYTES? && ?new_size? > ?MAX_BYTES)
            ????????
            {
            ????????????
            return ?realloc(p,?new_size);
            ????????}


            ????????
            if ?(round_up(old_size)? == ?round_up(new_size))
            ????????
            {
            ????????????
            return ?p;
            ????????}


            ????????
            void * ?result? = ?malloc(new_size);
            ????????
            int ?copy_size? = ?new_size? > ?old_size? ? ?old_size?:?new_size;
            ????????memcpy(result,?p,?copy_size);

            ????????
            return ?result;
            ????}

            ????
            ????typedef?default_alloc_template
            < false ,? 0 > ?alloc;

            ????
            /*
            ?????*?對以定義好的兩個配置器模板進行封裝,以使其與STL相容
            ?????
            */

            ????template
            < typename?T >
            ????
            class ?allocator
            ????
            {
            ????
            public :
            ????????typedef????????size_t????????size_type;
            ????????typedef????????T????????????value_type;
            ????????typedef????????T
            * ????????????pointer;
            ????????typedef????????ptrdiff_t????difference_type;
            ????????typedef????????
            const ?T * ????const_pointer;
            ????????typedef????????T
            & ????????????reference;
            ????????typedef????????
            const ?T & ????const_reference;

            ????????template
            < typename?U > ?
            ????????
            struct ?rebind
            ????????
            {
            ????????????typedef?allocator
            < U > ?other;
            ????????}
            ;

            ????????allocator()?
            throw ()
            ????????
            {
            ????????}


            ????????template
            < typename?U >
            ????????allocator(
            const ?allocator < U >& ?)? throw ()
            ????????
            {
            ????????}

            ????????
            ????????
            ~ allocator()? throw ()
            ????????
            {
            ????????}


            ????????pointer?address(reference?x)?
            const
            ????????
            {
            ????????????
            return ? & ?x;
            ????????}


            ????????const_pointer?address(const_pointer?x)?
            const
            ????????
            {
            ????????????
            return ? & x;
            ????????}


            ????????T
            * ?allocate(size_type?n,? void * ?p? = ? 0 )
            ????????
            {
            ????????????
            return ?n? != ? 0 ? ? ?static_cast < T *> (alloc::allocate(n? * ? sizeof (T)))?:? 0 ;
            ????????}


            ????????
            void ?deallocate(pointer?p,?size_type?n)
            ????????
            {
            ????????????alloc::deallocate(p,?n
            * sizeof (T));
            ????????}


            ????????size_type?max_size()?
            const ? throw ()
            ????????
            {
            ????????????
            return ?(size_t) - 1 / sizeof (T);
            ????????}


            ????????
            void ?construct(pointer?p,?const_reference?val)
            ????????
            {
            ????????????
            new (p)T(val);
            ????????}


            ????????
            void ?destroy(pointer?p)
            ????????
            {
            ????????????p
            ->~ T();
            ????????}
            ????????
            ????}
            ;

            }


            #endif

            ?以下是測試文件,現在比較晚了。。沒有寫一個比較像樣的測試,以后有時候再寫寫。。。

            // ?sgi_allocator.cpp?:?定義控制臺應用程序的入口點。
            //
            /*
            ?*????模擬SGI?STL中allocator的實現,以內存池的形式,構建一個比STD::allocator
            ?*????更高效的空間配置器
            ?*????作者:?Szwolf
            ?*????2006.8.3:23.31'暑假@SZU
            ?*
            ?
            */

            #include?
            " stdafx.h "
            #include?
            " sgi_allocator.h "
            #include?
            < iostream >
            #include?
            < vector >
            #include?
            < algorithm >

            using ? namespace ?std;

            class ?test
            {
            public :
            ????friend?ostream
            & ? operator ? << ?(ostream & ?os,? const ?test & ?x)
            ????
            {
            ????????
            return ?os? << ? " test?success?:?) " ? << ?endl;
            ????}

            }
            ;

            int ?_tmain( int ?argc,?_TCHAR * ?argv[])
            {
            ????
            int ?a[]? = ? { 1 , 2 , 3 , 4 } ;
            ????test?b[
            10 ];
            ????vector
            < int ,?SGI::allocator < int > ? > ?vec(a,?a? + ? 4 );
            ????vector
            < test,?SGI::allocator < test > ? > vec2(b,?b + 10 );
            ????copy(vec.begin(),?vec.end(),?ostream_iterator
            < int > (cout,? " ? " ));
            ????cout?
            << ?endl;
            ????copy(vec2.begin(),?vec2.end(),?ostream_iterator
            < test > (cout));
            ????cout?
            << ?endl;

            ????
            return ? 0 ;
            }

            一個類似于SGI STL::allocator的空間配置器就這樣完成了:)個人感覺在建內存池的過程從其無所不用其極的空間申請方式中受益頗多~~~(呵呵,鏈表操作又復習了一遍。。)
            ?以下是在VS2005中可以正常編譯通過的源碼:
            http://www.shnenglu.com/Files/szwolf/sgi_allocator.rar

            posted on 2006-08-06 01:15 szwolf 閱讀(1305) 評論(2)  編輯 收藏 引用

            評論

            # re: STL學習之一:構建自己的內存配置器  回復  更多評論   

            老大,既然你開博,并且貼出代碼,就貼全,干嘛臨代碼結束了,漏掉一句,呵呵,不要告訴我是故意的喔!:-)

            謝謝你將stl的代碼清晰化,并且加了注釋,閱讀更方便了,謝謝!
            2008-12-30 11:23 | mislang

            # re: STL學習之一:構建自己的內存配置器  回復  更多評論   

            大哥:對不起了!剛剛仔細看了代碼,建議您還是把代碼撤下來吧,太多錯誤!
            哎。。。

            質量!

            為了不給后來人添亂,您還是撤了吧,謝謝!
            2008-12-30 17:46 | mislang
            精品久久久久久国产牛牛app| 国产农村妇女毛片精品久久| 国产高潮国产高潮久久久91| 国产一区二区三区久久| 中文无码久久精品| 欧美日韩精品久久久免费观看| 久久久黄片| 久久精品国产国产精品四凭| 精品久久久久久国产免费了| 国产成人AV综合久久| 中文字幕亚洲综合久久2| 久久免费美女视频| 91久久精品视频| 狠狠人妻久久久久久综合| 久久99精品久久久久久秒播| 久久青青国产| 国内精品久久久久影院亚洲| 99久久这里只精品国产免费| 一本一本久久a久久综合精品蜜桃 一本一道久久综合狠狠老 | 大香网伊人久久综合网2020| 亚洲成人精品久久| 久久久久久久综合综合狠狠| 亚洲国产综合久久天堂 | 四虎国产精品成人免费久久| 性做久久久久久久久久久| 久久精品一本到99热免费| 欧洲成人午夜精品无码区久久| 亚洲精品无码久久一线| 国产成人久久精品一区二区三区| 久久不射电影网| 亚洲国产精品综合久久网络| 一本色道久久综合亚洲精品| 国产99久久精品一区二区| 亚洲天堂久久精品| 国产精品美女久久福利网站| 婷婷久久香蕉五月综合加勒比| 久久综合综合久久97色| 少妇久久久久久被弄到高潮| 精品熟女少妇av免费久久| 精品久久久久久国产三级| 久久人人爽人人爽人人片av麻烦|