c++ - 从另一个线程修改 vector 中的指针数据是否安全?

标签 c++ boost stl thread-safety

一切似乎都奏效了,但我不确定这是否是解决问题的最佳方式。

基本上我有一个异步检索数据的对象。这个对象有一个指针 vector ,在主线程上分配和取消分配。使用 boost 函数,过程结果回调与此 vector 中的指针之一绑定(bind)。当它触发时,它将在某个任意线程上运行并修改指针的数据。

现在我在插入 vector 和删除的部分周围有关键部分,以防异步检索对象收到更多请求,但我想知道我是否需要在修改指针数据的回调中使用某种保护措施

希望这段精简的伪代码能让事情变得更清楚:

class CAsyncRetriever
{
    // typedefs of boost functions

    class DataObject
    {
         // methods and members
    };

public:
    // Start single asynch retrieve with completion callback
    void Start(SomeArgs)
    {
        SetupRetrieve(SomeArgs);
        LaunchRetrieves();
    }

protected:
    void SetupRetrieve(SomeArgs)
    {
            // ...

        { // scope for data lock
            boost::lock_guard<boost::mutex> lock(m_dataMutex);
            m_inProgress.push_back(SmartPtr<DataObject>(new DataObject)));
            m_callback = boost::bind(&CAsyncRetriever::ProcessResults, this, _1, m_inProgress.back());
        }

            // ...
    }

    void ProcessResults(DataObject* data)
    {
                // CALLED ON ANOTHER THREAD ... IS THIS SAFE?
        data->m_SomeMember.SomeMethod();
                data->m_SomeOtherMember = SomeStuff;
    }

    void Cleanup()
    {
                // ...

        { // scope for data lock
            boost::lock_guard<boost::mutex> lock(m_dataMutex);
            while(!m_inProgress.empty() && m_inProgress.front()->IsComplete())
                m_inProgress.erase(m_inProgress.begin());
        }

                // ...
         }

private:
    std::vector<SmartPtr<DataObject>> m_inProgress;
    boost::mutex m_dataMutex;
        // other members
};

编辑:这是 ProccessResults 回调的实际代码(为了您的利益加上注释)

    void ProcessResults(CRetrieveResults* pRetrieveResults, CRetData* data)
        {
// pRetrieveResults is delayed binding that server passes in when invoking callback in thread pool
// data is raw pointer to ref counted object in vector of main thread (the DataObject* in question)

                // if there was an error set the code on the atomic int in object
            data->m_nErrorCode.Store_Release(pRetrieveResults->GetErrorCode());

                // generic iterator of results bindings for generic sotrage class item
            TPackedDataIterator<GenItem::CBind> dataItr(&pRetrieveResults->m_DataIter);
                // namespace function which will iterate results and initialize generic storage
            GenericStorage::InitializeItems<GenItem>(&data->m_items, dataItr, pRetrieveResults->m_nTotalResultsFound); // this is potentially time consuming depending on the amount of results and amount of columns that were bound in storage class definition (i.e.about 8 seconds for a million equipment items in release)
                // atomic uint32_t that is incremented when kicking off async retrieve
            m_nStarted.Decrement(); // this one is done processing

                // boost function completion callback bound to interface that requested results
            data->m_complete(data->m_items);
        }

最佳答案

就目前而言,Cleanup 代码似乎可以销毁正在回调 ProcessResults 的对象。当您在回调中取消引用指针时,这会导致问题。

我的建议是扩展 m_dataMutex 的语义以包含回调,但如果回调是长时间运行的,或者可以在 SetupRetrieve 中内联发生(有时确实会发生这种情况 - 虽然在这里你声明回调在不同的线程上,在这种情况下你没问题)那么事情就更复杂了。目前,m_dataMutex 对于它是否控制对 vector 的访问、或其内容或两者的访问有点困惑。明确其范围后,可以 boost ProcessResults 以验证锁内有效负载的有效性。

关于c++ - 从另一个线程修改 vector 中的指针数据是否安全?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6311671/

相关文章:

c++ - 解析包含多行条目的日志文件

java - 不同语言(即 Java 和 C++)中的 "random"生成器如何比较?

c++ - 在 C++ 中相互交换数组的部分

c++ - 将 boost 间隔扩展到标量乘法

c++ - 使用 zlib 压缩 boost 二进制文件

c++ std::map 分配错误:无法在分配中将 ' type **' 转换为 'type *'

C++ 对象列表只是拷贝

c++ - 如何在不使用数组或任何库函数(任何用于反转的函数)的情况下反转用户输入?

c++ - Boost.Python : how to create & return a list of existing c++ objects, 没有复制

c++ - 对 STL 容器的安全并行只读访问