类似于嵌套互斥锁,但更通用
Something like a nested mutex but more generic?
我正在研究一个项目,其中必须在对类的成员对象执行某些操作后保存文件。有时我们希望在一次操作后保存文件,有时我们需要在执行了一批操作后才保存文件。
我的想法是使用一个类,它基本上像递归互斥锁一样工作。除了不锁定和解锁互斥锁外,我希望当类在堆栈中的最后一个实例超出作用域时,类调用一个方法(在本例中是保存文件)。
实现这样做的类不是问题,但这感觉像是一个通用问题,我只是在Boost或STL中找不到。对于这个问题是否存在预先存在的标准解决方案,或者我是否需要滚动我自己的类来完成它?如果是这样,我的方法是正确的,还是有更好的方法来解决问题?
下面是我正在寻找的行为的简单实现。即使DoItOnce()被调用了11次,它也只会打印两次"Hello World!"我想使用像GenericGuard
这样的东西,通过从公认的标准中提取它,而不是在代码库中粘贴我自己的实现。这可能吗?
#include <iostream>
void Noop (void) { }
void HelloWorld (void) { std::cout << "Hello World!" << std::endl; }
// This is what I imagine a generic implementation would look like...
template <void (*InitFunc)(), void (*DestructFunc)()>
class GenericGuard
{
int & _i;
public:
GenericGuard (int & i) : _i(i) { if (_i++ == 0) { InitFunc(); } }
~GenericGuard () { if (--_i == 0) { DestructFunc(); } }
};
int HelloWorldCounter; // Use a factory class in real-world?
typedef GenericGuard<Noop, HelloWorld> HelloWorldGuard;
void DoSomethingOnce (void)
{
HelloWorldGuard G (HelloWorldCounter);
// Do something
}
void DoItTenTimes (void)
{
HelloWorldGuard G (HelloWorldCounter);
for (int i = 0; i < 10; ++i)
{
DoSomethingOnce();
}
}
int main (void)
{
DoSomethingOnce();
DoItTenTimes();
return 0;
}
您可以使用带有自定义删除函数的shared_ptr
。
- STL (c++11起):http://en.cppreference.com/w/cpp/memory/shared_ptr/shared_ptr
- 增加:http://www.boost.org/doc/libs/1_55_0/libs/smart_ptr/shared_ptr.htm deleter_constructor
的例子:
#include <memory>
#include <iostream>
void HelloWorld(void *) { std::cout << "Hello World!" << std::endl; }
class factory
{
public:
static std::shared_ptr<void> get_instance()
{
static std::weak_ptr<void> ref;
if (ref.expired())
{
std::shared_ptr<void> sp{nullptr, HelloWorld};
ref = sp;
return sp;
}
return ref.lock();
}
};
void DoSomethingOnce (void)
{
std::shared_ptr<void> G = factory::get_instance();
// Do something
}
void DoItTenTimes (void)
{
std::shared_ptr<void> G = factory::get_instance();
for (int i = 0; i < 10; ++i)
{
DoSomethingOnce();
}
}
int main(void)
{
DoSomethingOnce();
DoItTenTimes();
return 0;
}
您所追求的模式似乎是众所周知的:您正在寻找事务中的组操作[1]。
我想到的相关模式是
-
命令模式(带有著名的Do/Undo示例)
- 复合模式(所以你可以有一个命令,组成几个其他命令,形成一个树);
-
工作单位模式;这可以让你将未决编辑分组,并将它们应用为一个组
-
软件事务性内存(关注操作的真正原子性,例如异常安全)
不,我不是模式的坚定倡导者,但我喜欢它给你谈论事物的概念:所以,你真正想要的是工作单元(它可以像分组命令一样简单),你想要一个"事务",在破坏时自动应用更改。
根据您的实际应用程序,坚持使用您现在使用的可变对象方法,只是偶尔序列化它可能是好的。如果应用程序领域变得稍微有趣一些(例如,使用线程、撤销和/或版本控制?),您很快就会发现,当您转移到文档模型(对不可变节点的引用图)时,生活会变得更加简单。这允许您通过简单地替换节点来廉价地"编辑"复杂的对象图。节点是不可变的,即使在线程环境中,共享它们也是安全的。
我认为与你的问题有关的是Sean Parent的调味c++ 谈话。虽然这篇文章关注的是如何组织文档模型,但我觉得它可能非常有见地,可能会给您带来观点上的"突破性"变化,使问题再次变得简单。
[1]在这个上下文中根本不需要是原子的,尽管它们可能(需要)在您的应用程序域中
- 嵌套在类中时无法设置成员数据
- 无法访问嵌套类.类的使用无效
- 我正在使用嵌套的while循环来解析具有多行的文本文件,但由于某种原因,它只通过第一行,我不知道为什么
- 如何在C++中初始化嵌套类中的2个memeber
- 如何声明特征矩阵,然后通过嵌套循环初始化它
- 在C++中搜索嵌套多映射值
- 在C++中将矢量转换为嵌套地图
- C++嵌套if语句,基本货币交换
- 类似于strcat()的函数出现问题
- 在nlohmann json中,如何将嵌套对象的数组转换为嵌套结构的向量
- 嵌套的匿名命名空间
- 了解嵌套循环打印星号图案
- 为什么 OpenCL 嵌套循环仅适用于某些元素
- rxcpp:嵌套的 while 循环或类似的程序命令式结构"classic"
- 如何让代码存在于两个或多个非嵌套命名空间的范围内
- 嵌套在模板化类中的类的大小,但不依赖于模板参数
- 类型严格依赖于另一个(嵌套类)语法
- C++:特定于友元的对象(嵌套类)
- 类似于嵌套互斥锁,但更通用
- C++:不应用于简单嵌套if-then-else语句的条件