与this question相关,我需要一个可在std
实现中使用的互斥量,或者是一种原子写入和读取指针的方法。用mingw-w64编译的代码产生一个线程,而另一个是静态/动态库中的Visual Studio 2019代码。
答案 0 :(得分:1)
从主可执行文件(mingw-w64)导出到DLL(VC ++)-用单独的编译器进行编译-同步/互斥对象“句柄”(通常是不透明的指针,尽管它也可以成为某些内容的索引)并且一对C样式的函数(如果需要,您可以将它们包装到std::mutex
和std::lock
之类的类中,公开相同的API-这是最安全的做法),将其锁定和解锁抓住那把柄。它们可能就这样裸露,或者它们可能包含超时或尝试锁定等其他功能-这些功能非常有用,但不是必需的。您还可以导出handle_t create()
和void delete(handle_t handle)
函数。
重点是,同步对象本身(互斥体或其他对象)始终由那些间接函数来操作以避免使用错误,并且这些函数取决于编译器(可以容易地由预处理器检测到),由特定于编译器的原子操作内部函数或CRT函数提供支持,例如完全合适的InterlockedCompareExchange
(它也可以在mingw-w64下运行)及其特定于Visual C ++的compiler intrinsic variant或GCC的__atomic
(更多信息)具体来说,__atomic_compare_exchange
。
答案 1 :(得分:1)
struct imutex {
virtual void lock() = 0;
virtual void unlock() = 0;
virtual ~imutex(){}
};
template<class M>
struct imp_mutex: imutex {
M m;
void lock() final override { m.lock(); }
void unlock() final override { m.unlock(); }
};
struct mymutex {
using up=std::unique_ptr<imutex, void(*)(imutex*)>;
mymutex( up m_in ):m(std::move(m_in)){}
mymutex():mymutex(up(new imp_mutex<std::mutex>{}, [](imutex* m){ delete m; })) {}
void lock(){ m->lock(); }
void unlock(){ m->unlock(); }
mymutex(mymutex&&)=delete;
private:
up m;
};
这假定vtables和std :: unique_ptr具有ABI兼容性,这很合理。
否则,请使用自定义变量替换唯一的ptr,并使用带有空指针的函数指针替换虚拟方法。
关键是,互斥锁是在一个库的代码中创建和销毁的。
这里是一个纯函数指针。它依赖于包含两个ptrs的结构具有相同的布局,并且C调用约定是相同的。
使用哪个库制作mymutex,然后两者都可以使用它。
struct imutex_vtable {
void (*lock)(void*) = 0;
void (*unlock)(void*) = 0;
void (*dtor)(void*)=0;
};
template<class M>
imutex_vtable const* get_imutex_vtable(){
static const imutex_vtable vtable = {
[](void* m){ static_cast<M*>(m)->lock(); },
[](void* m){ static_cast<M*>(m)->unlock(); },
[](void* m){ delete static_cast<M*>(m); }
};
return &vtable;
}
struct mymutex {
mymutex( imutex_vtable const* vt, void* pm ):vtable(vt), pv(pm){}
template<class M>
explicit mymutex(std::unique_ptr<M> m):mymutex( get_imutex_vtable<M>(), m.release() ) {}
mymutex():mymutex(std::make_unique<std::mutex>()) {}
void lock(){ vtable->lock(pv); }
void unlock(){ vtable->unlock(pv); }
~mymutex(){ vtable->dtor(pv); }
mymutex(mymutex&&)=delete;
private:
imutex_vtable const* vtable=0;
void* pv=0;
};
这基本上是使用类似于C的实现来实现C ++接口继承的简单情况,然后将其包装在类和模板中,以使用户不会注意到。