草庐IT

C++ std lib <mutex>, <conditional_variable> 库和共享内存

coder 2024-02-21 原文

如果您想在共享内存中的进程之间共享互斥体,POSIX 线程的 C API 需要设置一个特殊标志 - 请参阅 sem_init()。我真的不知道差异是什么,但我在尝试在共享内存中使用 C++ std::condition_variable 时遇到了问题——它的段错误。我在 C++ 文档或构造函数中看不到任何提及此内容的内容。我想知道如何/是否可以在共享内存中使用 C++ 线程互斥锁。这是我的测试代码供引用。注意 squeue 只是一个简单的 (POD) 静态大小的循环队列,省略了不相关的内容:

#include <iostream>
#include <sys/mman.h>
#include <sys/stat.h>        /* For mode constants */
#include <fcntl.h>           /* For O_* constants */
#include "squeue.h"
#define SHM_FILENAME "/shimmy-foo"
#define SQUEUE_LENGTH 10

typedef struct {
        squeue<int,SQUEUE_LENGTH> queue;
        std::mutex mutex;
        std::condition_variable_any condvar;
} SHM;

int main() {
        int shm_fd = 0;
        SHM * shm_ptr = NULL;
        squeue<int,SQUEUE_LENGTH> * queue = NULL;
        std::mutex * mutex;
        std::condition_variable_any * condvar;

        // Init SHM. ftruncate() will zero area.
        if((shm_fd = shm_open(SHM_FILENAME, O_CREAT|O_RDWR|O_EXCL, S_IREAD|S_IWRITE)) == -1 ) {
            fprintf (stderr, "Could not open shm object. %s\n", strerror(errno));
            return errno;
        }
        else {
            fprintf (stderr, "Open shm OK. %d\n", shm_fd);
        }
        ftruncate(shm_fd, sizeof(SHM));

        // Connect the shmptr pointer to set to the shared memory area,
        // with desired permissions
        if((shm_ptr = (SHM*)mmap(0, sizeof(SHM), PROT_READ|PROT_WRITE, MAP_SHARED, shm_fd, 0)) == MAP_FAILED) {
            fprintf (stderr, "Could not map shm. %s\n", strerror(errno));
            return errno;
        }
        else {
        fprintf(stderr, "Mapped shm OK. %p\n", shm_ptr);
        }

        // Create queue and mutex.
        queue = new(&shm_ptr->queue) squeue<int,SQUEUE_LENGTH>();
        mutex = new(&shm_ptr->mutex) std::mutex();
        condvar = new(&shm_ptr->condvar) std::condition_variable_any();

        srand(time(NULL));
        while(true) {
            cout << "Waiting on lock" << endl;
            mutex->lock();
            if(!queue->full()) {
                int value = rand()%100;
                queue->push(value);
                cout << "Pushed " << value << endl;
            } else {
                cout << "Que is full!" << endl;
            };
            condvar->notify_all(); //Seg fault.
            mutex->unlock();
            sleep(1);
        }
    }

最佳答案

我使用了类似的模式,但是,标准互斥锁和条件变量并非设计为在进程之间共享。原因是 POSIX 需要在进程共享互斥锁和条件变量上设置 PTHREAD_PROCESS_SHARED 属性,但标准 C++ 原语不这样做。在 Windows 上,它可能比这更复杂。

您可以尝试使用 boost process shared mutexesprocess shared condition variables反而。或者为 POSIX 接口(interface)创建您自己的包装器。


也可能是 squeue 破坏了缓冲区以外的内存,覆盖了 struct SHM 内存中的互斥锁和条件变量。我会尝试注释掉推送到队列中的代码,看看您是否仍然遇到崩溃。我在注释掉队列代码的情况下尝试了您的代码,它按预期工作。


您可能还喜欢使用 condition_variable 而不是 condition_variable_any,因为后者维护自己的互斥锁,但如果您在通知条件变量的同时通知该条件变量,则不需要该互斥锁关联的互斥量已锁定(就像您所做的那样)。

关于C++ std lib <mutex>, <conditional_variable> 库和共享内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24360477/

有关C++ std lib <mutex>, <conditional_variable> 库和共享内存的更多相关文章

  1. ruby-on-rails - 如何从 format.xml 中删除 <hash></hash> - 2

    我有一个对象has_many应呈现为xml的子对象。这不是问题。我的问题是我创建了一个Hash包含此数据,就像解析器需要它一样。但是rails自动将整个文件包含在.........我需要摆脱type="array"和我该如何处理?我没有在文档中找到任何内容。 最佳答案 我遇到了同样的问题;这是我的XML:我在用这个:entries.to_xml将散列数据转换为XML,但这会将条目的数据包装到中所以我修改了:entries.to_xml(root:"Contacts")但这仍然将转换后的XML包装在“联系人”中,将我的XML代码修改为

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

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

  3. ruby-on-rails - 如何使用 instance_variable_set 正确设置实例变量? - 2

    我正在查看instance_variable_set的文档并看到给出的示例代码是这样做的:obj.instance_variable_set(:@instnc_var,"valuefortheinstancevariable")然后允许您在类的任何实例方法中以@instnc_var的形式访问该变量。我想知道为什么在@instnc_var之前需要一个冒号:。冒号有什么作用? 最佳答案 我的第一直觉是告诉你不要使用instance_variable_set除非你真的知道你用它做什么。它本质上是一种元编程工具或绕过实例变量可见性的黑客攻击

  4. ruby - 通过 ruby​​ 进程共享变量 - 2

    我正在编写一个gem,我必须在其中fork两个启动两个webrick服务器的进程。我想通过基类的类方法启动这个服务器,因为应该只有这两个服务器在运行,而不是多个。在运行时,我想调用这两个服务器上的一些方法来更改变量。我的问题是,我无法通过基类的类方法访问fork的实例变量。此外,我不能在我的基类中使用线程,因为在幕后我正在使用另一个不是线程安全的库。所以我必须将每个服务器派生到它自己的进程。我用类变量试过了,比如@@server。但是当我试图通过基类访问这个变量时,它是nil。我读到在Ruby中不可能在分支之间共享类变量,对吗?那么,还有其他解决办法吗?我考虑过使用单例,但我不确定这是

  5. ruby-on-rails - rspec should have_select ('cars' , :options => ['volvo' , 'saab' ] 不工作 - 2

    关闭。这个问题需要detailsorclarity.它目前不接受答案。想改进这个问题吗?通过editingthispost添加细节并澄清问题.关闭8年前。Improvethisquestion在首页我有:汽车:VolvoSaabMercedesAudistatic_pages_spec.rb中的测试代码:it"shouldhavetherightselect"dovisithome_pathit{shouldhave_select('cars',:options=>['volvo','saab','mercedes','audi'])}end响应是rspec./spec/request

  6. ruby-on-rails - Nokogiri:使用 XPath 搜索 <div> - 2

    我使用Nokogiri(Rubygem)css搜索寻找某些在我的html里面。看起来Nokogiri的css搜索不喜欢正则表达式。我想切换到Nokogiri的xpath搜索,因为这似乎支持搜索字符串中的正则表达式。如何在xpath搜索中实现下面提到的(伪)css搜索?require'rubygems'require'nokogiri'value=Nokogiri::HTML.parse(ABBlaCD3"HTML_END#my_blockisgivenmy_bl="1"#my_eqcorrespondstothisregexmy_eq="\/[0-9]+\/"#FIXMEThefoll

  7. 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.你能做的最好的事情是:

  8. ruby - 如何计算 Liquid 中的变量 +1 - 2

    我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我

  9. ruby-on-rails - 没有参数的 `<<`(小于两倍)是什么意思? - 2

    我在一个我想在formtasticGem中覆盖的方法中找到了这个。该方法如下所示:defto_htmlinput_wrappingdohidden_field_html是什么意思?在第三行做什么?我知道它对数组有什么作用,但在这里我不知道。 最佳答案 你可以这样读:hidden_field_htmllabel_with_nested_checkbox是连接到hidden_​​field_html末尾的参数-为了“清晰”,他们将其分成两行 关于ruby-on-rails-没有参数的`

  10. ruby-on-rails - 找不到 gem railties (>= 0.a) (Gem::GemNotFoundException) - 2

    我已经看到了一些其他的问题,尝试了他们的建议,但没有一个对我有用。我已经使用Rails大约一年了,刚刚开始一个新的Rails项目,突然遇到了问题。我卸载并尝试重新安装所有Ruby和Rails。Ruby很好,但Rails不行。当我输入railss时,我得到了can'tfindgemrailties。我当前的Ruby版本是ruby2.2.2p95(2015-04-13修订版50295)[x86_64-darwin15],尽管我一直在尝试通过rbenv设置ruby​​2.3.0。如果我尝试rails-v查看我正在运行的版本,我会得到同样的错误。我使用的是MacOSXElCapitan版本10

随机推荐