将析构函数调用转移到专用线程

问题描述 投票:0回答:1

我正在优化 C++ 代码,并且遇到析构函数调用需要花费大量时间的情况。

然后我为了好玩而编写了这个小类,只是为了看看我是否可以简单地将破坏转移到另一个线程,它实际上似乎有效。

我对此代码有一些疑问:

  1. 代码的功能符合我的想法吗? IE。将shared_ptr中数据的所有权从调用者的线程转移到另一个线程,从而将释放内存的成本转移到另一个线程。
  2. 使用这样的模式时是否有任何陷阱或副作用需要注意?
  3. 这是应该避免的反模式吗?如果是这样,为什么?
#pragma once

#include <queue>
#include <mutex>
#include <memory>
#include <functional>

namespace test {

  class Cleaner {
    struct State {
      std::queue<std::shared_ptr<void>> queue;
      std::mutex mtx;
      std::condition_variable condition;
      bool cancelled;
      bool done;
    };
  public:
    Cleaner()
      :
      _state(std::make_shared<State>()),
      _thread(&runCleanerloop, _state)
    {
    }

    ~Cleaner() {
      {
        std::lock_guard<std::mutex> lock(_state->mtx);
        _state->done = true;
      }
      _state->condition.notify_all();
      _thread.join();
    }

    template <typename T>
    void run(std::shared_ptr<T>& data) {
      {
        std::lock_guard<std::mutex> lock(_state->mtx);

        // Push a copy to the queue to be released by the thread.
        _state->queue.push(data);

        // Reset the input in the caller's thread.
        data.reset();
      }
      _state->condition.notify_all();
    }

    static void runCleanerloop(
      const std::shared_ptr<State>& state
    ) {
      std::shared_ptr<void> data;

      bool done = false;

      while (true) {
        // Wait for data to appear in queue.
        {
          std::unique_lock<std::mutex> lock(state->mtx);

          state->condition.wait(lock, [&state] {
            return state->cancelled || state->queue.size() || state->done;
          });

          if (state->cancelled || (!state->queue.size() && state->done)) {
            done = true;
          }
          else {
            data = state->queue.front();

            state->queue.pop();
          }
        }
        state->condition.notify_all();

        if (done) {
          return;
        }

        // Release the data inside this thread.
        data.reset();
      }
    }
  private:
    std::shared_ptr<State> _state;
    std::thread _thread;
  };
}

预期用途:

#include "cleaner.h"

void test() {
  Cleaner cleaner;
     
  std::shared_ptr<Data> current_data;
  while (true) {
    current_data = createData();

    /* Do something */
      
    // This will reset the current_data ptr, but the actual destructor-call
    // will be done inside the Cleaner thread.
    cleaner.run(current_data);
  }
}
c++ multithreading optimization memory-management
1个回答
-1
投票

这不是对原帖中问题的回答,只是想提一下:

在考虑使用这些奇怪的模式来转移数据所有权之前,您应该首先考虑设计一个合适的内存管理系统,这样您就不需要在每个循环上重新分配数据。

此外,如果你有另一个shared_ptr保持数据活动,线程将不会破坏任何数据,因为引用计数没有达到0。

© www.soinside.com 2019 - 2024. All rights reserved.