使用 std::unique_ptr/std::shared_ptr 确认线程安全

2023-12-02

我的应用程序有一个 IRC 模块,本质上是一个普通的客户端。由于这是高度线程化的,因此我面临插件检索的风险,例如,用户昵称 - 它当时有效,但解析器触发更新,更改所述昵称。 一旦另一个线程再次执行,它就会处理指向现在无效内存的指针,因为不可能将 return + copy 作为原子操作。

根据下面的代码,我对此的假设是否正确?因此,我想我必须使用通常的互斥锁/解锁方法,除非有人可以确认或建议其他方法(我宁愿不必转换并返回一个shared_ptr,但我想这是一个有效的选项,它是只是我打算对此进行 SWIG'ing,但不知道它是否会不喜欢它们)。

IrcUser.h

class IrcUser : public IrcSubject
{
private:
    ...
    std::shared_ptr<std::string>    _nickname;
    std::shared_ptr<std::string>    _ident;
    std::shared_ptr<std::string>    _hostmask;
public:
    ...
    const c8*
    Ident() const
    { return _ident.get()->c_str(); }

    const c8*
    Hostmask() const
    { return _hostmask.get()->c_str(); }

    const u16
    Modes() const
    { return _modes; }

    const c8*
    Nickname() const
    { return _nickname.get()->c_str(); }

    bool
    Update(
        const c8 *new_nickname,
        const c8 *new_ident,
        const c8 *new_hostmask,
        const mode_update *new_modes
    );
};

IrcUser.cc

bool
IrcUser::Update(
    const c8 *new_nickname,
    const c8 *new_ident,
    const c8 *new_hostmask,
    const mode_update *new_modes
)
{
    if ( new_nickname != nullptr )
    {
        if ( _nickname == nullptr )
        {
            *_nickname = std::string(new_nickname);
        }
        else
        {
            _nickname.reset();
            *_nickname = std::string(new_nickname);
        }

        Notify(SN_NicknameChange, new_nickname);
    }

    ...
}

我建议锁定如此细粒度的级别可能(方式)过度杀伤力。

我建议对 IrcUser 对象本身进行原子更新,这可能是无锁取决于您的库实现和目标架构。这是一个使用的示例

  • std::atomic_is_lock_free<std::shared_ptr>
  • std::atomic_load<std::shared_ptr>
  • std::atomic_store<std::shared_ptr>

See http://en.cppreference.com/w/cpp/memory/shared_ptr/atomic用于文档。

免责声明 我不知道有多少编译器/C++ 库实现已经实现了这个 C++11 功能。

它看起来像这样:

#include <atomic>
#include <memory>
#include <string>

struct IrcSubject {};
typedef char c8;
typedef uint16_t u16;
typedef u16 mode_update;

class IrcUser : public IrcSubject
{
    private:
        // ...
        std::string _nickname;
        std::string _ident;
        std::string _hostmask;
        u16         _modes;
    public:
        IrcUser(std::string nickname, std::string ident, std::string hostmask, u16 modes)
            : _nickname(nickname), _ident(ident), _hostmask(hostmask), _modes(modes) { }
        // ...
        std::string const& Ident()    const { return _ident; }
        std::string const& Hostmask() const { return _hostmask; }
        const u16          Modes()    const { return _modes; }
        std::string const& Nickname() const { return _nickname; }
};

//IrcUser.cc
bool Update(std::shared_ptr<IrcUser>& user,
    std::string new_nickname,
    std::string new_ident,
    std::string new_hostmask,
    const mode_update *new_modes
)
{
    auto new_usr = std::make_shared<IrcUser>(std::move(new_nickname), std::move(new_ident), std::move(new_hostmask), *new_modes /* ??? */);
    std::atomic_store(&user, new_usr);
    //Notify(SN_NicknameChange, new_nickname);
    return true;
}

bool Foo(IrcUser const& user)
{
    // no need for locking, user is thread safe
}

int main()
{
    auto user = std::make_shared<IrcUser>("nick", "ident", "hostmask", 0x1e);

    mode_update no_clue = 0x04;
    Update(user, "Nick", "Ident", "Hostmask", &no_clue);

    {
        auto keepref = std::atomic_load(&user);
        Foo(*keepref);
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 std::unique_ptr/std::shared_ptr 确认线程安全 的相关文章

  • static_assert 有什么作用,你会用它做什么?

    你能举个例子吗static assert C 11 会优雅地解决手头的问题吗 我熟悉运行时assert 我应该选择什么时候static assert 超过常规assert 另外 在boost有一种东西叫做BOOST STATIC ASSER
  • boto 库是线程安全的吗?

    具体来说 我对从多个线程 放置 获取 更新等 使用 DynamoDB 表对象感兴趣 如果这不安全 那么是否有一种安全的方法 即每个线程可能有一个表对象 关于在 boto 中使用线程的任何其他陷阱或技巧表示赞赏 boto 库使用 httpli
  • queue.Queue 与 collections.deque

    我需要一个队列 多个线程可以将内容放入其中 并且多个线程可以从中读取 Python至少有两个队列类 queue Queue and collections deque 前者似乎在内部使用后者 两者在文档中都声称是线程安全的 但是 那Queu
  • udp客户端服务器从拉模型更改为推模型[关闭]

    Closed 这个问题需要调试细节 help minimal reproducible example 目前不接受答案 我已经实施了udp client和 udp server 其中服务器和客户端遵循拉模型 服务器仅在客户端请求时推送数据
  • 执行 INSERT into 数据库后如何获取插入行的 id?

    我正在使用 c 11 和 pqxx 访问 postgresql 数据库 我需要插入行的 id 和标志 如果成功与否 执行 INSERT into 数据库后如何获取插入行的 id 我试图在网上找到例子但没有成功 work txn conn t
  • C++11 在运行时索引元组而不使用 switch 的方法

    我有一段 c 11 代码 如下所示 switch var case 1 dosomething std get lt 1 gt tuple case 2 dosomething std get lt 2 gt tuple 有什么办法可以把这
  • 混合别名和模板专业化

    我试图找到一种最好的方法来拥有一种可以专门化或 链接 到另一种类型的 对象 例如 您不能专门化一个类以使其成为一个简单的 int 并且您不能使用关键字 using 来专门化类 我的解决方案如下 template
  • 是否有自动 noexcept 说明符?

    我听说过noexcept关键字更像是 它永远不应该抛出异常 而不是 它不抛出异常 我觉得不好用noexcept关键字 如果我不确定它是否引发异常 但是noexcept关键字有时与性能相关 例如在移动构造函数中 所以我尝试使用noexcept
  • C++ 11 相当于 java.util.ConcurrentHashMap

    我发现自己不断地编写互斥体代码 以便同步对 std unordered map 和其他容器的读 写访问 以便我可以像使用 java util concurrent 容器一样使用它们 我正要开始编写一个包装器来封装互斥体 但我宁愿使用经过良好
  • 指向 STL 容器的指针安全吗?

    如果我做一个怎么办unique ptr指向一个STL容器的实例 如下所示 这段代码安全吗 unique ptr lt vector
  • C++11 删除重写方法

    Preface 这是一个关于最佳实践的问题 涉及 C 11 中引入的删除运算符的新含义 当应用于覆盖继承父类的虚拟方法的子类时 背景 根据标准 引用的第一个用例是明确禁止调用某些类型的函数 否则转换将是隐式的 例如最新版本第 8 4 3 节
  • 具有元组类型子集相应参数的模板函数

    我想这样写函数find multi set
  • ASP.NET 开发人员真的需要关心线程安全吗?

    我认为自己了解线程的概念以及为什么某些代码是或不是 线程安全 的 但作为主要使用 ASP NET 的人 线程和线程安全是我很少考虑的事情 然而 我似乎在 Stack Overflow 上遇到了大量评论和答案 不一定适用于 ASP NET 大
  • 在 SQLite 中搜索时排除 HTML 标签和一些 UNICODE 字符

    更新 4 我已经成功运行了firstchar例如 但现在的问题是使用regex 即使包含头文件 它也无法识别regex操作员 有什么线索可以解决这个问题吗 更新 2 我已经编译了sqlite3我的项目中的库 我现在正在寻找任何人帮助我为我的
  • 用于多行字符串的 ECMAScript 正则表达式

    我正在为我的应用程序编写加载过程 它涉及从文件中读取数据并创建具有适当属性的适当对象 该文件由以下格式的连续条目 以换行符分隔 组成 OBJECT TYPE
  • Shared_ptr 在哪里?

    经过几个小时试图找到shared ptr 所在的位置后 我现在非常沮丧 我看到的示例都没有显示包含标头的完整代码shared ptr 和工作 简单说明一下std tr1 and
  • C++11 容器/适配器属性的实用总结/参考? [关闭]

    Closed 这个问题是无关 help closed questions 目前不接受答案 我正在寻找各种 C 11 标准容器和容器适配器的重要属性的全面总结 参考 也可以选择包括 boost Qt 但是按这些属性索引而不是通常的每个容器文档
  • 在 C++11 中抛出异常时是否使用移动语义?

    http www drdobbs com cpp practical c error handling in hybrid env 197003350 pgno 4 http www drdobbs com cpp practical c
  • std::to_string - 多个重载函数的实例与参数列表匹配

    counter is an int void SentryManager add std string name std shared ptr
  • 具有交替类型的可变参数模板参数包

    我想知道是否可以使用参数包捕获交替参数模式 例如 template

随机推荐

  • 如何从android中的sqlite数据库中检索数据并将其显示在TextView中

    我正在学习安卓 我有一个问题 但我无法解决它 我想从现有数据库中检索数据并将其显示在TextView单击按钮后 My code 数据库助手看起来像这样 public class DataBaseHelper extends SQLiteOp
  • 卷积中的2D步幅是什么意思?

    我知道当步幅只是一个整数时它的含义是什么 通过这一步你应该对图像应用过滤器 但是关于 1 1 或者甚至更多维度的进步 The stride定义滤波器如何沿着输入图像 张量 移动 没有什么可以阻止你沿着不同的轴以不同的方式大步前进 例如 st
  • 如何在 Mac OS X 中监听应用程序启动事件?

    我写了一个AppleScript安装一个SparseBundle图像 我希望它准确地执行Time Machine发射 现在 我定期检查 Time Machine 是否正在运行AppleScript using on idle陈述 on id
  • 带有操作栏和选项卡的 Android 布局

    我是 Android 新手 需要您的建议 我想要一个带有操作栏的活动 我还需要选项卡 但不是操作栏中的选项卡 和操作栏中的下拉列表进行导航 当我点击例如第一个选项卡时 操作栏中的导航列表应填充数据 当秒选项卡时 导航列表应填充其他数据等 当
  • Javascript 错误:JupyterLab 中未定义 IPython

    我有最新 更新的 Anaconda 包 每次我尝试使用 python 3 6 6 绘制某些内容时 我都会在 JupyterLab 中收到以下错误 JavaScript 错误 IPython 未定义 当我使用 ipython 内核在 Spyd
  • 无法解决“c 不是构造函数”错误

    我正在尝试使用 ExtJS 构建一个非常非常基本的 概念验证 应用程序 但我遇到了困难 我想要的只是两个网格从远程 JSON 文件获取数据 但无论我做什么 我都会不断收到主题中的错误 这是我的简单代码 app js Ext Loader s
  • Azure 函数在大型 TIF 文件上调用 Image.FromStream 抛出“参数无效”

    我正在尝试在 Azure 函数中处理多页 TIF 该函数由 blob 存储的更改触发 当触发器运行时 它会调用 function loadFile Stream mpTif Bitmap pageOnes Bitmap Image From
  • 将模块版本作为命令行参数发送给 SBT

    我正在使用 TeamCity 运行 bash 脚本 该脚本利用 SBT Native Packager 将映像发布到 Docker bash 脚本的 sbt 部分如下所示 sbt DdockerRepository repo Dpackag
  • 更新 VS2008 Crystal Reports 上的数据集架构

    我正在使用 Visual Studio 2008 中 Crystal Reports 的内置模块创建一个报告 为此我添加了一个包含多个数据表的数据集 就目前而言 数据表具有一定数量的字段 这些字段将来可能会增长 因此下一个更新我的报告的人将
  • event.currentTarget 的实际用途?

    非常清楚的是event target处理发起事件的 DOM 元素 And event delegateTarget提供我们实际附加监听器的 DOM 元素 但我很难理解我什么时候会使用 事件 currentTarget 查看显示此示例的 jQ
  • 并行 ForEach 与 SQL 插入 C#

    我有一个如下所示的对象 但数据量很大 我们观察到插入到我们的 SQL 数据库中需要很长时间 因为我们使用普通的foreach 主要思想是插入每个部门并获取生成的身份号码 然后插入分配有该部门 ID 的嵌套员工
  • 按行删除每行列子集中的重复项,按行仅保留第一个副本

    我有以下 pandas 数据框 超过 700 万行 import pandas as pd data date 2023 02 22 2023 02 21 2023 02 23 x1 descx1a descx1b descx1c x2 A
  • angular2firebase - 使用 Angular 6 的多个实例

    我正在升级到Angular 6 using AngularFire2 我的应用程序引用了 2Firebase项目使用这样的代码来创建数据库引用 public initFirebaseApp config FirebaseAppConfig
  • 寻找实时网络服务器分析包[关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 目前不接受答案 我是一家县医院教育科的程序员 我希望能够在只能在内部访问的 IIS6 Web 服务器上查看一些实时统计数据 我正在寻找类似于 1and1 com 为
  • 圆角包含在小分区中的大图像的侧面在 Chrome 中不起作用

    我正在尝试用圆角化背景图像的侧面border radius财产 这是我的场景 我将一个大图像放在一个小分区中作为背景 并将溢出隐藏起来 现在我需要对小部门进行四舍五入 我成功绕过了小师 但图像的角不是圆角的 HTML div class v
  • 如何自动调整 iFrame 的大小? [复制]

    这个问题在这里已经有答案了 可能的重复 根据内容调整 iframe 的大小 我正在加载 iFrame 并希望父级根据 iFrame 内容的高度自动更改高度 简而言之 所有页面都属于同一域 因此我不应该遇到跨站点脚本问题 在任何其他元素上 我
  • Keras - 绘制训练、验证和测试集准确性

    我想绘制这个简单神经网络的输出 model compile loss binary crossentropy optimizer adam metrics accuracy history model fit x test y test n
  • 使用node-csv和meteor-file将CSV导入到集合中

    现在已经挣扎了几个小时 尝试导入从客户端上传的 CSV流星文件并使用转换为 CSVnode csv服务器端 我基本上需要用用户上传的 CSV 文件中的数据填充我的集合 server filehandler js Meteor methods
  • 如何克隆包含装箱特征对象的 HashMap?

    I have HashMap使用自定义哈希器 这个的项目HashMap没有实现特征Clone 这是一个特征 但是有一个克隆项目的功能 如下所示 use std collections HashMap use std hash BuildHa
  • 使用 std::unique_ptr/std::shared_ptr 确认线程安全

    我的应用程序有一个 IRC 模块 本质上是一个普通的客户端 由于这是高度线程化的 因此我面临插件检索的风险 例如 用户昵称 它当时有效 但解析器触发更新 更改所述昵称 一旦另一个线程再次执行 它就会处理指向现在无效内存的指针 因为不可能将