国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發(fā)設計 > 正文

高性能無鎖(Lock-free) 內存池

2019-11-08 02:49:03
字體:
來源:轉載
供稿:網友
http://blog.csdn.net/jadedrip/article/details/5787388

由于懶惰,一直脫到現在才完成,實在是罪過啊!很快會用它來改寫我的無鎖容器,嗯,如果我不懶惰的話。

稍微解釋一下關鍵問題:

先分配一塊內存,然后將內存劃分為等大的內存格。每次調用 alloc 就分配一塊內存格出去。

可分配內存是個鏈表,這個鏈表被直接貯存在未分配的內存里。換句話說,未被分配的內存格里存放了一個指針,這個指針指向下一個未被分配的空閑內存格。

另外,為了我們分配的內存可以被正確釋放,還需要一個鏈表來貯存我們分配的內存列表,這里我把這個鏈表貯存在我們分配的內存首部。也就是每塊分配的內存,前幾個字節(jié)保存了下一塊內存的指針。

我們通過 cas 爭用的一個指針指向了鏈表頭,分配內存的過程就是從鏈表頭摘取一個內存格,而釋放的過程就是在鏈表頭掛上內存格(注意,都是鏈表頭,因此只需要爭用一個指針)。

設計上希望代碼支持 64 位,考慮到64位指針本身就是64位,但是當前系統(tǒng)最高應該只使用了 48位,因此使用剩下的部分來作為 ABA 計數。如果你的程序沒有使用 256T 以上就應該沒有問題吧,嗯——大概。

 

內存池的初始大小最好是夠大,如果在中途分配,可能由于幾個線程同時進程分配內存而一下子分配好幾塊,由于串聯可分配內存的操作是比較費時的,為了節(jié)約,我把他們全掛上了,如果你希望節(jié)約內存的分配量,可以犧牲 cpu時間,放棄多分配的內存。

 

這個很快會作為一個庫的一個組件發(fā)布,這個庫暫時被命名為 lugce, 誰有更好的名字可以推薦不?呵呵

 

照例發(fā)表源碼

[cpp] view plain copy/*   * Copyright (C) 2010  Chen Wang ( China )  * Email: jadedrip@Gmail.com  *  * This library is free software; you can redistribute it and/or  * modify it under the terms of the GNU Lesser General Public  * License as published by the Free Software Foundation; either  * version 2.1 of the License, or (at your option) any later version.  *  * This library is distributed in the hope that it will be useful,  * but WITHOUT ANY WARRANTY; without even the implied warranty of  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU  * Lesser General Public License for more details.  *  * You should have received a copy of the GNU Lesser General Public  * License along with this library; if not, write to the Free Software  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA  */  #PRagma once  #include <exception>  #include "lockfree.hpp"  #if !defined(_MSC_VER) || (_MSC_VER < 1600)  #   define nullptr NULL  #endif  namespace lugce  {      namespace lockfree      {          template< typename T, int blocksize=255 >          class memory_pool          {              static const int objsize= sizeof(T) < sizeof(intptr_t) ? sizeof(intptr_t) : sizeof(T);              static const int64 aba_inc  =0x0001000000000000LL;  // ABA 計數每次需要增加的值              static const int64 aba_mark =0xFFFF000000000000LL;  // ABA Mark              static const int64 ptr_mark =0x0000FFFFFFFFFFFFLL;      // 指針 Mark          public:              memory_pool()              {                  char *block=tadem_block();                  _first_block=block;                  _free_head.data=reinterpret_cast<intptr_t>(block)+sizeof(intptr_t)+objsize;   // 指向鏈表頭              }              ~memory_pool()              {                  // 釋放內存塊                  char * next=_first_block;                  do{                      char *p=next;                      intptr_t x=*(intptr_t*)p;                      next=(char*)x;                      delete[] p;                  }while(next);              }          public:              /// 申請內存,返回一個指向新內存的指針              T* alloc()              {                  /// 嘗試從堆棧中彈出一個空閑索引                  atomic_int64 nval;                  atomic_int64 old;                  for(;;){                      old=_free_head;                      assert( (_free_head.data & ptr_mark) > 0x10000 );                      intptr_t *next=reinterpret_cast<intptr_t*>( _free_head.data & ptr_mark ); // 指向下一塊空閑單位的指針                      if( *next==0 ){ // 沒有空閑,需要創(chuàng)建新塊                          // 創(chuàng)建新塊                          create_new_block();                          continue;                      }                      nval.data=( (old.data + aba_inc)  & aba_mark);                      nval.data|=int64(*next);    // ABA 計數                      //assert( (nval.data & ptr_mark) > 0x10000 );                      if( atomic_cas( &_free_head, old.data, nval.data  ) )                           break;                  };                  return reinterpret_cast<T*>(old.data & ptr_mark);              }              void free( const T* ptr )              {                  intptr_t *p=(intptr_t*)ptr;                  atomic_int64 nval;                  atomic_int64 old;                  // 嘗試將其放回鏈表                  do{                      old=_free_head;                      *p=(intptr_t)(old.data & ptr_mark); // 把內容改為下一個空閑索引                      assert(*p > 10000);                      nval.data=((old.data + aba_inc) & aba_mark) | (intptr_t)ptr;                      assert( (nval.data & ptr_mark) > 0x10000 );                  }while( !atomic_cas(&_free_head, old.data, nval.data) );              }          private:              /// 創(chuàng)建新的內存塊              void create_new_block()              {                  char *block=tadem_block();  // 分配內存                  atomic_intptr_t *p=(atomic_intptr_t*)_first_block;                  // 嘗試掛接到內存塊鏈表                  while( !atomic_cas( p, 0, intptr_t(block) ) ){                      p=(atomic_intptr_t*)(p->data);   // 移動到鏈表下一位                  }                  p=(atomic_intptr_t*)( block+sizeof(intptr_t) ); // 讓 p 指向鏈表尾部                  // 嘗試掛接到空閑內存棧頭上                  atomic_int64 old;                  atomic_int64 nval;                  do{                      old=_free_head;                      p->data=intptr_t(old.data & ptr_mark);       // 讓鏈表尾指向當前尾                          intptr_t x=*(intptr_t*)(p->data);                      assert( x==0 || x > 10000 );                      assert(p->data>10000);                      nval.data= ( (old.data + aba_inc) & aba_mark) | reinterpret_cast<int64>(block+sizeof(intptr_t)+objsize);  // 新的下塊空閑指向本塊                      assert( (nval.data & ptr_mark) > 0x10000 );                  } while( !atomic_cas(&_free_head, old.data, nval.data ) );              }              /// 創(chuàng)建新內存塊,并將內存串聯為鏈表              char* tadem_block()              {                  char *block=new char[blocksize * objsize+sizeof(intptr_t)]; // 準備一塊內存,注意 new 可能拋出異常                  char *p=block;                  *reinterpret_cast<intptr_t*>(p)=0;    // 內存的頭是對齊的,我們用來保存下一塊內存的地址,以構建內存塊鏈表(用來內存池析構時釋放內存塊)                  p+=sizeof(intptr_t);                  *reinterpret_cast<intptr_t*>(p)=0;    // 接下來的4個字節(jié),同樣是對齊的,作為鏈表的尾部                  p+=objsize;                  // 把這塊內存做成鏈表                  for( int32 i=0; i< blocksize-2; ++i ){                      *reinterpret_cast<intptr_t*>(p)=reinterpret_cast<intptr_t>(p)+objsize;  // 內容成為指向下一塊的空閑單元的指針                      p+=objsize;                  }                  *reinterpret_cast<intptr_t*>(p)=reinterpret_cast<intptr_t>(block)+sizeof(intptr_t);     // 最后一塊指向尾節(jié)點                  return block;              }          private:              char * _first_block;              atomic_int64 _free_head;    // 下一個空閑塊的索引          };      };  };  

頂0踩
發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 益阳市| 桂平市| 浏阳市| 太原市| 永胜县| 台南县| 鞍山市| 昌黎县| 高州市| 宁夏| 景德镇市| 沧州市| 岱山县| 新宁县| 会宁县| 陇西县| 封开县| 蚌埠市| 海门市| 建瓯市| 前郭尔| 响水县| 若尔盖县| 新乡市| 若羌县| 余庆县| 马公市| 东乌珠穆沁旗| 定安县| 闸北区| 文登市| 班戈县| 华坪县| 黎城县| 聊城市| 临夏市| 余干县| 邢台县| 古蔺县| 太保市| 枣强县|