先从github上可以把相应的Synchrobench代码下载下来https://github.com/gramoli/synchrobench

一.lazy-list代码重构的潜在需求:

  第一个也是最明显的问题是内存回收问题。 比如在并发执行的过程中,如果只是一个节点b的逻辑移除,即使它不再存在于抽象集合中。 但实际上还是有联系的,只是一开始就达不到。 如下所示
这样,如果项目不是空闲的,随着时间的推移,它会导致内存激增。 因此分配给项目节点的内存被回收。
如果你让我去做,我会在最后收回记忆来坚持记忆。

解决方案1:垃圾收集

但是这个方法只来自 Java 和 C#,而不是 C/C++(至少官方)

解决方案 2:智能指针(Smart Pointers)

C++ 及更高版本中的智能指针(#include),它通过三个 API 扮演每个对象的垃圾收集角色和 RAII。 而如果我们只是调用API,就像一个黑匣子,我们只知道结果而不知道过程。

解决方案 3:特定领域的回收

并发数据结构:如惰性链表、无锁链表

二.lazy-list潜在的线程安全问题

  条件变量设置不合理,加锁解锁过程没有设置休眠时间。 如果超时到期,它将无限期地等待。 (没有有效和有用的等待功能)。
  使用全局共享变量容易增加不同任务或线程之间的耦合,也增加了引入bug的风险,所以应该尽量少使用全局共享变量。
  节点是否标记与标记参考情况的功能设计是高度耦合的。 如果实际情况发生变化,修改起来会相当麻烦。 有效性检查和搜索功能是相同的。 插入和删除函数不考虑 while 循环中的异常。 如果中间出现错误,就会陷入死循环。

解决方案:

  1. 通过引用传递而不是传递指针
  2. 尽可能依赖构造函数、复制构造函数和析构函数
  3. 不能只使用堆栈分配

三.lazy-list 代码详解

  1. coupling.c
int lockc_delete(intset_l_t *set, val_t val) {node_l_t *curr, *next;int found;//Lock the first two elementsLOCK(&set->head->lock);curr = set->head;LOCK(&curr->next->lock);next = curr->next;//如果下一个节点的值<当前值:解锁前一个,保留当前的所有权,并在循环中锁定下一个while (next->val < val) {UNLOCK(&curr->lock);curr = next;LOCK(&next->next->lock);next = next->next;}// wait until next node's value == current valuefound = (val == next->val);// 'found' = 1, 然后找到下一个节点,同时解锁并删除它。最后,解锁它的下一个节点if (found) { curr->next = next->next;UNLOCK(&next->lock);node_delete_l(next);UNLOCK(&curr->lock);} else {              // 'found' = 0, only unclock it and its next node UNLOCK(&curr->lock);UNLOCK(&next->lock);}//return whether delete next nodereturn found;
}

delete, find, and insert方法也差不多

  1. insert.c
//当 d->unit_tx == 2 时,返回 ((curr->val == val) && !is_marked_ref((long) curr->next)),否则,在获取元素副本之前Locking每个元素
int set_contains_l(intset_l_t *set, val_t val, int transactional)
{if (transactional == 2) return parse_find(set, val);else return lockc_find(set, val);
}

add和remove方法与此相差不大
3) linkedlist-lock.c

node_l_t *new_node_l(val_t val, node_l_t *next, int transactional){// INIT_LOCK and assign memory to new node
intset_l_t *set_new_l(){//insert node and set min and max for node
void node_delete_l(node_l_t *node) {//DESTROY_LOCK
void set_delete_l(intset_l_t *set){//DESTROY_LOCK and move current node to next
int set_size_l(intset_l_t *set){//compute length of nodes
  1. lazy.c
/** File:*   lazy.c* Author(s):*   Vincent Gramoli <vincent.gramoli@epfl.ch>* Description:*   Lazy linked list implementation of an integer set based on Heller et al. algorithm*   "A Lazy Concurrent List-Based Set Algorithm"*   S. Heller, M. Herlihy, V. Luchangco, M. Moir, W.N. Scherer III, N. Shavit*   p.3-16, OPODIS 2005** Copyright (c) 2009-2010.** lazy.c is part of Synchrobench* * Synchrobench is free software: you can redistribute it and/or* modify it under the terms of the GNU General Public License* as published by the Free Software Foundation, version 2* of the License.** This program is distributed in the hope that it will be useful,* but WITHOUT ANY WARRANTY; without even the implied warranty of* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the* GNU General Public License for more details.*/#include "lazy.h"inline int is_marked_ref(long i) {return (int) (i &= LONG_MIN+1);
}inline long unset_mark(long i) {i &= LONG_MAX-1;return i;
}inline long set_mark(long i) {i = unset_mark(i);i += 1;return i;
}inline node_l_t *get_unmarked_ref(node_l_t *n) {return (node_l_t *) unset_mark((long) n);
}inline node_l_t *get_marked_ref(node_l_t *n) {return (node_l_t *) set_mark((long) n);
}/** Checking that both curr and pred are both unmarked and that pred's next pointer* points to curr to verify that the entries are adjacent and present in the list.*/
inline int parse_validate(node_l_t *pred, node_l_t *curr) {return (!is_marked_ref((long) pred->next) && !is_marked_ref((long) curr->next) && (pred->next == curr));
}int parse_find(intset_l_t *set, val_t val) {//wait until curr->val == val, set next node to unmark node_l_t *curr;curr = set->head;while (curr->val < val)curr = get_unmarked_ref(curr->next);return ((curr->val == val) && !is_marked_ref((long) curr->next));
}int parse_insert(intset_l_t *set, val_t val) {node_l_t *curr, *pred, *newnode;int result, validated, notVal;while (1) {//Initpred = set->head;curr = get_unmarked_ref(pred->next);//Unmark and lock each nodewhile (curr->val < val) {pred = curr;curr = get_unmarked_ref(curr->next);}LOCK(&pred->lock);LOCK(&curr->lock);//check its validated and curr->val whether equals valvalidated = parse_validate(pred, curr);notVal = (curr->val != val);result = (validated && notVal);//only meeting at same time, make pred->next = newnodeif (result) {newnode = new_node_l(val, curr, 0);pred->next = newnode;} //UNLOCK curr and predUNLOCK(&curr->lock);UNLOCK(&pred->lock);//wait until pred and curr meet the validate conditions, exit this loopif(validated)return result;}
}/** Logically remove an element by setting a mark bit to 1 * before removing it physically.** NB. it is not safe to free the element after physical deletion as a * pre-empted find operation may currently be parsing the element.* TODO: must implement a stop-the-world garbage collector to correctly * free the memory.*/
int parse_delete(intset_l_t *set, val_t val) {node_l_t *pred, *curr;int result, validated, isVal;while(1) {//Initpred = set->head;curr = get_unmarked_ref(pred->next);//Unmark and lock each nodewhile (curr->val < val) {pred = curr;curr = get_unmarked_ref(curr->next);}LOCK(&pred->lock);LOCK(&curr->lock);
/*
* Mark Phase:
* Start from the root set to find all memory block references, and then mark the referenced memory block (mark)
*///check its validated and curr->val whether equals valvalidated = parse_validate(pred, curr);isVal = val == curr->val;result = validated && isVal;//only meeting at same time, make pred->next = newnodeif (result) {curr->next = get_marked_ref(curr->next);pred->next = get_unmarked_ref(curr->next);}//UNLOCK curr and predUNLOCK(&curr->lock);UNLOCK(&pred->lock);
/*
* Sweep Phase:
* All memory blocks that are not marked are considered garbage and can be recycled
*///find memory blocks that are not marked, setting a mark bit to 1result = result && parse_find(curr,isVal);//wait until pred and curr meet the validate conditions, exit this loopif(validated){//free the elementfree(curr);return result;}}
}//Checking this node whether null
bool isEmpty(intset_l_t *set, val_t val) {node_l_t  *curr = set->head;//search an element that exist in the list, both logically and physicallywhile (curr->val != val) {//make sure element was not removed logicallycurr = get_unmarked_ref(curr->next);}return ((curr->val == val) && !is_marked_ref((long) curr->next));
}/*Table of sleeping threads. */
static struct array *sleepers;struct node_l_t *thread_bootstrap(void){node_l_t *curr, *pred, *newnode;/*Create the data structures we need.*/sleepers = array_create();if(!sleepers){printf("Cannot create sleepers array\n");}
}void node_sleep(intset_l_t *set, val_t val){//may not sleep in an interrupt handlernode_l_t *curr, *pred;LOCK(&pred->lock);LOCK(&curr->lock);mi_switch(S_SLEEP);UNLOCK(&curr->lock);UNLOCK(&pred->lock);
}/* Release lock, put node to sleep until cv is signaled; when node wakes up again, re-acquire lock before returning */
void node_wakeup(const void *addr){int i, result;isVal = val == curr->val;node_l_t *curr;//This is inefficient, Feel free to improve it.for(i=0; i<array_getnum(sleepers); i++){node_l_t *n = array_getguy(sleepers, i);if (n->val == val) {//Remove from listarray_remove(sleepers. i);//must look at the same sleepers[i] againi--;UNLOCK(&curr->lock);curr = curr->next;/*Because we preallocate during therad_fork,this should never fail. */result = make_runnable(t);assert(result==0);}}
}
  1. lazy.h
/** File:*   lazy.c* Author(s):*   Vincent Gramoli <vincent.gramoli@epfl.ch>* Description:*   Lazy linked list implementation of an integer set based on Heller et al. algorithm*   "A Lazy Concurrent List-Based Set Algorithm"*   S. Heller, M. Herlihy, V. Luchangco, M. Moir, W.N. Scherer III, N. Shavit*   p.3-16, OPODIS 2005** Copyright (c) 2009-2010.** lazy.c is part of Synchrobench* * Synchrobench is free software: you can redistribute it and/or* modify it under the terms of the GNU General Public License* as published by the Free Software Foundation, version 2* of the License.** This program is distributed in the hope that it will be useful,* but WITHOUT ANY WARRANTY; without even the implied warranty of* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the* GNU General Public License for more details.*/#include "coupling.h"/* handling logical deletion flag */
inline int is_marked_ref(long i);
inline long unset_mark(long i);
inline long set_mark(long i);
inline node_l_t *get_unmarked_ref(node_l_t *n);
inline node_l_t *get_marked_ref(node_l_t *n);/* linked list accesses */
int parse_validate(node_l_t *pred, node_l_t *curr);
int parse_find(intset_l_t *set, val_t val);
int parse_insert(intset_l_t *set, val_t val);
int parse_delete(intset_l_t *set, val_t val);

lazy-list C 代码详解相关推荐

  1. 【CV】Pytorch一小时入门教程-代码详解

    目录 一.关键部分代码分解 1.定义网络 2.损失函数(代价函数) 3.更新权值 二.训练完整的分类器 1.数据处理 2. 训练模型(代码详解) CPU训练 GPU训练 CPU版本与GPU版本代码区别 ...

  2. html5代码转换为视频,HTML5中的视频代码详解

    摘要 腾兴网为您分享:HTML5中的视频代码详解,智学网,云闪付,易推广,小红书等软件知识,以及360win10,流量魔盒,fitbit,上港商城,安卓2.3.7,全民惠,五年级下册英语单词表图片,t ...

  3. js php base64,JavaScript实现Base64编码与解码的代码详解

    本篇文章给大家分享的是jJavaScript实现Base64编码与解码的代码详解,内容挺不错的,希望可以帮助到有需要的朋友 一.加密解密方法使用//1.加密 var str = '124中文内容'; ...

  4. yii mysql 事务处理_Yii2中事务的使用实例代码详解

    前言 一般我们做业务逻辑,都不会仅仅关联一个数据表,所以,会面临事务问题. 数据库事务(Database Transaction) ,是指作为单个逻辑工作单元执行的一系列操作,要么完全地执行,要么完全 ...

  5. 代码详解|tensorflow实现 聊天AI--PigPig养成记(1)

    Chapter1.代码详解 完整代码github链接,Untitled.ipynb文件内. [里面的测试是还没训练完的时候测试的,今晚会更新训练完成后的测试结果] 修复了网上一些代码的bug,解决了由 ...

  6. vue build text html,Vue中v-text / v-HTML使用实例代码详解_放手_前端开发者

    废话少说,代码如下所述: /p> 显示123 /p> 补充:vuejs {{}},v-text 和 v-html的区别 {{message}} let app = new Vue({ el ...

  7. sift计算描述子代码详解_代码详解——如何计算横向误差?

    在路径跟踪控制的论文中,我们常会看到判断精确性的指标,即横向误差和航向误差,那么横向误差和航向误差如何获得? 在前几期代码详解中,参考路径和实际轨迹均由To Workspace模块导出,如图所示: 那 ...

  8. 委托与事件代码详解与(Object sender,EventArgs e)详解

    委托与事件代码详解 using System; using System.Collections.Generic; using System.Text; namespace @Delegate //自 ...

  9. python怎么画条形图-python绘制条形图方法代码详解

    1.首先要绘制一个简单的条形图 import numpy as np import matplotlib.pyplot as plt from matplotlib import mlab from ...

  10. python代码大全表解释-python操作列表的函数使用代码详解

    python的列表很重要,学习到后面你会发现使用的地方真的太多了.最近在写一些小项目时经常用到列表,有时其中的方法还会忘哎! 所以为了复习写下了这篇博客,大家也可以来学习一下,应该比较全面和详细了 列 ...

最新文章

  1. linux基础知识_压缩—进程管理-网络管理-ftp-nfs-ssh-scp
  2. pycharm2017设置注释字体颜色
  3. scrollToItemAtIndexPath使用
  4. GODADDY主机用tar命令通过SSH远程打包20M以上的文件
  5. pycharm连接到gitee的操作
  6. 【转】【OpenCV入门教程之一】 安装OpenCV:OpenCV 3.0、OpenCV 2.4.8、OpenCV 2.4.9 +VS 开发环境配置
  7. 接口的意义及于抽象类的区别(蒋波涛)
  8. 具体解释站点沙盒期的原因表现与解决的方法
  9. mybatis整体架构
  10. websocket多人聊天php,php-notes/基于websocket实现多人聊天室.md at master · dd-code-site/php-notes · GitHub...
  11. laravel商品图片怎么展示_如何使用Laravel图片处理包intervention-image
  12. 2020-11-16学习总结: sass配置
  13. editplus的php插件,editplus的各式插件
  14. 两点天上来,爱情一线牵——Global Timing Debugger
  15. 与蜂窝连接的无人机的空地干扰缓解
  16. 学生DW静态网页设计—西安旅游-高质量(9页) HTML+CSS+JavaScript 学生DW网页设计
  17. MySQL中按天、自然周、月、季度、年份统计
  18. Arduino UNO控制HC-SR04超声波实现(测距)及对超声波的认识
  19. 自动投票系统【二】模拟登录提交
  20. 【camx】camera sensor点亮

热门文章

  1. 数据结构与算法python—6.链表及python实现
  2. pytorch---模型加载与保存(6)通过设备保存/加载模型
  3. Datawhale编程学习之图(6)
  4. 基于Hosted WebCore 方式部署Web Role
  5. 79 ----二次曲面的分类、二次项系数矩阵的特征多项式、二次项系数矩阵的特征值与特征向量、消去二次交叉项、二次曲面方程中的一次项和常数项的变化
  6. 无法添加外键约束的原因(cannot add foreign key constraint)
  7. pyinstaller相关错误
  8. java4特征_java的四大基本特征
  9. base cap 分布式_分布式系统一致性问题、CAP定律以及 BASE 理论
  10. stm32 非debug模式程序无法运行