16、基于共享内存二叉树的LRU

初级代码游戏的专栏介绍与文章目录-CSDN博客

我的github:codetoys,所有代码都将会位于ctfc库中。已经放入库中我会指出在库中的位置。

这些代码大部分以Linux为目标但部分代码是纯C++的,可以在任何平台上使用。


        在共享内存的二叉树上尝试了LRU,思路很简单,通过重新定义HANDLE,所需的节点不在共享内存则从文件读取,如果满了就把访问队列里最长时间没有被访问的节点换出去。

        先说结论:对于二叉树毫无意义,想寻求LRU解决方案就不用往下看了。

目录

一、头结构

二、节点结构

三、句柄结构

四、LRU代码

五、解释


        主要的意义是作为编程技巧的练习,如何巧妙地通过对一个对象的重新定义来改变整个容器的行为。

一、头结构

        由于是基于二叉树模板来实现,所以增加的节点链表放在二叉树的USER_HEAD里面:

#define LRU_HEAD_VIRTUAL_SET_HEAD_SIZE 1024struct T_USER_HEAD_LRU{T_SHM_SIZE head_FLRU;//访问过的节点的链表T_SHM_SIZE head_MLRU;//修改过的节点的链表char vitrual_set_head[LRU_HEAD_VIRTUAL_SET_HEAD_SIZE];//虚拟SET的HEADT_USER_HEAD_LRU():head_FLRU(-1),head_MLRU(-1){}string & toString(string & str)const{char buf[2048];sprintf(buf,"head_FLRU %ld , head_MLRU %ld",head_FLRU,head_MLRU);return str=buf;}};

二、节点结构

        节点其实就是链表:

	template<typename T >struct T_DATA_LRU : public CActiveObjectBase{T_SHM_SIZE handle;T_SHM_SIZE next_FLRU; T_SHM_SIZE next_MLRU; T data;bool operator < (T_DATA_LRU const & tmp)const{return handle<tmp.handle;}string & toString(string & str)const{char buf[2048];sprintf(buf,"h=%ld next_FLRU=%ld data=",handle,next_FLRU);return str=buf+data.toString(str);}};

        handle是二叉树的句柄。

三、句柄结构

        句柄是核心:

	template<typename T,int PI_N >struct T_HANDLE_LRU{typedef T_DATA_LRU<T > T_DATA_BUFFER;//缓存结构typedef T_SHMSET_NO_MUTEX<T_DATA_BUFFER,PI_N,T_USER_HEAD_LRU > T_SET_LRU_BUFFER;//缓存容器T_SHM_SIZE handle;T_HANDLE_LRU(T_SHM_SIZE h=-1):handle(h){}T_HANDLE_LRU & operator ++ (){++handle;return *this;}T_HANDLE_LRU & operator = (T_HANDLE_LRU const & tmp){handle=tmp.handle;return *this;}bool operator == (T_HANDLE_LRU const & tmp)const{return handle==tmp.handle;}bool operator != (T_HANDLE_LRU const & tmp)const{return !((*this)==tmp);}T & operator * ()const{return * operator ->();}T * operator -> ()const{if(0==PI_N)throw "SHM PI_N=0";//thelog<<"进入T_HANDLE_LRU -> handle="<<handle<<endi;T_SET_LRU_BUFFER * pLRUBuffer=(T_SET_LRU_BUFFER *)GET_PP_LRU(PI_N);typename T_SET_LRU_BUFFER::const_iterator it;T_DATA_BUFFER tmp;tmp.handle=handle;string str;//pLRUBuffer->Report();it=pLRUBuffer->find(tmp);if(it==pLRUBuffer->end()){if(pLRUBuffer->capacity()<=pLRUBuffer->size()){STATIC_G bool exchange=false;if(exchange){thelog<<"LRU置换重入"<<endi;throw "LRU置换重入";}else exchange=true;//throw exception_my(__FILE__,__LINE__,"空间已满,需要LRU置换");//thelog<<"空间已满,需要LRU置换 "<<handle<<endi;//pLRUBuffer->Report();//找最久没有访问的并替换出去T_SHM_SIZE flru=pLRUBuffer->GetUserHead()->head_FLRU;it.handle=flru;while(it->next_FLRU>=0){flru=it.handle;it.handle=it->next_FLRU;}//现在it指向最久没有访问的节点,flru指向前一个//thelog<<"最久没有被访问的是 "<<it.handle<<" ;逻辑节点 "<<it->handle<<endi;CStdOSFile f;string file;file=pLRUBuffer->GetName();file+=".lru";if(!f.OpenRW(file.c_str())){thelog<<"打开文件失败 "<<file<<ende;throw exception_my(__FILE__,__LINE__,"打开文件失败");}f.SeekEnd();long f_length=f.Tell();long pos=LRU_HEAD_VIRTUAL_SET_HEAD_SIZE+it->handle*sizeof(T);if(pos>=f_length){//补足文件长度for(long tmpi=f_length;tmpi<pos;++tmpi)f.Write("\0",1);}//将最久没有访问的那个写出去并从共享内存删除f.SeekBegin(pos);if(!f.Write(&it->data,sizeof(T)))throw exception_my(__FILE__,__LINE__,"写文件失败");//thelog<<it->data.toString(str)<<endi;pLRUBuffer->erase(it);f.Close();it.handle=flru;it->next_FLRU=-1;//pLRUBuffer->Report();exchange=false;}//已经确保有了一个可用空间,检查是否节点已经在文件中,若在则读入{CStdOSFile f;string file;file=pLRUBuffer->GetName();file+=".lru";if(!f.OpenRW(file.c_str())){thelog<<"打开文件失败 "<<file<<ende;throw exception_my(__FILE__,__LINE__,"打开文件失败");}f.SeekEnd();long f_length=f.Tell();long pos=LRU_HEAD_VIRTUAL_SET_HEAD_SIZE+handle*sizeof(T);if(pos<f_length){//将文件中的内容读入f.SeekBegin(pos);if(!f.Read((char *)&tmp.data,sizeof(T)))throw exception_my(__FILE__,__LINE__,"读文件失败");//thelog<<tmp.data.toString(str)<<endi;}f.Close();tmp.next_FLRU=pLRUBuffer->GetUserHead()->head_FLRU;it=pLRUBuffer->insert(tmp).first;pLRUBuffer->GetUserHead()->head_FLRU=it.handle;//pLRUBuffer->Report();}}if(it!=pLRUBuffer->end()){return &it->data;}else{return NULL;}}static T_SHM_SIZE _me(T const * p){T_DATA_BUFFER tmp;T_DATA_BUFFER * plru;plru=(T_DATA_BUFFER *)((char *)p-((char *)&(tmp.data)-(char *)&tmp));return plru->handle;}static void ShowVMapPrivateData(){thelog<<"ShowVMapPrivateData未定义"<<ende;}};

四、LRU代码

        主体代码:

	template<typename T_DATA,int PI_N,typename T_USER_HEAD=CDemoData,int VER=0 >class T_SHMLRU : public T_SHMSET<T_DATA,PI_N,T_USER_HEAD,0,VER,T_HANDLE_LRU<T_TREE_NODE_STRUCT<T_DATA > ,PI_N > >{public:typename T_HANDLE_LRU<T_TREE_NODE_STRUCT<T_DATA > ,PI_N >::T_SET_LRU_BUFFER m_LRUBuffer;typedef T_SHMSET<T_DATA,PI_N,T_USER_HEAD,0,VER,T_HANDLE_LRU<T_TREE_NODE_STRUCT<T_DATA > ,PI_N > > T_SET_PARENT;//父类型typedef typename T_SET_PARENT::iterator iterator;public:using T_SET_PARENT::capacity;using T_SET_PARENT::size;using T_SET_PARENT::GetName;T_SHMLRU(char const * name, int version) :T_SET_PARENT((string(name) + "_V").c_str(), version), m_LRUBuffer(name, version){GET_PP_LRU(PI_N)=&m_LRUBuffer;}T_SHMLRU(char const * name):T_SET_PARENT((string(name)+"_V").c_str(),VER),m_LRUBuffer(name,VER){GET_PP_LRU(PI_N)=&m_LRUBuffer;}pair<iterator, bool> insert(T_DATA const & data){if(capacity()==size()){SetVirtualCapacity(capacity()+1);}return T_SET_PARENT::insert(data);}public://IShmActiveObjectvirtual bool CreateShm(){if(sizeof(typename T_SET_PARENT::TREE_HEAD)>LRU_HEAD_VIRTUAL_SET_HEAD_SIZE){thelog<<"LRU_HEAD_VIRTUAL_SET_HEAD_SIZE "<<LRU_HEAD_VIRTUAL_SET_HEAD_SIZE<<" 不足,至少需要 "<<sizeof(typename T_SET_PARENT::TREE_HEAD)<<ende;return false;}bool ret=m_LRUBuffer.CreateShm() && m_LRUBuffer.Attach(false) && T_SET_PARENT::set_CreateShm_virtual(m_LRUBuffer.GetUserHead()->vitrual_set_head);if(!ret)return ret;//保存数据头CStdOSFile f;string file;file=m_LRUBuffer.GetName();file+=".lru";if(!f.OpenW(file.c_str())){thelog<<"打开文件失败 "<<file<<ende;return false;}if(LRU_HEAD_VIRTUAL_SET_HEAD_SIZE!=f.Write((char *)T_SET_PARENT::GetTreeHead(),LRU_HEAD_VIRTUAL_SET_HEAD_SIZE)){thelog<<"写文件头失败 "<<file<<ende;return false;}f.Close();m_LRUBuffer.Detach();return true;}virtual bool _Attach(bool isReadOnly){return m_LRUBuffer.Attach(isReadOnly) && T_SET_PARENT::set_AttachToShm_virtual(m_LRUBuffer.GetUserHead()->vitrual_set_head);}virtual bool Detach(){return m_LRUBuffer.Detach();}virtual bool LoadFromDir(char const * dir_name){thelog<<GetName()<<" IShmActiveObject::LoadFromDir 尚未支持"<<ende;return false;}virtual bool SaveToDir(char const * dir_name)const{thelog<<GetName()<<" IShmActiveObject::SaveToDir 尚未支持"<<ende;return false;}virtual bool Report()const{string str;thelog<<T_SET_PARENT::Report_virtual(str)<<endi;return  m_LRUBuffer.Report();}};

五、解释

        你现在问我这个模板咋工作的,我得花些时间重新想想,但是当初绝对是可以工作的。


(这里是结束)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/48854.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

grafana大坑,es找不到时间戳 | No date field named timestamp found

grafana大坑&#xff0c;es找不到时间戳。最近我这边的es重新装了一遍&#xff0c;结果发现grafana连不上elasticsearch了&#xff08;以下简称es&#xff09;&#xff0c;排查问题查了好久一直以为是es没有装成功或者两边的版本不兼容&#xff0c;最后才发现是数值类型问题 一…

XSLFO 文档:格式化 XML 数据的艺术

XSLFO 文档&#xff1a;格式化 XML 数据的艺术 1. 引言 XSLFO&#xff08;Extensible Stylesheet Language Formatting Objects&#xff09;是一种基于 XML 的语言&#xff0c;用于描述如何将 XML 数据格式化为可视化的文档&#xff0c;如 PDF 或打印的页面。XSLFO 提供了一种…

过滤器、同步异步、跨域问题、json数据格式字符串

1、过滤器 过滤器是将JavaEE中对请求和响应进行拦截的技术&#xff0c;定义一个类实现Filter接口&#xff0c;可以让某些请求地址在到达servlet之前进入到指定的过滤器中从而实现统一管理&#xff0c;例如编码过滤&#xff0c;权限过滤等进行统一过滤。 下面是一个编码过滤的…

Java 基础语法教程

1. 类和对象 Java 是一种面向对象的编程语言&#xff0c;它使用类和对象来组织代码。一个 Java 程序可以认为是一系列对象的集合&#xff0c;而这些对象通过调用彼此的方法来协同工作。 1.1 类 类&#xff08;Class&#xff09;是一个模板&#xff0c;它描述一类对象的行为和…

浅聊 Three.js 屏幕空间反射SSR-SSRShader

浅聊 Three.js 屏幕空间反射SSR(2)-SSRShader 前置基础 渲染管线中的相机和屏幕示意图 -Z (相机朝向的方向)||| -------------- <- 屏幕/投影平面| | || | || | (f) | <- 焦距| | ||…

在 Ubuntu 22.04/20.04 安装 CVAT 和 SAM 指南

1. 安装 Docker 和 Docker Compose sudo apt-get update sudo apt-get --no-install-recommends install -y \apt-transport-https \ca-certificates \curl \gnupg-agent \software-properties-common curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-ke…

跨平台游戏引擎 Axmol-2.1.4 发布

2.1.4 版本是用于错误修复和改进的次要 LTS 版本&#xff0c;感谢 axmol 的所有贡献者 相对于 2.1.3 的重大变化&#xff1a; 添加 JobSystem 支持添加 cmake 选项 AX_WASM_INITIAL_MEMORY添加 Linux WebView 实现改进 curl 下载实现 使用curl_multi_poll代替select使用curl_…

java-如何打破双亲委派机制

在Java虚拟机&#xff08;JVM&#xff09;中&#xff0c;双亲委派模型是一种类加载器之间的层次模型&#xff0c;它定义了类加载的规则&#xff0c;即当一个类需要被加载时&#xff0c;JVM默认的行为是首先请求父类加载器加载该类&#xff0c;只有当父类加载器无法加载该类时&a…

【BUG】已解决:error: legacy - install - failure

error: legacy - install - failure 目录 error: legacy - install - failure 【常见模块错误】 【解决方案】 欢迎来到英杰社区https://bbs.csdn.net/topics/617804998 欢迎来到我的主页&#xff0c;我是博主英杰&#xff0c;211科班出身&#xff0c;就职于医疗科技公司&…

51单片机14(独立按键实验)

一、按键介绍 1、按键是一种电子开关&#xff0c;使用的时候&#xff0c;只要轻轻的按下我们的这个按钮&#xff0c;按钮就可以使这个开关导通。 2、当松开这个手的时候&#xff0c;我们的这个开关&#xff0c;就断开开发板上使用的这个按键&#xff0c;它的内部结构&#xff…

免费分享:2021年度全国城乡划分代码(附下载方法)

《关于统计上划分城乡的规定》指出&#xff1a;“本规定作为统计上划分城乡的依据&#xff0c;不改变现有的行政区划、隶属关系、管理权限和机构编制&#xff0c;以及土地规划、城乡规划等有关规定”。统计用区划代码和城乡划分代码用于统计工作&#xff0c;需要在其他工作中使…

Transforms

深度学习中的Transforms 概述 Transforms在深度学习中起到了关键的作用&#xff0c;主要用于数据预处理、特征提取和数据增强&#xff08;Data Augmentation&#xff09;。通过对数据进行各种变换&#xff0c;能够提升模型的训练效果和泛化能力。 数据增强&#xff08;Data …

回溯题目的套路总结

前言 昨天写完了LeeCode的7&#xff0c;8道回溯算法的题目&#xff0c;写一下总结&#xff0c;这类题目的共同特点就是暴力搜索问题&#xff0c;排列组合或者递归&#xff0c;枚举出所有可能的答案&#xff0c;思路很简单&#xff0c;实现起来的套路也很通用&#xff0c;一…

java题目之抽奖以及优化方式

public class Main9 {public static void main(String[] args) {int[]arr{ 2,588,888,1000,10000};int [] newArrnew int[arr.length];//3.抽奖Random rnew Random();//因为有5个奖项,所以这里循环五次for (int i 0; i <5 ; ) {//获取随机索引int randomIndexr.nextInt(arr…

前端-模拟请求数据mook第三方插件 json-server的使用

大纲 第一步下载第二配置mook的数据源第三配置启动命令第四运行模拟服务第五测试接口如果要进行更复杂的操作 第一步下载 npm install json-server -D"devDependencies": {"json-server": "^1.0.0-beta.1"}第二配置mook的数据源 在项目的根目录…

图纸为什么需要加密?2024超好用的图纸加密软件推荐

图纸通常包含产品的设计细节、规格和技术信息&#xff0c;这些都是公司的核心知识产权。加密可以防止未经授权的访问和复制&#xff0c;避免知识产权被盗用或侵权。 图纸加密软件对于保护企业的知识产权和商业秘密至关重要&#xff0c;特别是在CAD&#xff08;计算机辅助设计&…

内网安全:各类密码的抓取

Mimikatz在线读取SAM文件 离线读取SAM文件 在线读取lsass进程 离线读取lsass进程 BrowserGhost浏览器密码抓取 Sharp-HackBrowserData浏览器密码抓取 SharpDecryptPwd数据库密码抓取 LaZagne各类密码的抓取 Windows其他类型抓NTLM Hash工具 sam文件和lsass进程就是Wind…

员工的成长=公司潜力的发展,最大的误区99.99%机器视觉公司不培训员工

员工成才最好的方式&#xff0c;绝对是培训。 机器视觉公司培训99.99%从来不培训员工的&#xff0c;不训练员工。 员工不变得优秀&#xff0c;如何更好的服务客户&#xff0c;无法搞定客户。 去和客户商务谈判&#xff0c;让自己员工去送死&#xff0c; 不去学习如何搞定客户&a…

谷粒商城-商品上架

1.sku在es中的存储模型分析(spring整和es) es中所有数据存在内存中,内存产品贵,能节省就节省,只保存有用的信息 两种保存方法:(空间换时间,时间换空间): 我们选空间换时间 ES中放这些东西: "mappings": { "properties": { "skuId"…

【C++】deque以及优先级队列

容器适配器 deque的介绍deque的原理介绍 priority_queue的介绍与使用priority_queue的介绍priority_queue的使用constructor&#xff08;构造函数&#xff09;emptypushpoptopsize priority_queue的模拟实现 仿函数何为适配器容器适配器deque的缺陷选择deque作为适配器的理由ST…