用 asio io-service boose wait_for_any…如何才能返回适合 wait_for_any 的 future?

我有一段使用asio coroutine来异步使用http get获取文件的代码,现在我试图修改这段代码来获取24个文件,我想做一个有boost::futures的容器 “而不是std::futures”,这样我就可以使用wait_for_any来处理准备好使用的future,我想把我的coroutine转换为保持异步http get,同时在http get完成时返回文件名的future “正确或错误”。

   void HTTPRequest::Execute(boost::asio::yield_context yield_r, std::string request_name, boost::shared_ptr<std::map<std::string, boost::shared_ptr<HTTPResponse>>> mHTTPClient_Responses_Map_shared_pointer)
//4-9-2020 trial of promise
//13std::string HTTPRequest::Execute(boost::asio::yield_context yield_r, boost::promise<std::string> &p, std::string request_name, boost::shared_ptr<std::map<std::string, boost::shared_ptr<HTTPResponse>>> mHTTPClient_Responses_Map_shared_pointer)
{
    std::map<std::string, boost::shared_ptr<HTTPResponse>> & mHTTPClient_Responses_Map = boost::ref(*mHTTPClient_Responses_Map_shared_pointer).get() ;
    ptime startFetch = second_clock::local_time();
    boost::unique_lock<boost::mutex> cancel_lock(mCancelMutex);
    if (mWasCancelled)
    {
        cancel_lock.unlock();
        OnFinish(boost::system::error_code(boost::asio::error::operation_aborted));

        m_formatting_ostream << "Request #" << this->GetId() << " for " << mUrl << " has been cancelled by the user at start of HTTPRequest::Execute coroutine." << std::endl;
        m_formatting_ostream.flush();
        ////allam2020 change UniqueSignalValue to url
        boost_log_function(mHTTPRequest_LoggingInstance_shared_pointer, "cancelExecute", request_name, m_formatting_ostream_string);
        m_formatting_ostream.clear();

        //p.set_value(request_name);
        //return request_name;

    }
    cancel_lock.unlock();

    bool iterator_failed = true;////    allam 2020 where is this variable changed?????????? is it before SendRequest()??????? after async_connect retruns successfully
    boost::system::error_code ec;
    for (auto iterator_resolve : *mRequestSharedPtrVecResolverIterator)
    {
        BOOST_LOG((*mHTTPRequest_LoggingInstance_shared_pointer).mloggerCoutLog) << "Request #" << this->GetId() << " for " << mUrl <<" trying to send request using " << iterator_resolve->endpoint().address().to_string() << std::endl;

        // Compose the request message.
        mRequestBuf += "GET " + mUri + " HTTP/1.1\r\n";
        // Add mandatory header.
        mRequestBuf += "Host: " + mHost + "\r\n";
        mRequestBuf += "\r\n";

        for (int mIrange : boost::irange(0, ATTEMPTS))
        {
            HTTPRequest::mIrange = mIrange;
            ////allam2020 1111111111111111111111111111111111111111111111111111111111
            resolver_iterator iterator_connect = boost::asio::async_connect(mSock, iterator_resolve, yield_r[ec]);////allam 2020 this gets us back to io_stream_run

            if (ec.value() == boost::system::errc::errc_t::success)//(ec.value()==0)
            {               
                ////allam 2020
                iterator_failed = false;//????????????/////???????

                boost::unique_lock<boost::mutex> cancel_lock(mCancelMutex);
                if (mWasCancelled)
                {
                    cancel_lock.unlock();
                    OnFinish(boost::system::error_code(boost::asio::error::operation_aborted));

                    m_formatting_ostream << "Request #" << this->GetId() << " for " << mUrl << " has been cancelled by the user after returning from async_connect inside HTTPRequest::Execute using"<< iterator_resolve->endpoint().address().to_string() << std::endl;
                    m_formatting_ostream.flush();
                    boost_log_function(mHTTPRequest_LoggingInstance_shared_pointer, "cancel_async_connect_Execute", iterator_resolve->endpoint().address().to_string(),m_formatting_ostream_string);
                    m_formatting_ostream.clear();

                    //p.set_value(request_name);
                    //return request_name;
                }

                cancel_lock.unlock();

                // Send the request message.
                SendRequest(yield_r);////alllam 2020 VVVVVVVVIIIIIIIIIIIIIPPPPPPPPPPP MILESTONE
            }
            else if (ec.value() != boost::system::errc::errc_t::success)//(ec.value()==0) //(ec.value() != 0)
            {
                OnFinish(ec);               
                BOOST_LOG((*mHTTPRequest_LoggingInstance_shared_pointer).mloggerCoutLog) <<"Request #" << this->GetId() << " for " << mUrl <<" failed after trying " << mIrange << "times" << " to async_connect inside HTTPRequest::Execute " << std::endl;                
                continue;
            }


            ////allam 2020  now test for mContinue_for ,this is done for other functions recurdively called inside SendRequest
            if (mContinue_for==true)
            {
                mContinue_for = !(mContinue_for);
                boost::this_thread::sleep_for(boost::chrono::seconds(mIrange));

                continue;
            }

            // Response is correct.
            //log str_status_code
            //Logger.info("Fetched {0} completed in {1}s".format(id, time.time() - start))
            //allam2020
            m_formatting_ostream << "Request #" << this->GetId() << " for " << mUrl << "Fetched " << mUrl << " completed in : " << (second_clock::local_time() - startFetch) << "with HTTP code :" << mResponsePtr->get_status_code() << "\n" << "and the code reasonPhrase is :" << HttpStatus::reasonPhrase(static_cast<int>(mResponsePtr->get_status_code())) << "with certain resolver iterator " << iterator_resolve->endpoint().address().to_string() << std::endl;
            m_formatting_ostream.flush();

            boost_log_function(mHTTPRequest_LoggingInstance_shared_pointer, "http_request_completed", HttpStatus::reasonPhrase(static_cast<int>(mResponsePtr->get_status_code())), m_formatting_ostream_string);
            m_formatting_ostream.clear();

            //if len(buffer.getbuffer()) <= 0:
            if (mResponsePtr->get_response_buf().size() <= 0)
            {
                //Logger.info("Buffer for {0} is empty ".format(id))
                //allam2020
                m_formatting_ostream << "Request #" << this->GetId() << " for " << mUrl << "Fetched " << mUrl << " with Buffer for " << mUrl << " is empty  " << "\n" << "with HTTP code :" << mResponsePtr->get_status_code() << "\n" << "and the code reasonPhrase is :" << HttpStatus::reasonPhrase(static_cast<int>(mResponsePtr->get_status_code())) << std::endl;
                m_formatting_ostream.flush();

                boost_log_function(mHTTPRequest_LoggingInstance_shared_pointer, "http_request_completed_empty", HttpStatus::reasonPhrase(static_cast<int>(mResponsePtr->get_status_code())), m_formatting_ostream_string);
                m_formatting_ostream.clear();

            }

            //continue work on response
            ////std::string response_name = "response_" + request_name;////allam 2020 make this member variable????????????//4-22-2020 yes 
            mHTTPRequest_response_name = "response_" + request_name;
            mHTTPClient_Responses_Map[mHTTPRequest_response_name] = GetResponseSharedPtr();

            break;
        }

        //the following conditions test the result of send request
        if (mSendRequest == 0)
        {
            if (mReadStatusLine == 0)
            {
                if (mHttp_1_1 == 0)
                {
                    if (mStatusCodeNot200 == 0)
                    {
                        if (mReadResponseHeaders == 0)
                        {
                            if (mReadResponseBody == 0)
                            {
                                ////allam2020 4-4-2020 no error present and response is recieved in its mHTTPResponse SO DO NOTHING 
                            }
                            else if (mReadResponseBody != 0)
                            {
                                m_formatting_ostream << "Request #" << this->GetId() << " for " << mUrl << " has failed completely after trying" << ATTEMPTS << "times" << " to async_read inside HTTPRequest::ReadResponseBody to get ResponseBody  " << "with certain resolver iterator " << iterator_resolve->endpoint().address().to_string() << std::endl;
                                m_formatting_ostream.flush();
                                boost_log_function(mHTTPRequest_LoggingInstance_shared_pointer, "failed_async_read_inside_HTTPRequest_ReadResponseBody", "requestFailed_ReadResponseBody_Iterator_ " + iterator_resolve->endpoint().address().to_string(),m_formatting_ostream_string);
                                m_formatting_ostream.clear();
                            }
                        }
                        else if (mReadResponseHeaders != 0)
                        {
                            m_formatting_ostream << "Request #" << this->GetId() << " for " << mUrl << " has failed completely after trying" << ATTEMPTS << "times" << " to async_read_until inside HTTPRequest::ReadResponseHeadersto get ResponseHeaders " << "with certain resolver iterator " << iterator_resolve->endpoint().address().to_string() << std::endl;
                            m_formatting_ostream.flush();
                            boost_log_function(mHTTPRequest_LoggingInstance_shared_pointer, "failed_async_read_until_inside_HTTPRequest_ReadResponseHeaders", "requestFailed_ReadResponseHeaders_Iterator_ " + iterator_resolve->endpoint().address().to_string(), m_formatting_ostream_string);
                            m_formatting_ostream.clear();
                        }
                    }
                    else if (mStatusCodeNot200 != 0)
                    {
                        m_formatting_ostream << "Request #" << this->GetId() << " for " << mUrl << " has failed completely after" << ATTEMPTS << "times" << " to async_read_until inside HTTPRequest::ReadStatusLine because of status_code not 200:" << http_errors::invalid_response << "the error code is :" << mStatusCode << "\n" << "and the error reasonPhrase is :" << HttpStatus::reasonPhrase(static_cast<int>(std::stoul(mStatusCode))) << "with certain resolver iterator " << iterator_resolve->endpoint().address().to_string() << std::endl;
                        m_formatting_ostream.flush();
                        boost_log_function(mHTTPRequest_LoggingInstance_shared_pointer, "failed_StatusCodeNot200_inside_HTTPRequest_ReadStatusLine", "requestFailed_ReadStatusLine_StatusCodeNot200:" + mStatusCode + "_Iterator_ " + iterator_resolve->endpoint().address().to_string(), m_formatting_ostream_string);
                        m_formatting_ostream.clear();
                    }
                }
                else if (mHttp_1_1 != 0)
                {
                    ////4-2-2020
                    m_formatting_ostream << "Request #" << this->GetId() << " for " << mUrl << " after trying " << ATTEMPTS << "times" << " to async_read_until inside HTTPRequest::ReadStatusLine because of bad not http/1.1 version response" << mHTTP_Version << "recieved with certain resolver iterator " << iterator_resolve->endpoint().address().to_string() << std::endl;
                    m_formatting_ostream.flush();
                    boost_log_function(mHTTPRequest_LoggingInstance_shared_pointer, "failed_Http_1_1_inside_HTTPRequest_ReadStatusLine", "requestFailed_ReadStatusLine_Http_1_1_Iterator " + iterator_resolve->endpoint().address().to_string(), m_formatting_ostream_string);
                    m_formatting_ostream.clear();
                }
            }
            else if (mReadStatusLine != 0)
            {
                ////4-2-2020
                m_formatting_ostream << "Request #" << this->GetId() << " for " << mUrl << " after trying " << ATTEMPTS << "times" << " to async_read_until inside HTTPRequest::ReadStatusLine  with certain resolver iterator " << iterator_resolve->endpoint().address().to_string() << std::endl;
                m_formatting_ostream.flush();
                boost_log_function(mHTTPRequest_LoggingInstance_shared_pointer, "failed_async_read_until_inside_HTTPRequest_ReadStatusLine", "requestFailed_ReadStatusLine_Iterator " + iterator_resolve->endpoint().address().to_string(), m_formatting_ostream_string);
                m_formatting_ostream.clear();
            }
        }
        else if (mSendRequest != 0)
        {
            ////4-2-2020
            m_formatting_ostream << "Request #" << this->GetId() << " for " << mUrl << " after trying " << ATTEMPTS << "times" << " to async_write inside HTTPRequest::SendRequest  with certain resolver iterator " << iterator_resolve->endpoint().address().to_string() << std::endl;
            m_formatting_ostream.flush();
            boost_log_function(mHTTPRequest_LoggingInstance_shared_pointer, "failed_async_write_inside_HTTPRequest_SendRequest", "requestFailed_SendRequest_Iterator " + iterator_resolve->endpoint().address().to_string(), m_formatting_ostream_string);
            m_formatting_ostream.clear();
        }



        if (iterator_failed == true)
        {
            m_formatting_ostream << "Request failed for " << mUrl << " after trying " << ATTEMPTS << "times" << " to async_connect inside HTTPRequest::Execute with certain resolver iterator "<< iterator_resolve->endpoint().address().to_string() << std::endl;
            m_formatting_ostream.flush();
            ////allam 2020 i might need to pass iterator resolve which has failed
            boost_log_function(mHTTPRequest_LoggingInstance_shared_pointer, "failed_async_connect_inside_HTTPRequest_Execute", "requestFailed_Iterator " + iterator_resolve->endpoint().address().to_string(), m_formatting_ostream_string);
            m_formatting_ostream.clear();


            continue;////allam 2020 here i should continue for next iterator
        }
    }
    if (iterator_failed == true)
    {
        m_formatting_ostream << "Request failed for " << mUrl << " after trying " << ATTEMPTS << "times" << " to async_connect inside HTTPRequest::Execute with ALL resolver iterators" << std::endl;
        m_formatting_ostream.flush();
        ////allam 2020 i might need to pass iterator resolve which has failed
        boost_log_function(mHTTPRequest_LoggingInstance_shared_pointer, "failed_async_connect_inside_HTTPRequest_Execute", "requestFailed_Iterator" + GetmUrlLogger(),m_formatting_ostream_string);////allam2020 ?????i might need to change this from GetmUrlLogger to request name argument of Execute???????????????????4-2-2020
        m_formatting_ostream.clear();
        ////allam 2020 here i should return from execute because no resolved address could be used so the whole execute request operation failed

        //p.set_value(request_name);
        //return request_name;
    }
    ////allam2020 should i put if conditions for mSendRequest ....mReadResponseBody????? to identify final complete error at these functions and end of 5 attempts

}

还有其他函数SendRequest……是从Execute中调用的,但我没有把它们放进去以减少代码。

解决方案:

我不是经常光看代码就气喘吁吁的。这就是其中的一次。你也许应该直接说明你的目标。

  • 还有 mRequestSharedPtrVecResolverIterator 表明你正在存储一个解析器结果的向量,只是为了迭代它们并尝试执行请求。

    你知道吗,你可以直接使用 boost::asio::[async_]connect 来为你做这个?它看起来像一个简单的 boost::asio::async_connect 应该可以解决所有关于解析器迭代器和

  • 你应该只返回响应,而不是神奇地把它设置到地图中(你不需要访问其他条目)。
  • 最后,你可以砍掉99%的共享指针,这将为你节省更多的时间,而不是人为地用 m_formatting_ostream 我想象的

    std::string m_formatting_ostream_string;
    boost::iostreams::stream<boost::iostreams::back_insert_device<std::string>>
        m_formatting_ostream{ m_formatting_ostream_string };
    

    但你一直在重复容易出错和低效的代码,如

    m_formatting_ostream << ... << std::endl;
    m_formatting_ostream.flush(); // this is redundant already
    boost_log_function(
        ...,
        m_formatting_ostream_string);
    m_formatting_ostream.clear();
    
  • 还有很多混乱的代码。例如:这里是怎么回事?

    boost::ref(*mHTTPClient_Responses_Map_shared_pointer).get()。

boost::ref(*p).get() 根据定义,只是 *p.

  • 一切都是有状态的,更糟糕的是:状态是突变的。例如:

    mRequestBuf += "GET " + mUri + " HTTP/1.1\r\n";
    // Add mandatory header.
    mRequestBuf += "Host: " + mHost + "\r\n";
    mRequestBuf += "\r\n";
    

    每次在循环中都会发生,但它从未被重置。它可能不应该发生多次(那是浪费)。

  • boost::this_thread::sleep_for(boost::chrono::seconds(mIrange)); 在async IO中是一个巨大的危险信号。你应该在不睡觉的情况下等待结果。

  • 你在一个布尔标志周围使用了整个mutex。只要把那个原子的

    std::atomic_bool mWasCancelled{ false };
    

    另外,使用 unique_lock 如果你100%手动解锁,就没有意义了。

  • 一般来说,有一种倾向是非常啰嗦的(匈牙利语)名称和同上注释。这可能是试图获得一种感觉控制,但情况恰恰相反:代码变得如此 “令人印象深刻 “和 “交代”,以至于它实际上不清楚它应该做什么,为什么要工作。

  • 这个 圣诞树 反模式是发明例外的目的。这也消除了对 Execute 来 “了解 “每一个小的实现细节。SendRequest 和许多难以捉摸的状态标志,它可以设置成神秘的值。

enter image description here

好吧,我真的是气不打一处来。我将无法解决这个问题,甚至无法认识这个问题(因为没有一个未来)。相反,我建议工作的东西,如 https:/www.boost.orgdoclibsdeveloplibsbeastexamplehttpclientasynchttp_client_async.cpp 对于稍微不那么重口味的方法,会适合维护。

给TA打赏
共{{data.count}}人
人已打赏
未分类

Gif图片在ionic-5的闪屏中无法使用。

2022-9-9 4:24:17

未分类

如何在Ruby中迭代一个数组的第2个元素?[重复]

2022-9-9 4:24:19

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索