跨标准实现工作的互斥体

时间:2019-06-23 22:03:36

标签: c++ mutex

this question相关,我需要一个可在std实现中使用的互斥量,或者是一种原子写入和读取指针的方法。用mingw-w64编译的代码产生一个线程,而另一个是静态/动态库中的Visual Studio 2019代码。

2 个答案:

答案 0 :(得分:1)

从主可执行文件(mingw-w64)导出到DLL(VC ++)-用单独的编译器进行编译-同步/互斥对象“句柄”(通常是不透明的指针,尽管它也可以成为某些内容的索引)并且一对C样式的函数(如果需要,您可以将它们包装到std::mutexstd::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 ++接口继承的简单情况,然后将其包装在类和模板中,以使用户不会注意到。