我正在为本机C ++库编写C ++ / CLI包装器。在其中一个返回给CLI包装器的类中,使用线程,特别是标题中的#include <mutex>
来定义类级别的互斥锁。
问题是一旦头文件被带入CLI代码(启用了/ clr选项),我在使用/ clr或/clr:pure编译时遇到错误<mutex>
}。 p>
阅读这篇文章How to implement a unmanaged thread-safe collection when I get this error: <mutex> is not supported when compiling with /clr,有一篇博客文章提到了一些可能的解决方法。但是,解决方法假设您不需要任何导致冲突的头文件,并且所有头文件都可以在类函数中完成,实质上是从CLI应用程序中隐藏线程函数。
对于类级别的互斥锁,情况并非如此。它必须在标题中。
有没有办法让CLI应用程序与带有线程的本机库一起工作?
是的,我知道托管代码和非托管代码之间存在GetCurrentThreadID()问题,但正确的方法是什么?或者没有办法绕过它?
我不得不加入像ZMQ这样的东西,因为这是一个关键的部分,现在有三个数据副本(可能非常大)将是令人望而却步的。 (一个在托管端,一个在本机上,一个在ZMQ中通过消息缓冲区)。我知道ZMQ的零拷贝,但是没有尝试在托管和非托管c ++之间使用inproc来查看是否可以共享内存。如果可能的话,可能需要在整个应用程序中使用低级别的连续数据结构,否则会再次复制数据。
有没有像样的解决方案?
答案 0 :(得分:1)
解决方案是使用#ifdef在CLI代码中有选择地隐藏.h文件中的互斥体声明,但仍在cpp本机代码中对其进行编译。
nativeClass.h文件:
#ifdef NATIVE_CODE
#include <mutex>
#endif
class naticeClass {
public:
void doSomething();
private:
#ifdef NATIVE_CODE
mutex _mutex;
#endif
};
在nativeClass.cpp中:
#define NATIVE_CODE
#include "nativeClass.h"
void nativeClass:doSomething()
{
_mutex.lock();
...
}
答案 1 :(得分:0)
我之前为std :: thread研究了这个问题,我发现以下内容正在发挥作用。由于CLR不允许您在编译时包含std::thead
,因此您可以尝试仅在链接时使用它。通常你可以解决这个问题,在你的标题中声明类,并将它们仅包含在你的cpp文件中。但是,可以转发在头文件中声明自己的类,但不能用于命名空间std中的类。根据C ++ 11标准,17.6.4.2.1:
如果添加声明或者C ++程序的行为是未定义的 命名空间std或命名空间std中的命名空间的定义 除非另有说明。
此问题的解决方法是创建一个继承自{strong>可以向前声明的std::thread
的线程类。此类的头文件如下所示:
#pragma once
#include <thread>
#include <utility>
namespace Threading
{
class Thread : std::thread
{
public:
template<class _Fn, class... _Args> Thread(_Fn fn, _Args... args) : std::thread(fn, std::forward<_Args...>(args...))
{
}
private:
};
}
在您想要使用该主题的头文件中,您可以将其声明为:
#pragma once
// Forward declare the thread class
namespace Threading { class Thread; }
class ExampleClass
{
public:
ExampleClass();
void ThreadMethod();
private:
Threading::Thread * _thread;
};
在源文件中,您可以使用theading类,如:
#include "ExampleClass.h"
#include "Thread.h"
ExampleClass::ExampleClass() :
{
_thread = new Threading::Thread(&ExampleClass::ThreadMethod, this);
}
void ExampleClass::ThreadMethod()
{
}
你应该可以为std :: mutex做同样的事情。希望它可以帮助任何人。
答案 2 :(得分:0)
这就是我解决此问题的方法-通过创建自卷式Mutex。由于等待时间太长,我对解决方案并不感到高兴,但它似乎很好用。我只需要保护对std :: vector的多线程访问。
in .h file:
std::atomic<int> vectorLock = 0;
in .cpp file:
while (vectorLock.exchange(1) == 1) {}
... critical code goes here
vectorLock = 0;