Libev源码分析08:Libev中的内存扩容方法
在Libev中,如果某种结构的数组需要扩容,它使用array_needsize宏进行处理,比如:
array_needsize (int, fdchanges, fdchangemax, fdchangecnt, EMPTY2);
这就表示要将整型(int)数组fdchanges,由原来的fdchangemax个元素扩容为fdchangecnt,新扩容的内存空间使用EMPTR2进行初始化。
array_needsize宏定义如下:
#define array_needsize(type,base,cur,cnt,init) \
if (expect_false ((cnt) > (cur))) \
{ \
int ecb_unused ocur_ = (cur); \
(base) = (type *)array_realloc(sizeof(type), (base), &(cur), (cnt)); \
init ((base) + (ocur_), (cur) - ocur_); \
}
base是type类型的数组,当前有cur个元素,需要调整到cnt个元素,新扩充的内存空间使用init函数初始化。
该宏的关键在于array_realloc函数,它的实现如下:
static void * array_realloc (int elem, void *base, int *cur, int cnt)
{
*cur = array_nextsize (elem, *cur, cnt);
return ev_realloc (base, elem * *cur);
}
该函数中,首先使用array_nextsize计算最终的元素个数,然后调用ev_realloc申请空间。array_nextsize计算新元素个数的方法如下:
/* find a suitable new size for the given array, */
/* hopefully by rounding to a nice-to-malloc size */
int array_nextsize (int elem, int cur, int cnt)
{
int ncur = cur + 1; do
ncur <<= 1;
while (cnt > ncur); /* if size is large, round to MALLOC_ROUND - 4 * longs to accommodate malloc overhead */
if (elem * ncur > MALLOC_ROUND - sizeof (void *) * 4)
{
ncur *= elem;
ncur = (ncur + elem + (MALLOC_ROUND - 1) + sizeof (void *) * 4) & ~(MALLOC_ROUND - 1);
ncur = ncur - sizeof (void *) * 4;
ncur /= elem;
}
return ncur;
}
该函数中,首先得到一个比cnt大的偶数ncur,如果ncur个元素占用的空间(elem* ncur + sizeof (void *) * 4)大于MALLOC_ROUND(4096)个字节,则需要调整ncur。
这里之所以要加上sizeof(void *) * 4,是因为malloc在申请空间时,除了申请的字节数之外,它还会在内存块之外加上额外的空间,记录当前内存块的信息,也就是sizeof (void *) * 4个字节。
调整ncur的方法,主要是下面的语句:
ncur *= elem;
ncur = (ncur + elem + (MALLOC_ROUND - 1) + sizeof (void *) * 4) & ~(MALLOC_ROUND - 1);
它的主要作用,就是使得ncur向上调整成MALLOC_ROUND的倍数。这里的ncur代表的是最终申请空间的总字节数。因此,还需要将其调整为元素个数:
ncur = ncur - sizeof (void *) * 4;
ncur /= elem;
得到最终的元素个数之后,接下来就是调用ev_realloc申请空间了,它的实现如下:
static void *ev_realloc_emul (void *ptr, long size) EV_THROW
{
/* some systems, notably openbsd and darwin, fail to properly
* implement realloc (x, 0) (as required by both ansi c-89 and
* the single unix specification, so work around them here.
* recently, also (at least) fedora and debian started breaking it,
* despite documenting it otherwise.
*/ if (size)
return realloc (ptr, size); free (ptr);
return 0;
} static void *(*alloc)(void *ptr, long size) = ev_realloc_emul; void *ev_realloc (void *ptr, long size)
{
ptr = alloc (ptr, size); if (!ptr && size)
{
fprintf (stderr, "(libev) cannot allocate %ld bytes, aborting.", size);
abort ();
}
return ptr;
}
PS:Libev的代码就分析到这了!
Libev源码分析08:Libev中的内存扩容方法的更多相关文章
- Java|ArrayList源码分析|add()增加方法和grow()扩容方法
本文结构: 1.介绍特点 2.基本方法 3.重点源码分析 1.介绍特点 ArrayList: 是List的一个具体实现子类,是List接口的一个数组实现 (里面必定维护了一个数组). 默认初始容量10 ...
- Libev源码分析08:Libev中的信号监视器
Libev中的信号监视器,用于监控信号的发生,因信号是异步的,所以Libev的处理方式是尽量的将异步信号同步化.异步信号的同步化方法主要有:signalfd.eventfd.pipe.sigwaiti ...
- [转]Libev源码分析 -- 整体设计
Libev源码分析 -- 整体设计 libev是Marc Lehmann用C写的高性能事件循环库.通过libev,可以灵活地把各种事件组织管理起来,如:时钟.io.信号等.libev在业界内也是广受好 ...
- angular源码分析:angular中脏活累活的承担者之$interpolate
一.首先抛出两个问题 问题一:在angular中我们绑定数据最基本的方式是用两个大括号将$scope的变量包裹起来,那么如果想将大括号换成其他什么符号,比如换成[{与}],可不可以呢,如果可以在哪里配 ...
- angular源码分析:angular中入境检察官$sce
一.ng-bing-html指令问题 需求:我需要将一个变量$scope.x = '<a href="http://www.cnblogs.com/web2-developer/&qu ...
- angular源码分析:angular中各种常用函数,比较省代码的各种小技巧
angular的工具函数 在angular的API文档中,在最前面就是讲的就是angular的工具函数,下面列出来 angular.bind //用户将函数和对象绑定在一起,返回一个新的函数 angu ...
- angular源码分析:angular中的依赖注入式如何实现的
一.准备 angular的源码一份,我这里使用的是v1.4.7.源码的获取,请参考我另一篇博文:angular源码分析:angular源代码的获取与编译环境安装 二.什么是依赖注入 据我所知,依赖注入 ...
- spark 源码分析之十六 -- Spark内存存储剖析
上篇spark 源码分析之十五 -- Spark内存管理剖析 讲解了Spark的内存管理机制,主要是MemoryManager的内容.跟Spark的内存管理机制最密切相关的就是内存存储,本篇文章主要介 ...
- Libev源码分析09:select突破处理描述符个数的限制
众所周知,Linux下的多路复用函数select采用描述符集表示处理的描述符.描述符集的大小就是它所能处理的最大描述符限制.通常情况下该值为1024,等同于每个进程所能打开的描述符个数. 增大描述符集 ...
随机推荐
- Java 基本数据类型 相互转换
int -> String String s=String.valueOf(12345); String -> int int i=Integer.parseInt("123&q ...
- 插头DP智障操作合集
今天一共四道插头DP[其实都差不多],智障错误出了不下五个:D 来,让我好好数落我自己一下 直接写代码注释里吧 Eat the Trees #include<iostream> #incl ...
- jquery源码学习(二)——jquery中的变量
jquery在 21-93 行提供了变量 var // A central reference to the root jQuery(document) rootjQuery, // The defe ...
- 请自行检查是否安装VC9运行库??
phpStudy是一款PHP调试环境的程序集成包,该程序包集成最新的Apache+PHP+MySQL+phpMyAdmin+ZendOptimizer,一次性安装,无须配置即可使用,是非常方便.好用的 ...
- string型的“600.000”如何转换为int型
string型的“600.000”怎么转换为int型?为什么我用int.parse不能转换? ------解决方案--------------------int.Parse("600.000 ...
- 找不到windows.h源文件
一.找不到源文件window.h 今天在网上下了个程序,在公司用VS2015能打开,在家用VS2017却打不开,提示找不到源文件window.h,因为引用了这个头文件,但是却找不到 解决方案: 右侧解 ...
- 建立DbLink 时报ORA-01017/ORA-02063分析及解决
今天在11G的oracle数据库上创建DBlink连接10g的库时, 出现: ORA-01017: invalid username/password; logon denied ORA-02063: ...
- PHPCMS快速建站系列之getcache()的用法
/** * 读取缓存,默认为文件缓存,不加载缓存配置. * @param string $name 缓存名称 * @param $filepath 数据路径(模块名称) caches/cache_$f ...
- 阿里云发布SaaS生态战略,成就亿级营收独角兽
7月26日,在上海举办的阿里云合作伙伴峰会上,阿里云正式发布SaaS生态战略,计划用阿里云的品牌.渠道.资本.方法论.技术加持伙伴,成就亿级营收独角兽. 该生态战略计划招募10家一级SaaS合作伙伴, ...
- BZOJ2770: YY的Treap
原本看标题还以为是treap的题,但是实际上是线段树. 求两点的LCA相当于求区间priority最小值的位置. 然后就可以离线先离散化然后建树做了. 记录的minpos是线段树上叶子结点的节点编号. ...