轻量级包装 - 这是一个常见问题,如果是,它的名字是什么?

for*_*idt 13 c++ design-patterns locking idioms wrapper

我必须使用一个库来进行非线程安全的数据库调用.另外,我偶尔也需要在后台线程中加载大量数据.
很难说哪些库函数实际访问了数据库,因此我认为对我来说最安全的方法是用锁来保护每个库调用.

假设我有一个库对象:

dbLib::SomeObject someObject;
Run Code Online (Sandbox Code Playgroud)

现在我可以这样做:

dbLib::ErrorCode errorCode = 0;
std::list<dbLib::Item> items;
{
    DbLock dbLock;
    errorCode = someObject.someFunction(&items);
} // dbLock goes out of scope
Run Code Online (Sandbox Code Playgroud)

我想将其简化为类似的东西(甚至更简单):

dbLib::ErrorCode errorCode =
    protectedCall(someObject, &dbLib::SomeObject::someFunction(&items));
Run Code Online (Sandbox Code Playgroud)

这样做的主要优点是我不必复制接口,dbLib::SomeObject以便用锁来保护每个呼叫.

我很确定这是一个常见的模式/习语,但我不知道它的名字或搜索的关键词.(看看http://www.vincehuston.org/dp/gof_intents.html我认为,它更像是一种成语而不是一种模式).

我在哪里可以查找更多信息?

rek*_*o_t 8

你可以做一个protectedCall模板函数,它不带参数(这意味着你会在绑定的调用点的参数)一个仿函数,然后创建一个范围的锁,来电函子,并返回其值.例如:

template <typename Ret>
Ret protectedCall(boost::function<Ret ()> func)
{
    DbLock lock;
    return func();
}
Run Code Online (Sandbox Code Playgroud)

然后你会这样称呼它:

dbLib::ErrorCode errorCode = protectedCall(boost::bind(&dbLib::SomeObject::someFunction, &items));
Run Code Online (Sandbox Code Playgroud)

编辑.如果您使用的是C++ 0x,则可以使用std::functionstd::bind不是使用boost等效项.

  • 或者只是在C++ 0x的情况下使用lambdas. (3认同)

Ale*_* C. 5

在C++ 0x中,您可以实现某种形式的装饰器:

template <typename F>
auto protect(F&& f) -> decltype(f())
{
    DbLock lock;
    return f();
}
Run Code Online (Sandbox Code Playgroud)

用法:

dbLib::ErrorCode errorCode = protect([&]() 
{
    return someObject.someFunction(&items); 
});
Run Code Online (Sandbox Code Playgroud)