zoukankan      html  css  js  c++  java
  • sgi stl内存池实现------源码加翻译

    class __default_alloc_template {
    	enum { unit = 8 };//分配单位  后面直接用8代替
    	enum { max_bytes = 128 };//最大分配字节数 后面直接用128代替
    	enum { list_size = 16 }; //数组大小  后面直接用16代替
    
    	static char* _S_start_free;//目前内存池的首地址
    	static char* _S_end_free;//目前内存池的尾地址
    	static size_t _S_heap_size;//内存池的总大小,包括分配和未分配的
    
    	union obj
    	{
    		union obj* next_obj;//指向下一个内存的地址
    		char _M_client_data[1];//内存的首地址
    	};
    
    	static obj*  _S_free_list[16];//链表数组
    
    	static size_t _S_round_up(size_t __bytes)//向上取整 8的倍数
    	{
    		return (((__bytes)+(size_t)8 - 1) & ~((size_t)8 - 1));
    	}
    
    	static  size_t _S_freelist_index(size_t __bytes) //根据字节数找到对应的链表数组下标(字节数向上取整8的倍数)
    	{
    		return (((__bytes)+(size_t)8 - 1) / (size_t)8 - 1);
    	}
    
    	// Returns an object of size __n, and optionally adds to size __n free list.
    	static void* _S_refill(size_t __n);
    
    	// Allocates a chunk for nobjs of size size.  nobjs may be reduced
    	// if it is inconvenient to allocate the requested number.
    	static char* _S_chunk_alloc(size_t __size, int& __nobjs);
    
    	// Chunk allocation state.
    
    	class _Lock;//保证线程安全的。构造时加锁,析构时释放
    	friend class _Lock;
    	class _Lock
    	{
    	public:
    		_Lock() { __NODE_ALLOCATOR_LOCK; }
    		~_Lock() { __NODE_ALLOCATOR_UNLOCK; }
    	};
    
    	static void* allocate(size_t __n)
    	{
    		void* __ret = 0;//返回的内存地址
    		if (__n > (size_t)128) //如果请求内存大于128b,则调用第一级配置器
    		{
    			__ret = malloc_alloc::allocate(__n);
    		}
    		else
    		{
    			// 根据请求内存大小,找到链表数组负责这个大小的索引位置的地址
    			obj** __my_free_list =
    				_S_free_list //链表数组首地址
    				+ _S_freelist_index(__n);//偏移量(n会向上取整8倍数) 
    
    			_Lock __lock_instance;//加锁
    
    			obj* __RESTRICT __result = *__my_free_list;//取得对应链表的第一块内存
    
    			if (__result == 0)//这个链表不够内存时,调用_S_refill重新从内存池分配
    			{
    				__ret = _S_refill(_S_round_up(__n));
    			}
    			else
    			{
    				*__my_free_list = __result->next_obj;//指向该链表的下一块内存
    				__ret = __result;
    			}
    		}
    		return __ret;
    	};
    
    	static void deallocate(void* __p, size_t __n)//释放内存块
    	{
    		if (__n > (size_t)128)//大于128b,调用第一级配置器回收
    		{
    			malloc_alloc::deallocate(__p, __n);
    		}
    		else {
    			obj**  __my_free_list//找到对应的链表
    				= _S_free_list + _S_freelist_index(__n);
    			obj* __q = (obj*)__p;
    
    			_Lock __lock_instance;//加锁
    
    			__q->next_obj = *__my_free_list;//回收的内存的下一块内存指向原链表的第一块内存
    
    			*__my_free_list = __q;//链表第一块内存指向被回收的内存
    		}
    	}
    
    };
    
    char* __default_alloc_template::_S_chunk_alloc(size_t __size, int& __nobjs)
    {
    	char* __result;
    	size_t __total_bytes = __size * __nobjs;//__total_bytes为从内存池上要取得内存块总大小。__nobjs默认为20,但会受条件限制而改变
    	size_t __bytes_left = _S_end_free - _S_start_free;//_S_end_free - _S_start_free得到目前内存池剩余的内存
    
    	if (__bytes_left >= __total_bytes) //如果足够20个直接取
    	{
    		__result = _S_start_free;
    		_S_start_free += __total_bytes;
    		return(__result);
    	}
    	else if (__bytes_left >= __size) //如果不够20个且大于1个,则能取多少个就取多少个
    	{
    		__nobjs = (int)(__bytes_left / __size);
    		__total_bytes = __size * __nobjs;
    		__result = _S_start_free;
    		_S_start_free += __total_bytes;
    		return(__result);
    	}
    	else //当内存池的内存小于一块内存的大小时,先将剩余内存加在数组适当的位置
    	{
    		size_t __bytes_to_get = 40 * __size + _S_round_up(_S_heap_size >> 4);//从内存里面要得到的内存大小,至少40块
    
    		if (__bytes_left > 0) //把内存池剩余的内存分配到对应的链表中,清空当前内存池,以便后续去处理不连续的内存池里的另一块内存块
    		{
    			obj** __my_free_list = _S_free_list + _S_freelist_index(__bytes_left);
    			((obj*)_S_start_free)->next_obj = *__my_free_list;
    			*__my_free_list = (obj*)_S_start_free;
    		}
    		_S_start_free = (char*)malloc(__bytes_to_get);//调用malloc从内存分配
    		if (0 == _S_start_free) //系统内存不足时
    		{
    			size_t __i;
    			obj** __my_free_list;
    			obj* __p;
    
    			for (__i = __size; __i <= (size_t)128;__i += (size_t)8)  // 利用好自己拥有的内存,即从其他空闲链表获取内存.
    			{
    				__my_free_list = _S_free_list + _S_freelist_index(__i);
    				__p = *__my_free_list;
    				if (0 != __p) {
    					*__my_free_list = __p->next_obj;
    					_S_start_free = (char*)__p;
    					_S_end_free = _S_start_free + __i;
    					return(_S_chunk_alloc(__size, __nobjs));//此时调用调用chunk_alloc,就能获取得到足够的内存
    				}
    			}
    			_S_end_free = 0;	// 从其他链表也没获取到内存
    			_S_start_free = (char*)malloc_alloc::allocate(__bytes_to_get); // 调用第一级配置器,因为有错误处理函数,也是最后的补救办法了
    		}
    		_S_heap_size += __bytes_to_get;//当从系统分配到内存时,更新到目前为止的内存总数
    		_S_end_free = _S_start_free + __bytes_to_get;
    		return(_S_chunk_alloc(__size, __nobjs));//递归调用说不定成功了呢
    	}
    }                            
    
    void* __default_alloc_template::_S_refill(size_t __n)
    {
    	int __nobjs = 20;//默认分配20块内存块
    	char* __chunk = _S_chunk_alloc(__n, __nobjs);//从内存池获取,返回第一块
    	obj** __my_free_list;
    	obj* __result;
    	obj* __currentobj;
    	obj* __next_obj;
    	int __i;
    
    	if (1 == __nobjs) return(__chunk);//如果只返回一块内存,直接返回
    	__my_free_list = _S_free_list + _S_freelist_index(__n);
    
    	/* Build free list in chunk */
    	__result = (obj*)__chunk;//不止一块内存,取出第一块内存
    	*__my_free_list = __next_obj = (obj*)(__chunk + __n);//对应链表头部指向第二块内存
    	for (__i = 1; ; __i++) {//串联起来
    		__currentobj = __next_obj;
    		__next_obj = (obj*)((char*)__next_obj + __n);
    		if (__nobjs - 1 == __i) {
    			__currentobj->next_obj = 0;//最后一块的next为空
    			break;
    		}
    		else {
    			__currentobj->next_obj = __next_obj;
    		}
    	}
    	return(__result);
    }
    

      

  • 相关阅读:
    ggplot常见语法汇总查询
    共线性图 | Alluvial Diagrams | Parallel plot | Parallel Coordinates Plot
    绿色地狱
    deepnude | 福利
    文献阅读 | A single-cell molecular map of mouse gastrulation and early organogenesis
    Seurat V3.0
    文献阅读 | Molecular Architecture of the Mouse Nervous System
    《我的团长我的团》
    RNA剪接体 Spliceosome | 冷冻电镜 | 结构生物学
    文献阅读 | Resetting histone modifications during human parental-to-zygotic transition
  • 原文地址:https://www.cnblogs.com/l2017/p/10700735.html
Copyright © 2011-2022 走看看