简体   繁体   English

有哪些 C++ 替代 static 对象可以使销毁更安全(或更具确定性)?

[英]What are some C++ alternatives to static objects that could make destruction safer (or more deterministic)?

I'm working on a large code base that, for performance reasons, limits access to one or more resources.我正在处理一个大型代码库,出于性能原因,它限制了对一个或多个资源的访问。 A thread pool is a good analogy to my problem - we don't want everyone in the process spinning up their own threads, so a common pool with a producer/consumer job queue exists in an attempt to limit the number of threads running at any given time.线程池是我的问题的一个很好的类比——我们不希望进程中的每个人都启动自己的线程,因此存在一个带有生产者/消费者作业队列的公共池,以试图限制在任何时候运行的线程数量给定的时间。

There isn't an elegant way to make ownership of the thread pool clear so, for all intents and purposes, it is a singleton. I speak better in code than in English, so here is an example:没有一种优雅的方式来明确线程池的所有权,因此,出于所有意图和目的,它是一个 singleton。我说代码比英语好,所以这里有一个例子:

class ThreadPool {
public:
  static void SubmitTask(Task&& t) { instance_.SubmitTask(std::move(t)); }

private:
  ~ThreadPool() {
    std::for_each(pool_.begin(), pool_.end(), [](auto &t) {
      if (t.joinable()) t.join();
    });
  }

private:
  std::array<std::thread, 5> pool_;
  static ThreadPool instance_; // here or anonymous namespace
};

The issue with this pattern is instance_ doesn't go out of scope until after main has returned which typically results in races or crashes.此模式的问题是instance_在 main 返回之前不会从 scope 中取出 go,这通常会导致竞争或崩溃。 Also, keep in mind this is analogous to my problem so better ways to do something asynchronously isn't really what I'm after;另外,请记住这类似于我的问题,所以更好的异步方式并不是我真正想要的; just better ways to manage the lifecycle of static objects.只是管理 static 对象生命周期的更好方法。

Alternatives I've thought of:我想到的替代方案:

  1. Provide an explicit Terminate function that must be called manually before leaving main.提供一个明确的Terminate function,必须在离开 main 之前手动调用。
  2. Not using statics at all and leaving it up to the app to ensure only a single instance exists.根本不使用静态并将其留给应用程序以确保只存在一个实例。
  3. Not using statics at all and crashing the app if more than 1 instance is instantiated.如果实例化超过 1 个实例,则根本不使用静态并使应用程序崩溃。

I also realize that a small, sharp, team could probably make the above code work just fine.我还意识到,一个小而敏锐的团队可能会让上面的代码工作得很好。 However, this code lives within a large organization that has many developers of various skill levels contributing to it.但是,此代码存在于一个大型组织中,该组织拥有许多不同技能水平的开发人员为其做出贡献。

You could explicitly bind the lifetime to your main function. Either add a static shutdown() method to your ThreadPool that does any cleanup you need and call it at the end of main() .您可以将生命周期显式绑定到您的主 function。要么将 static shutdown()方法添加到您的ThreadPool以执行您需要的任何清理,并在main()结束时调用它。

Or fully bind the lifetime via RAII:或者通过 RAII 完全绑定生命周期:

class ThreadPool {
public:
  static ThreadPool* get() { return instance_.get(); }

  void SubmitTask(Task&& t) { ... }
  ~ThreadPool() { ... }

private:
  ThreadPool() {}

  static inline std::unique_ptr<ThreadPool> instance_;

  friend class ThreadPoolScope;
};

class ThreadPoolScope  {
public:
  ThreadPoolScope(){
    assert(!ThreadPool::instance_);
    ThreadPool::instance_.reset(new ThreadPool());
  }

  ~ThreadPoolScope(){
    ThreadPool::instance_.reset();
  }
};

int main() {
  ThreadPoolScope thread_pool_scope{};
  ...
}

void some_func() {
  ThreadPool::get()->SubmitTask(...);
}

This makes destruction completely deterministic and if you do this with multiple objects, they are automatically destroyed in the correct order.这使得销毁完全确定,如果您对多个对象执行此操作,它们将以正确的顺序自动销毁。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM