c++ - 如何在多线程 MEX 函数中打印到控制台?

标签 c++ multithreading matlab boost mex

我正在编写一个使用 Boost 库的简单生产者消费者 MEX 函数。我已经成功地让以下程序正常运行。

#include "mex.h"
#include <boost/thread/thread.hpp>
#include <boost/lockfree/spsc_queue.hpp>
#include <iostream>
#include <boost/atomic.hpp>

int producer_count = 0;
boost::atomic_int consumer_count (0);
boost::lockfree::spsc_queue<int, boost::lockfree::capacity<1024> > spsc_queue;
const int iterations = 10000000;

void producer()
{
    for (int i = 0; i != iterations; ++i) {
        int value = ++producer_count;
        while (!spsc_queue.push(value));
    }
}

boost::atomic<bool> done (false);

void consumer()
{
    int value;
    while (!done) {
        while (spsc_queue.pop(value))
            ++consumer_count;
    }

    while (spsc_queue.pop(value))
        ++consumer_count;
}

void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
    if (!spsc_queue.is_lock_free())
    {
      mexPrintf("boost::lockfree::queue is not lockfree\n");
      mexEvalString("drawnow;");
    }
    else
    {
      mexPrintf("boost::lockfree::queue is lockfree\n");
      mexEvalString("drawnow;");
    }

    boost::thread producer_thread(producer);
    boost::thread consumer_thread(consumer);

    producer_thread.join();
    done = true;
    consumer_thread.join();

    cout << "produced " << producer_count << " objects." << endl;
    cout << "consumed " << consumer_count << " objects." << endl;
}

最大的问题是我尝试将 mexPrintf() 包含到生产者或消费者方法中,MATLAB 只是崩溃了。经过一些调查后我发现 this post这解释了这种情况是由于竞争条件而发生的。有谁知道我该如何解决这个问题?我阅读了有关 Mutex 的答案,但我不明白如何实现这样的功能。

最佳答案

您无法调用mexPrintf来自除主线程之外的任何线程。互斥锁不能解决您的问题。

来自MATLAB documentation :

MEX API Is Not Thread Safe

Do not call a single session of MATLAB® on separate threads from a MEX file. The MEX and Matrix Library APIs are not multi-threaded.

You can create threads from a C MEX file; however, accessing MATLAB from those threads is not supported. Do not call any MEX API functions from the spawned threads, including printf, which is defined as mexPrintf in the mex.h header file.

如果您确实需要从这些线程生成输出,请考虑实现一个简单的消息传递系统,其中线程发布一条消息,其中包含要输出的文本和主线程,而不是等待 producer_thread.join(); ,坐在循环中寻找要打印的消息,并使用 mexPrintf 打印它们。 .


下面的代码未经测试。它甚至还没有被编译。将其视为伪代码。我认为这是解决方案的合理尝试,但可能还有更好的方法。继续,风险自负。 :)

boost::lockfree::queue<std::string> message_queue;

void producer() {
    //...
    message_queue.push("A string to print!");
    //...
}

void mexFunction( /*...*/ ) {
    // ...
    boost::thread producer_thread(producer);
    boost::thread consumer_thread(consumer);
    while(producer_thread.joinable()) {
        join_for(boost::chrono::milliseconds(50));
        std::string s;
        while (message_queue.pop(s)) {
            mexPrintf("%s\n", s.c_str());
        }
    }
    producer_thread.join();
    done = true;
    consumer_thread.join();
    // ...
}

关于c++ - 如何在多线程 MEX 函数中打印到控制台?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54010898/

相关文章:

matlab - MATLAB:audioplayer()

c++ - TFS 2013 构建如何使工作区文件可编辑?

c++ - Brace-init-list 和赋值

c++ - 抛出导致调用析构函数的异常会使程序崩溃

c++ - QThread不会退出

java - Executor 关闭后 ScheduledFuture.get() 仍然被阻塞

java - 什么时候应该实现 Runnable?

c++ - Hadoop流C++ getTaskId

matlab - 在 MATLAB 中摆脱 for 绘图 for 循环的最佳方法

matlab - Matlab 中的多元随机数生成