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我认为,它更像是一种成语而不是一种模式).
我在哪里可以查找更多信息?
你可以做一个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::function而std::bind不是使用boost等效项.
在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)