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相关推荐

  1. 【数据库】sqlite3常用命令及SQL语句

    [数据库]sqlite3数据库备份.导出方法汇总 一.准备工作 0.安装SQLite3 1)ubuntu命令安装(不是最新版本) sudo apt install sqlite3 2)源码安装(可以安 ...

  2. Linux Malloc分析-从用户空间到内核空间【转】

    转自:http://blog.csdn.net/ordeder/article/details/41654509 版权声明:本文为博主(http://blog.csdn.net/ordeder)原创文 ...

  3. C程序员必须知道的内存知识【英】

    C程序员必须知道的内存知识[英] 时间 2015-03-08 14:16:11 极客头条原文  http://marek.vavrusa.com/c/memory/2015/02/20/memory/ ...

  4. 【BBED】BBED模拟并修复ORA-08102错误

    [BBED]BBED模拟并修复ORA-08102错误 1.1  BLOG文档结构图 1.2  前言部分 1.2.1  导读和注意事项 各位技术爱好者,看完本文后,你可以掌握如下的技能,也可以学到一些其 ...

  5. oracle lms进程 内存,【案例】Oracle ges resource消耗内存高报错ORA-04031 MOS解决办法...

    天萃荷净 Oracle研究中心案例分析:运维DBA反映Oracle数据库10.2.0.4.12每间隔一段时间就必须重启,运行一断时间报ORA-04031错误oracle ges res cache l ...

  6. 【CentOS】利用Kubeadm部署Kubernetes (K8s)

    [CentOS]利用Kubeadm部署Kubernetes (K8s)[阅读时间:约10分钟] 一.概述 二.系统环境&项目介绍 1.系统环境 2.项目的任务要求 三.具体实验流程 1 系统准 ...

  7. 【Spring】框架简介

    [Spring]框架简介 Spring是什么 Spring是分层的Java SE/EE应用full-stack轻量级开源框架,以IOC(Inverse Of Control:反转控制)和AOP(Asp ...

  8. 【C#】类——里式转换

    类是由面对对象程序设计中产生的,在面向结构的程序设计例如C语言中是没有类这个概念的!C语言中有传值调用和传址调用的两种方式!在c语言中,主方法调用方法,通过传递参数等完成一些操作,其中比较常用的的数据 ...

  9. 【C#】Out与ref是干什么的?

    关于return: 1.最后没有写 return 语句的话,表示程序正常退出 2.不需要返回值时,存在return的作用 例子 void main() {return; //return退出该程序的作 ...

最新文章

  1. 大数据笔记2019.5.9 Java中方法的使用
  2. 用Kotlin打造一个Router
  3. ExtJs 3.1 XmlTreeLoader Example Error
  4. 普211标准三维EE零基础转CS申
  5. c++ 回调函数与std::function使用实例
  6. Mybatis各种模糊查询及#和$区别
  7. Spring之项目中pofile的应用
  8. (15)FPGA面试题存储器资源区别
  9. 不能错过的好书—《观止》NT当年那点事儿
  10. python画散点图-从零开始学Python【15】--matplotlib(散点图)
  11. react-navigation之动态修改title的内容
  12. 【机器学习】线性回归(最小二乘法实现)
  13. python办公自动化——提取pdf中的文字和表格
  14. 地铁里的广播语和广告语
  15. 罗技鼠标M330拆解
  16. 盯市盈亏、浮动盈亏、总盈亏的计算方法
  17. vimdiff解决git merge冲突
  18. Linux学习之错误与解决记录(持续更新)
  19. 简单python网络爬虫批量下载视频
  20. 1367: [蓝桥杯2018初赛]付账问题

热门文章

  1. mp3音频剪辑软件怎么使用?
  2. flash加载html代码
  3. ue怎么转换html格式,ue格式化html代码
  4. HTML+CSS入门
  5. csv和excel php 解析_php读取csv文件(excel可另存为csv格式文件)
  6. hvr的license过期时的提示
  7. matlab是什么意思,matlab是什么意思_matlab的翻译_音标_读音_用法_例句_爱词霸在线词典...
  8. 微信小程序开发 - 五星好评
  9. 繁易FStudio 下载项目显示打包失败。Pack failed. Return value is -101 解决方法
  10. Python数据分析实战-将一维列表和二维列表内容保存到本地excel文件(附源码和实现效果)