【iceoryx】 Freelist
iceoryx 里的 freeList
- FreeList的init()
- publisher getChunk()
- void* MemPool::getChunk() :
- 看一下freelist的pop
- MemPool::freeChunk(const void* chunk)
在iceoryx中,publisher 获取一块chunk,填充数据,发布;供subscriber 读取。这一系列操作要用到内存管理中的freeList。
FreeList的init()
void LoFFLi::init(cxx::not_null<Index_t*> freeIndicesMemory, const uint32_t capacity) noexcept
{cxx::Expects(capacity > 0 && "A capacity of 0 is not supported!");constexpr uint32_t INTERNALLY_RESERVED_INDICES{1U};cxx::Expects(capacity < (std::numeric_limits<Index_t>::max() - INTERNALLY_RESERVED_INDICES)&& "Requested capacityexceeds limits!");cxx::Expects(m_head.is_lock_free() && "std::atomic<LoFFLi::Node> must be lock-free!");m_nextFreeIndex = freeIndicesMemory;m_size = capacity;m_invalidIndex = m_size + 1;if (m_nextFreeIndex != nullptr){for (uint32_t i = 0; i < m_size + 1; i++){// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) upper limit of index is set by m_sizem_nextFreeIndex[i] = i + 1;}}
}
init看起来相对简单,拿 [[segment.mempool]] , size = 128 , count = 10000 举例,所做的操作如下:
1、m_invalidIndex = 10001;
2、m_size = 10000;
3、m_nextFreeIndex[10000] 依此填充 1,2,3,4…10001
publisher getChunk()
追踪代码可知,最终调用MemoryManager::getChunk(const ChunkSettings& chunkSettings)
核心代码:
for (auto& memPool : m_memPoolVector){uint32_t chunkSizeOfMemPool = memPool.getChunkSize();if (chunkSizeOfMemPool >= requiredChunkSize){chunk = memPool.getChunk();memPoolPointer = &memPool;aquiredChunkSize = chunkSizeOfMemPool;break;}}
void* MemPool::getChunk() :
void* MemPool::getChunk() noexcept
{uint32_t l_index{0U};if (!m_freeIndices.pop(l_index)){std::cerr << "Mempool [m_chunkSize = " << m_chunkSize << ", numberOfChunks = " << m_numberOfChunks<< ", used_chunks = " << m_usedChunks << " ] has no more space left" << std::endl;return nullptr;}/// @todo: verify that m_usedChunk is not changed during adjustMInFree/// without changing m_minFreem_usedChunks.fetch_add(1U, std::memory_order_relaxed);adjustMinFree();return m_rawMemory + l_index * m_chunkSize;
}
关键在 m_freeIndices.pop(l_index) 这里传入的 l_index 。
看一下freelist的pop
bool LoFFLi::pop(Index_t& index) noexcept
{Node oldHead = m_head.load(std::memory_order_acquire);Node newHead = oldHead;do{// we are empty if next points to an element with index of Sizeif (oldHead.indexToNextFreeIndex >= m_size){return false;}// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) upper limit of index set by m_sizenewHead.indexToNextFreeIndex = m_nextFreeIndex[oldHead.indexToNextFreeIndex]; //<1>newHead.abaCounter += 1;} while (!m_head.compare_exchange_weak(oldHead, newHead, std::memory_order_acq_rel, std::memory_order_acquire)); //<2>/// comes from outside, is not shared and therefore no synchronization is neededindex = oldHead.indexToNextFreeIndex; //<3>/// @todo what if interrupted here an another thread guesses the index and/// calls push/// @brief murphy case: m_nextFreeIndex does not require any synchronization since it/// either is used by the same thread in push or it is given to another/// thread which performs the cleanup and during this process a synchronization/// is required// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)m_nextFreeIndex[index] = m_invalidIndex; //<4>/// we need to synchronize m_nextFreeIndex with push so that we can perform a validation/// check right before push to avoid double free'sstd::atomic_thread_fence(std::memory_order_release);return true;
}
先看一下 LoFFLi 类的成员:
class LoFFLi
{private:struct alignas(8) Node{Index_t indexToNextFreeIndex;uint32_t abaCounter;};std::atomic<Node> m_head{{0U, 1U}};
}
它有一个m_head{0,1};
因此 <1>处 newHead.indexToNextFreeIndex = m_nextFreeIndex[0];
由init()知,m_nextFreeIndex[0] = 1;
<2> 如果 m_head 当前的值 == oldHead ,则将 m_head = newHead,并返回 true;
反之 ,oldHead = m_head ,返回false。
这里主要是担心 执行 do 下面的操作时被打断,考虑以下情况:
此时 index = 0;若此时有一线程抢占CPU并将 index = 0 的chunk取走,则此时 m_head = {1,2};
oldHead = {1,2},newHead.indexToNextFreeIndex = m_nextFreeIndex[1],去get index = 1 的 chunk。
后面操作 index = 0 , m_nextFreeIndex[0] = 10001; 然后将index 返回。
MemPool::freeChunk(const void* chunk)
当需要free该chunk时,调用 m_freeIndices.push(index):
bool LoFFLi::push(const Index_t index) noexcept
{/// we synchronize with m_nextFreeIndex in pop to perform the validity checkstd::atomic_thread_fence(std::memory_order_release);/// we want to avoid double free's therefore we check if the index was acquired/// in pop and the push argument "index" is valid// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) index is limited by capacityif (index >= m_size || m_nextFreeIndex[index] != m_invalidIndex) //<1>{return false;}Node oldHead = m_head.load(std::memory_order_acquire);Node newHead = oldHead;do{// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) index is limited by capacitym_nextFreeIndex[index] = oldHead.indexToNextFreeIndex; //<2>newHead.indexToNextFreeIndex = index; //<3>newHead.abaCounter += 1;} while (!m_head.compare_exchange_weak(oldHead, newHead, std::memory_order_acq_rel, std::memory_order_acquire));return true;
}
假定index = 0
<1>处判断 传入的 m_nextFreeIndex[0] 是否 = m_invalidIndex,因为pop时已置为 m_invalidIndex;
<2> oldHead.indexToNextFreeIndex = (上面 push 时) 1 ,因此 m_nextFreeIndex[0] = 1;
<3> newHead.indexToNextFreeIndex =0 ,即 m_head ={0,3} ;
这样就把 index = 0 的chunk free了。
【iceoryx】 Freelist相关推荐
- 【数据库】sqlite3常用命令及SQL语句
[数据库]sqlite3数据库备份.导出方法汇总 一.准备工作 0.安装SQLite3 1)ubuntu命令安装(不是最新版本) sudo apt install sqlite3 2)源码安装(可以安 ...
- Linux Malloc分析-从用户空间到内核空间【转】
转自:http://blog.csdn.net/ordeder/article/details/41654509 版权声明:本文为博主(http://blog.csdn.net/ordeder)原创文 ...
- C程序员必须知道的内存知识【英】
C程序员必须知道的内存知识[英] 时间 2015-03-08 14:16:11 极客头条原文 http://marek.vavrusa.com/c/memory/2015/02/20/memory/ ...
- 【BBED】BBED模拟并修复ORA-08102错误
[BBED]BBED模拟并修复ORA-08102错误 1.1 BLOG文档结构图 1.2 前言部分 1.2.1 导读和注意事项 各位技术爱好者,看完本文后,你可以掌握如下的技能,也可以学到一些其 ...
- oracle lms进程 内存,【案例】Oracle ges resource消耗内存高报错ORA-04031 MOS解决办法...
天萃荷净 Oracle研究中心案例分析:运维DBA反映Oracle数据库10.2.0.4.12每间隔一段时间就必须重启,运行一断时间报ORA-04031错误oracle ges res cache l ...
- 【CentOS】利用Kubeadm部署Kubernetes (K8s)
[CentOS]利用Kubeadm部署Kubernetes (K8s)[阅读时间:约10分钟] 一.概述 二.系统环境&项目介绍 1.系统环境 2.项目的任务要求 三.具体实验流程 1 系统准 ...
- 【Spring】框架简介
[Spring]框架简介 Spring是什么 Spring是分层的Java SE/EE应用full-stack轻量级开源框架,以IOC(Inverse Of Control:反转控制)和AOP(Asp ...
- 【C#】类——里式转换
类是由面对对象程序设计中产生的,在面向结构的程序设计例如C语言中是没有类这个概念的!C语言中有传值调用和传址调用的两种方式!在c语言中,主方法调用方法,通过传递参数等完成一些操作,其中比较常用的的数据 ...
- 【C#】Out与ref是干什么的?
关于return: 1.最后没有写 return 语句的话,表示程序正常退出 2.不需要返回值时,存在return的作用 例子 void main() {return; //return退出该程序的作 ...
最新文章
- 大数据笔记2019.5.9 Java中方法的使用
- 用Kotlin打造一个Router
- ExtJs 3.1 XmlTreeLoader Example Error
- 普211标准三维EE零基础转CS申
- c++ 回调函数与std::function使用实例
- Mybatis各种模糊查询及#和$区别
- Spring之项目中pofile的应用
- (15)FPGA面试题存储器资源区别
- 不能错过的好书—《观止》NT当年那点事儿
- python画散点图-从零开始学Python【15】--matplotlib(散点图)
- react-navigation之动态修改title的内容
- 【机器学习】线性回归(最小二乘法实现)
- python办公自动化——提取pdf中的文字和表格
- 地铁里的广播语和广告语
- 罗技鼠标M330拆解
- 盯市盈亏、浮动盈亏、总盈亏的计算方法
- vimdiff解决git merge冲突
- Linux学习之错误与解决记录(持续更新)
- 简单python网络爬虫批量下载视频
- 1367: [蓝桥杯2018初赛]付账问题
热门文章
- mp3音频剪辑软件怎么使用?
- flash加载html代码
- ue怎么转换html格式,ue格式化html代码
- HTML+CSS入门
- csv和excel php 解析_php读取csv文件(excel可另存为csv格式文件)
- hvr的license过期时的提示
- matlab是什么意思,matlab是什么意思_matlab的翻译_音标_读音_用法_例句_爱词霸在线词典...
- 微信小程序开发 - 五星好评
- 繁易FStudio 下载项目显示打包失败。Pack failed. Return value is -101 解决方法
- Python数据分析实战-将一维列表和二维列表内容保存到本地excel文件(附源码和实现效果)