草庐IT

c++ - 在实践现代 c++17 最佳实践的同时管理线程

coder 2024-02-22 原文

本来我想设计一个ThreadManager要存储的类 threads连同 data type objectsfunction type objects他们将与之合作。该类负责管理标准多线程库中关联类型的内存、访问、传输、释放、锁定、解锁、连接和其他典型的通用功能。它最初旨在将包含线程及其 ID 与特定线程有权访问的一组特定资源相关联。

阅读完 cppreference 上的文档后关于mutex , shared_mutex , lock_guard , shared_lock , std::function<...>等,现在知道 mutexeslock_guards是不可复制的,而且如果我将类模板化以存储任意 function objects 的事实, function pointers , lambdasstd::function<>作为 std::function<>在这个类的容器中,这个预期的单例的类实例化只能存储一个特定的函数签名,限制它不能实例化任何其他声明签名。

关于 mutexes 的标准库中多线程库的这些行为和属性, shared_mutexes lock_guards , threads , promises , futures等等...我想到了我对这门课的整体设计考虑过多。

您可以通过我之前提出的这个问题来引用我最初的设计尝试。 Storing arbitrary function objects into a class member container without knowing their declaration signature , 这应该让您了解我正在尝试做什么。


更多地了解它们的行为、属性和职责 我想知道以下内容是否适合预期的设计过程。

而不是存储任何 mutexes , lock_guards , threads , data type objectsfunction objects ;只存储生成的 ids 是否更有意义?的 threads ,让我的经理类更像是一个监控、记录和报告类型的类?

我的新意图是容器将线程的 ID 作为其键与关联的公共(public)结构一起存储在关联的映射中。该结构将包含组合资源的所有职责和操作的属性列表。这可能允许支持以下某些功能:优先级队列、任务调度程序、发送和获取资源的命令调度程序,知道线程是否可用,此类不会执行这些类型的操作直接但通过通用函数模板。

例如:

struct ThreadProperties {
    // thread specific
    id,
    slept for,
    is locked,
    is waiting,
    is joined,
    has mutex, if so hold id to mutex - lockguard
    is shared,
    is active,
    has promise or future...
    who has ownership of,
    marked for release,
    marked for transfer

    // other mutex and lock_guard properties

    // function object address stored as `size_t` to represent an id
    // data object address stored as `size_t` to represent an id

    // etc.

};

class ThreadManager {
private:
    std::map<unsigned, ThreadProperites> threadTable;
public:
    default constructor

    storeIds into relevant containers

    store properties into relevant containers

    associate above containers into a map or lookup table

    find or look for specific ID and if found 
    check to see its current status and report it
    also check to see if it's in a priority queue 
    or task scheduler and determine if it is ready
    to do something, or change its internal state.

    other common methods of functionality associated with threads.
};

// function templates to act on threads according to the reporting of the manager above.

我打算实现这种设计,同时尝试维护针对 c++17 的现代 c++ 的最佳实践;这种设计是否适合适当的类设计以使其通用、模块化、可移植和高效使用?

最佳答案

线程和其他 std基元就像原始指针。您应该建立一个不暴露任何低级别的并发模型。 std线程原语为您提供了足够的工具来做到这一点。

了解即将推出的一些新内容——执行程序、流、协程、rangesv3、monadic futures 等。围绕这些内容对您的库进行建模。

尝试基于互斥锁、线程休眠和唤醒、阻塞、原子和共享数据的原始使用来编写行为良好的代码是一个陷阱。

举个例子:

struct thread_pool;
template<class T>
struct my_future:std::future<T> {
  template<class F>
  auto then( F&& f )&&
  -> std::future< std::result_of_t<F(T&&)> >;
  thread_pool* executor = 0;
};
template<>
struct my_future<void>:std::future<void> {
  template<class F>
  auto then( F&& f )&&
  -> std::future< std::result_of_t<F()> >;
  thread_pool* executor = 0;
};
struct thread_pool {
  template<class F=do_nothing>
  my_future<std::result_of_t<F()>> do_task(F&& f={});
};

这里我们讨论了从一个任务到另一个任务的管道数据,并以一个增强的 future<T> 结束。 .通过拆分(通过 shared_future)和合并(future<X> 加入 future<Y> 生成 future<X, Y> )来增强它。

也许更进一步,构建一个基于流的系统:

template<class In>
using sink = std::function<void(In)>;
template<class Out>
using source = std::function<sink<Out>>;
template<class In, class Out>
using pipe = std::function< source<In>, sink<Out> >;

然后支持将源转换为异步源。

不要建立一些巨大的抽象城堡并希望它是完整的,而是阅读这些东西,当你遇到一个问题,其中一个可以解决你的问题时,实现足以解决你的问题。第一次尝试时,您并不是从头开始编写无所不能的线程系统,所以不要尝试。写一些有用的东西,下次再写一个更好的。

关于c++ - 在实践现代 c++17 最佳实践的同时管理线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49439929/

有关c++ - 在实践现代 c++17 最佳实践的同时管理线程的更多相关文章

  1. ruby-on-rails - 使用 Ruby on Rails 进行自动化测试 - 最佳实践 - 2

    很好奇,就使用ruby​​onrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提

  2. ruby - i18n Assets 管理/翻译 UI - 2

    我正在使用i18n从头开始​​构建一个多语言网络应用程序,虽然我自己可以处理一大堆yml文件,但我说的语言(非常)有限,最终我想寻求外部帮助帮助。我想知道这里是否有人在使用UI插件/gem(与django上的django-rosetta不同)来处理多个翻译器,其中一些翻译器不愿意或无法处理存储库中的100多个文件,处理语言数据。谢谢&问候,安德拉斯(如果您已经在ruby​​onrails-talk上遇到了这个问题,我们深表歉意) 最佳答案 有一个rails3branchofthetolkgem在github上。您可以通过在Gemfi

  3. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  4. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  5. ruby - RuntimeError(自动加载常量 Apps 多线程时检测到循环依赖 - 2

    我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("

  6. ruby-on-rails - 获取 inf-ruby 以使用 ruby​​ 版本管理器 (rvm) - 2

    我安装了ruby​​版本管理器,并将RVM安装的ruby​​实现设置为默认值,这样'哪个ruby'显示'~/.rvm/ruby-1.8.6-p383/bin/ruby'但是当我在emacs中打开inf-ruby缓冲区时,它使用安装在/usr/bin中的ruby​​。有没有办法让emacs像shell一样尊重ruby​​的路径?谢谢! 最佳答案 我创建了一个emacs扩展来将rvm集成到emacs中。如果您有兴趣,可以在这里获取:http://github.com/senny/rvm.el

  7. ruby-on-rails - 事件管理员日期过滤器日期格式自定义 - 2

    是否有简单的方法来更改默认ISO格式(yyyy-mm-dd)的ActiveAdmin日期过滤器显示格式? 最佳答案 您可以像这样为日期选择器提供额外的选项,而不是覆盖js:=f.input:my_date,as::datepicker,datepicker_options:{dateFormat:"mm/dd/yy"} 关于ruby-on-rails-事件管理员日期过滤器日期格式自定义,我们在StackOverflow上找到一个类似的问题: https://s

  8. 叮咚买菜基于 Apache Doris 统一 OLAP 引擎的应用实践 - 2

    导读:随着叮咚买菜业务的发展,不同的业务场景对数据分析提出了不同的需求,他们希望引入一款实时OLAP数据库,构建一个灵活的多维实时查询和分析的平台,统一数据的接入和查询方案,解决各业务线对数据高效实时查询和精细化运营的需求。经过调研选型,最终引入ApacheDoris作为最终的OLAP分析引擎,Doris作为核心的OLAP引擎支持复杂地分析操作、提供多维的数据视图,在叮咚买菜数十个业务场景中广泛应用。作者|叮咚买菜资深数据工程师韩青叮咚买菜创立于2017年5月,是一家专注美好食物的创业公司。叮咚买菜专注吃的事业,为满足更多人“想吃什么”而努力,通过美好食材的供应、美好滋味的开发以及美食品牌的孵

  9. ruby - 使用 `+=` 和 `send` 方法 - 2

    如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:

  10. ruby - 如何让Ruby捕获线程中的语法错误 - 2

    我正在尝试使用ruby​​编写一个双线程客户端,一个线程从套接字读取数据并将其打印出来,另一个线程读取本地数据并将其发送到远程服务器。我发现的问题是Ruby似乎无法捕获线程内的错误,这是一个示例:#!/usr/bin/rubyThread.new{loop{$stdout.puts"hi"abc.putsefsleep1}}loop{sleep1}显然,如果我在线程外键入abc.putsef,代码将永远不会运行,因为Ruby将报告“undefinedvariableabc”。但是,如果它在一个线程内,则没有错误报告。我的问题是,如何让Ruby捕获这样的错误?或者至少,报告线程中的错误?

随机推荐