像嵌套互斥​​体但更通用的东西?

时间:2014-06-24 14:34:21

标签: c++ boost stl

我正在开发一个项目,在对类的成员对象执行某些操作后必须保存文件。有时我们想在一次操作后保存文件,有时我们需要在执行一批操作之后才保存它。

我的想法是使用一个基本上像递归互斥体一样工作的类。除了锁定和解锁互斥锁之外,我希望类在堆栈中最后一个类的实例超出范围时调用方法(在这种情况下,保存文件)。

实现一个执行此操作的类不是问题,但这感觉就像我在Boost或STL中找不到的一般问题。是否有预先存在的标准解决方案来解决这个问题,或者我是否需要自己的类来完成它?如果是这样,我的方法是正确的,还是有更好的方法来解决问题?

以下是我正在寻找的行为的简单实现。它只会打印“Hello World!”即使DoItOnce()被调用了11次也是两次。我希望使用像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;
}

2 个答案:

答案 0 :(得分:3)

您可以将shared_ptr与自定义删除功能结合使用。

示例:

#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 :(得分:0)

您之后的模式似乎确实是众所周知的:您正在寻找交易 [1] 中的分组操作。

我脑海中出现的相关模式是

  • 命令模式(使用着名的Do / Undo示例)

    • 复合模式(所以你可以有一个命令组成其他几个命令,形成一棵树);
  • 工作单位模式;这使您可以对待处理的编辑进行分组并将其作为一个组应用

  • 软件事务内存(专注于操作的真实原子性,例如异常安全)。

不,我不是一个坚定的模式倡导者,但我喜欢它让你谈论事物的概念:所以,你真正想要的是工作单位(可能是简单的分组命令),你想要一个&#34;交易&#34;在破坏时自动应用更改。


根据您的实际应用,可能会坚持使用您现在看到的可变对象方法,并偶尔序列化它。如果应用程序域变得稍微有点兴趣(例如,使用线程,撤消和/或版本控制?),当您移动到文档模型时,您会很快发现生活变得更加简单 不可变节点。这样可以便宜地编辑&#34;简单地替换节点就是一个复杂的对象图。即使在线程环境中,不可变的节点也可以安全地共享它们。

与您的问题相关的认为是Sean Parent的Seasoning C++ talk。虽然这侧重于如何组织您的文档模型,但我觉得它可能非常有见地,并且可能会给您带来突破性的#34;改变观点以使问题再次变得简单。


[1] 在这种情况下根本不需要是原子的,尽管它们可能(需要)在您的应用程序域中。