从可锁定容器的DLL接口隐藏Boost::互斥

Hide Boost::mutex from DLL Interface from lockable Container

本文关键字:接口 隐藏 Boost DLL 互斥 锁定      更新时间:2023-10-16

我一直在DLL项目中使用Boost,但没有导出任何Boost依赖项。。。然而只是C类型和从DLL源代码树本身派生的东西。

但现在我正在为一个可锁定的数据模型而挣扎。。。我无法使其设计为异常安全,并且不直接将boost类型导出到DLL接口。

struct DLL_EXPORT DllTestData {
    double test1;
    double test2;
    void lock();
    void unlock();
    DllTestDataLock getGuard();
    boost::mutex;
}

并使用它:

DllTestData ptr;
ptr->lock();
ptr->test1 = 1.0;
ptr->unlock(); 

至少可以设计某种DllTestData::Pimpl,并对Dll隐藏互斥类型。但如果我想这样使用它:

DllTestData ptr;
{
    auto g = ptr->getGuard();
    ptr->test1 = 1.0;
}

在写这篇文章的时候,我开始考虑ILockable-接口,并将互斥对象类型隐藏在PImpl或某种类型中,所以类似于这样的东西:

struct ILockable {
    void lock() = 0;
    void unlock() = 0;
}
struct DLL_EXPORT DllTestData : public struct ILockable {
    /// ...
private:
    class PImpl;
    Pimpl * impl;
}
struct Guard {
    Guard( ILockable * ptr ) {
        ptr->lock();
    }
    ~Guard() {
        ptr->unlock();
    }
}

并像这样使用:

DllTestData ptr = fromDll();
{
    Guard g(ptr);
    ptr->test1 = 1.0;
}

这是一种有效的方法吗(用皮条隐藏互斥类型,并使用Lockable接口),还是我走错了方向?或者,在这种情况下,什么更有效?也许将整个boost::mutex PImpl移到Interface?

是的,在我看来,你走在了正确的轨道上。但您的struct太"重"了,所以您应该将其导出为一个具有值的get和set方法的接口,而不是值本身。如果你使用工厂模式,一个用于创建对象的函数和一个用于删除的函数,你可以安全地从dll内的接口中提取,甚至不会暴露出讨厌的Pimpl*impl。

再看一遍,您可以完全避免暴露互斥对象。例如,如果同时只设置两个值,则暴露

void setValues(double test1,double test2);

在methode中,您可以自己设置互斥对象。或者更经典的Win32方法,如果你不想要一个大的获取和设置列表:公开一个没有任何方法的结构,如:

struct DLLTestData
{
double test1;
double test2;
// …and as many as you want 
};

并为您的导出添加一个函数或方法,如

void setTestData(DLLTestData value);

在库中,您可以锁定并记住整个结构。如前所述,在大量使用Win32 API的过程中,我已经习惯了第二种方法,但我个人更喜欢第一种方法,即使用接口和get/settier,即使这需要更多的精力。