C++ 20 线程安全的Map

C++ 20 线程安全的Map

粗粒度(锁住整个bucket_data)

template <typename Key, typename Value, typename Hash = std::hash<Key>>
class threadsafe_lookup_table
{
private:class bucket_type{private:using bucket_value = std::pair<Key, Value>;using bucket_data = std::list<bucket_value>;using bucket_iterator = typename bucket_data::iterator;bucket_data data;mutable std::shared_mutex mutex;bucket_iterator find_entry_for(Key const& key) const{return std::find_if(data.begin(), data.end(), [&](bucket_value const& item) { return item.first == key; });}public:/*** std::shared_lock<std::shared_mutex>  允许多线程读*/Value value_for(Key const& key, Value const& default_value) const{std::shared_lock<std::shared_mutex> lock(mutex);bucket_iterator const found = find_entry_for(key);return found == data.end() ? default_value : found->second;}/*** std::unique_lock<std::shared_mutex> 只允许单个线程持有*/void add_or_update_mapping(Key const& key, Value const& value){std::unique_lock<std::shared_mutex> lock(mutex);bucket_iterator const found = find_entry_for(key);if (found == data.end()){data.push_back(std::make_pair(key, value));}else{found->second = value;}}/*** std::unique_lock<std::shared_mutex> 只允许单个线程持有*/void remove_mapping(Key const& key){std::unique_lock<std::shared_mutex> lock(mutex);bucket_iterator const found = find_entry_for(key);if (found != data.end()){data.erase(found);}}};std::vector<std::unique_ptr<bucket_type>> buckets;Hash hasher;bucket_type& get_bucket(Key const& key) const{std::size_t const bucket_index = hasher(key) % buckets.size();return *buckets[bucket_index];}public:using key_type = Key;using mapped_type = Value;using hash_type = Hash;threadsafe_lookup_table(std::size_t num_buckets = 23/*最好为质数*/, Hash const& hasher = Hash()): buckets(num_buckets), hasher(hasher){for (auto& bucket : buckets){bucket = std::make_unique<bucket_type>();}}threadsafe_lookup_table(threadsafe_lookup_table const& other) = delete;threadsafe_lookup_table& operator=(threadsafe_lookup_table const& other) = delete;Value value_for(Key const& key, Value const& default_value = Value()) const{return get_bucket(key).value_for(key, default_value);}void add_or_update_mapping(Key const& key, Value const& value){get_bucket(key).add_or_update_mapping(key, value);}void remove_mapping(Key const& key){get_bucket(key).remove_mapping(key);}// 快照std::map<Key, Value> get_map() const{std::vector<std::unique_lock<std::shared_mutex>> locks;// 持有所有bucket的锁 独占for (auto& bucket : buckets){locks.push_back(std::unique_lock<std::shared_mutex>(bucket->mutex)); }std::map<Key, Value> res;for (auto& bucket : buckets){for (auto& item : bucket->data){res.emplace(item.first, item.second);}}return res;}
};

细粒度(锁住每个node)

template <typename T>
class threadsafe_list
{
private:struct node{std::mutex m;std::shared_ptr<T> data;std::unique_ptr<node> next;node(): next(){}node(T const& value): data(std::make_shared<T>(value)), next(){}};node head;public:threadsafe_list(){}~threadsafe_list(){remove_if([](node const&) { return true; });}threadsafe_list(threadsafe_list const& other) = delete;threadsafe_list& operator=(threadsafe_list const& other) = delete;void push_front(T const& value){std::unique_ptr<node> new_node(new node(value));std::lock_guard<std::mutex> lock(head.m);new_node->next = std::move(head.next);head.next = std::move(new_node);}template <typename Function>void for_each(Function f){node* current = &head;std::unique_lock<std::mutex> lock(head.m);while (node* const next = current->next.get()){std::unique_lock<std::mutex> next_lk(next->m);lock.unlock();f(*next->data);current = next;lock = std::move(next_lk);}}template <typename Predicate>std::shared_ptr<T> find_first_if(Predicate P){node* current = &head;std::unique_lock<std::mutex> lock(head.m);while (node* const next = current->next.get()){std::unique_lock<std::mutex> next_lk(next->m);lock.unlock();if (P(*next->data)){return next->data;}current = next;lock = std::move(next_lk);}return std::shared_ptr<T>();}template <typename Predicate>void remove_if(Predicate p){node* current = &head;std::unique_lock<std::mutex> lk(head.m);while (node* const next = current->next.get()){std::unique_lock<std::mutex> next_lk(next->m);if (p(*next->data)){std::unique_ptr<node> old_next = std::move(current->next);current->next = std::move(next->next);next_lk.unlock();}else{lk.unlock();current = next;lk = std::move(next_lk);}}}
};

参考《C++并发编程实战第二版》, 稍有改动

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

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

相关文章

毕业多年,我们转变了多少?

懵懂,激情,成熟,沉默.似乎就是每个人的必经之路.从毕业时的酬躇满志到如今的随遇而安,从毕业时的悲伤离别到如今的陌路行人.从毕业时的海枯石烂到如今的两情分别.究竟,我们还有多少没有转变?毕业两年了,才知道,理想再崇高,究竟还是比不过面包.没有理想,大家照样活的滋润.没有面…

IOS设计模式之二(门面模式,装饰器模式)

本文原文请见&#xff1a;http://www.raywenderlich.com/46988/ios-design-patterns.由 krq_tiger&#xff08;http://weibo.com/xmuzyq&#xff09;翻译&#xff0c;如果你发现有什么错误&#xff0c;请与我联系谢谢。门面&#xff08;Facade&#xff09;模式&#xff08;译者…

java实现输出字符串中的数字字符

package com.joe; import java.util.regex.Matcher; import java.util.regex.Pattern; public class Test { //将字符串的数字字符输出 public static void main(String[] args) { String str "iu7i8hy4jnb2"; //方法一 …

隐私策略 URL

本隐私策略的目的是说明当您访问和使用本插件时我们可能会搜集的资料, 我们会怎样使用这些资料, 是否会透露给第三方, 以及您对这些资料的使用及修改方面的选择权利. 本隐私策略适用于本插件,您需要仔细阅读本隐私策略. 访问者的信息 本插件会保存用户要求保存的信息 插件将…

揭开Vmware 虚拟软件层的秘密

【电脑商网专稿】虚拟软件究竟是什么软件, 是让所有的软件都”虚拟”执行吗, 虚拟软件层究竟是怎样的一层软件? 为什么现在这么多的公司和个人都在使用这种软件, 虚拟软件能代替操作系统完全控制硬件吗? 下面就让我们逐渐的揭开虚拟化技术这一特殊软件层的秘密吧.谈到虚拟化就…

1.使用 Blazor 利用 ASP.NET Core 生成第一个 Web 应用

参考 https://dotnet.microsoft.com/zh-cn/learn/aspnet/blazor-tutorial/create 1.使用vs2022创建新项目 选择 C# -> Windows -> Blzxor Server 应用模板 2.项目名称BlazorApp下一步 3.选择 .NET6.0 或 .NET7.0 或 .NET8.0 创建 4.运行BlazorApp 5.全部选择是。 信…

BROCADE 300和MD3200扩展柜FC SAN,截图

这表示俺玩过&#xff0c;其实&#xff0c;这个光交换机在只有一个共享存储的情况下&#xff0c;可用可不用。 FC BROCADE只是为了方便后期扩展。 FC SAN之类的识别不靠IP&#xff0c;因为不是IP SAN嘛。但也是自己的识别体系。 转载于:https://www.cnblogs.com/aguncn/p/36640…

Java从控制台中读取数据完全攻略

0 引言从控制台中读取数据是一个比较常用的功能&#xff0c;在 JDK 5.0 以前的版本中的实现是比较复杂的&#xff0c;需要手工处理系统的输入流。有意思的是&#xff0c;从 JDK 5.0 版本开始&#xff0c;能从控制台中输入数据的方法每增加一个版本号&#xff0c;就有一种新增的…

总算有点眉目了!

今天打开一个很久没用的邮箱~发现51CTO居然还记得我给我发了封邮件~我也很久没去了&#xff08;基本上注册过后就没去&#xff09;进去看了下~发现变化好大......壮大了。现在我有点激动&#xff0c;总算找到点眉目&#xff0c;在经过了2年的等死阶段&#xff08;偶于2005年学校…

C++ 20 并发编程 std::promise

C 20 并发编程 std::promise std::promise和std::future是一对, 通过它们可以进行更加灵活的任务控制 promise通过函数set_value()传入一个值, 异常, 或者通知, 并异步的获取结果 例子: void product(std::promise<int>&& intPromise, int a, int b) {intPro…

react(87)--批量删除进行置空操作

if (selectedRowKeysList.length 0) {message.error(请选中列表内容);}this.setState({selectedRowKeysList: [],});

女孩儿们的那点秘密

女孩终归是女孩&#xff0c;女孩们总是强迫自己要出得了厅堂入得了厨房有木有&#xff1f;可你们造吗&#xff1f;这对女孩来说可都不容易&#xff01; 你们都以为做饭对女孩来说很简单&#xff0c;可知道我们面对四处乱喷热滚滚的油也会手足无措躲得远远的&#xff1f; 别嫌弃…

求一个正整数是由哪几个连数(连续的正整数)相加

题目描述&#xff1a;随便给出一个正整数&#xff0c; 求出这个数是由哪几个正整数相加&#xff0c;要求相加的这几个数是连续的。 如&#xff1a; 7815&#xff0c;45615&#xff0c;1234515 Test.java: package com.joe; public class Test { public static void main(Str…

CF卡引导IOS惊魂记(二)

接着昨天昨天头比较晕&#xff0c;没有理清思路&#xff0c;今天着重思考几个问题&#xff1a;CF卡的问题&#xff1b;网络为什么不能引导的问题&#xff1b;Flash是否有问题&#xff1b;&#xff08;1&#xff09;CF卡昨天一开始测试时候既然是好的&#xff0c;那么一定是后面…

react(88)--ant design控制inputNumber设置正整数

})(<InputNumberformatter{limitDecimals}parser{limitDecimals}placeholder"请输入助力人数"min{0}/>)} const limitDecimals (value) > {return value.replace(/^(0)|[^\d]/g, );};

求一个正整数是哪几个正整数相加的和,这些数不能相同

问题描述&#xff1a;求一个正整数是哪几个正整数相加的和 (这些数要各不相同) 说明&#xff1a;给定一个正整数&#xff0c;如8&#xff0c;要求输出以下数组&#xff0c;因为他们的和为8&#xff1a; [1, 2, 5] [1, 3, 4] [1, 7] [2, 6] [3, 5] [8] 代码是一个牛人写的…

管理学

管理学<?xml:namespace prefix o ns "urn:schemas-microsoft-com:office:office" />第一 什么是管理学管理学有两种认识&#xff1a;其一&#xff0c;运筹学(Operation Research)是一门运用科学&#xff0c;并不是纯粹的数学&#xff0c;它具有多学科交叉的…

react(89)--设置只能正整数

<InputNumber// formatter{limitDecimals}// parser{limitDecimals}precision{0}placeholder"请输入助力人数"min{0}/>