在地图中插入 thread::id 和 class 实例

Inserting thread::id and class instance in a map

我有一个class:

class IOWorker {

std::thread                                    thread_;
boost::asio::io_service                        ios_;
boost::optional<boost::asio::io_service::work> work_;
Callback                                       callback_;

// Map of thread::id and this class' instance
typedef std::map<std::thread::id, IOWorker *>  IOWorkerThreadMap;
static IOWorkerThreadMap                       iOWorkerThreadMap;

public:
    IOWorker(Callback cb);
    ~IOWorker();
    
    std::thread::id getThreadId() {
       return thread_.get_id();
    }
    
    // IO worker threads will call this to fetch their instance
    static IOWorker* getIOWorkerInstance (void) {
       auto it = iOWorkerThreadMap.find(std::this_thread::get_id());
       if (it == iOWorkerThreadMap.end()) {
           return nullptr;
       }
       return (it->second);
    }
};

IOWorker::IOWorker (Callback cb) : callback_{cb}
{
    work_ = boost::in_place(boost::ref(ios_));
    thread_ = std::thread{[this] () {
               ios_.run();
                  }
           };
}

在主线程执行的函数中,我创建了这个 class 的 10 个实例并将它们插入映射中,其中 thread::id 是键,class 实例是值. 我正在从所有工作线程访问此地图,以通过在地图中查找它们的 thread::id 来获取它们各自的 class 实例。主线程也访问这些实例,以调用一些方法,post ios_ 上的作业等

void startIOWorkers (Callback cb)
{
   for (int i = 0; i < 10; ++i) {
       IOWorker *iow = new IOWorker{cb};
       std::thread::id threadId = iow->getThreadId();
       IOWorkerThreadMap.insert(std::make_pair(threadId, iow));
   }
}

我的问题是针对以下行:

IOWorkerThreadMap.insert(std::make_pair(threadId, iow));

我的理解(可能是错误的!)是上面函数中的 iowthreadId 将在我将它们插入地图时被“复制”,并且它们的两个副本将存在。

我想避免这种情况,因此,我想知道在这种情况下拥有 thread::idclass 实例映射的更好方法是什么?

这似乎比实际情况要复杂得多。

如果看起来像这种情况,您只需要从 thread::this_thread 访问地图,该语言已经在 thread_local 中内置了 map<thread_id, T>

class IOWorker {

std::thread                                    thread_;
boost::asio::io_service                        ios_;
boost::optional<boost::asio::io_service::work> work_;
Callback                                       callback_;

static thread_local IOWorker*                  this_thread_worker_;

public:
    IOWorker(Callback cb);
    ~IOWorker();
    
    // IO worker threads will call this to fetch their instance
    static IOWorker* getIOWorkerInstance (void) {
       return this_thread_worker_;
    }
};

IOWorker::IOWorker (Callback cb) : callback_{std::move(cb)}
{
    work_ = boost::in_place(boost::ref(ios_));
    thread_ = std::thread{[this] () {
       this_thread_worker_ = this;
       ios_.run();
    };
}


std::vector<IOWorker> startIOWorkers(Callback cb)
{
    std::vector<IOWorker> launched_workers;
    launched_workers.reserve(10);
    
    for (int i = 0; i < 10; ++i) {
       launched_workers.emplace_back(cb);
    }

    return launched_workers;
}