Re[8]: BOOST.ASIO
От: paxerus  
Дата: 31.05.10 05:53
Оценка:
Здравствуйте, _pilgrim, Вы писали:

_>Здравствуйте, paxerus, Вы писали:


P>>я так понял пофлудить все горазды, а как что дельное сказать так....


_>Судя по иcпользованию метода shared_from_this, тип вашего объекта наследует от enable_shared_from_this. Такое наследование как правило нужно в случаях, когда из instance-метода необходимо передать shared_ptr, указывающий на текущий объект, во внешний метод\функцию.

_>Необходимым условием для этого (получение shared_ptr вызовом shared_from_this()) является наличие внешнего shared_ptr на ваш объект, т.е. "где-то" уже должен существовать shared_ptr, "владеющий" вашим объектом.

_>Касаемо кода

_>
_>shared_from_this().reset();
_>


_>вызов shared_from_this создает новый shared_ptr (внутренний, разделяемый между всеми экземплярами shared_ptr владеющими вашим объектом, счетчик которого >= 2, т.к. по крайней мере один shared_ptr уже ссылается на объект), у которого затем сбрасывается указатель на объект (и соотв. значение счетчика уменьшается на 1), т.е. полезный выхлоп от этого кода нулевой


_>Т.о., если вам нужно, чтобы объект жил пока идут асинхронные операции чтения\записи, и не держать при этом ссылку на объект где-нибудь еще, достаточно создать экземпляр объекта, инициализировать им shared_ptr и передать управлению вашему объекту, который будет "протаскивать" shared_ptr объекта (с пом. shared_from_this) через вызовы async_read\write методов asio, после вызова последнего read\write обработчика объект будет удален (конечно если нет других shared_ptr, кроме тех, которые переданы в методы async_read\write)

_>напр:

_>
_>shared_ptr<connection> conn(new connection(...));
conn->>run(); //асинхронный метод, connection сам отвечает за свое время жизни, передавая shared_ptr на себя в методы asio
_>


_>ps: имхо, описанный выше подход ("самоуправление" жизнью соединения) хоть и имеет право на жизнь, но не очень юзабелен, т.к. может потребоваться вести учет соединений, управлять их количеством, убивать "зависшие соединения" и тд, т.е. осуществлять управление соединениями.


Спасибо за разъяснения, а как тогда правильно делать? я так понимаю shared_from_this() нужно только чтоб соединение не завершиломь пока жив shared_from_this() правильно?

еще такая проблема наприсовалась :

у меня сервер является dll — плагином к другому серверу
и почему то происходит ошибка, пример кода ниже
class CSession
{....        
  public:
        CSession(){}
                UINT64                    SessionId;
        ExternalStruct                      s_us;                   //структура из внешнего приложения,ее описание в общем хидере
....
};
class connection : public boost::enable_shared_from_this<connection> {
public:
        ....
    typedef boost::ptr_map<UINT64,CSession>    SessionMap;  
        SessionMap                 ses_map; 
    ba::io_service&            io_service_;   
        ba::ip::tcp::socket        socket_; 
        boost::array<unsigned char, 8192>Buff; 
        ExternalSrv                 *extsrv;
    
   void run();
   void Recive(const bs::error_code& err, size_t len,size_t body_lenght);
  ....  
   CSession* create_ses(UINT64 ses_id) {
            ses_map.insert(ses_id,new CSession());
        return &ses_map[ses_id];
    }
 
   void delete_ses(UINT64 ses_id) {
       try{
            SessionMap::iterator it=ses_map.find(ses_id);
            if(&it!=NULL)      
               ses_map.erase(it);
         }
      catch(...){}
...
   }

void connection::run() 
{

    try 
    {
             
        async_read(socket_, ba::buffer(Buff), ba::transfer_at_least(9),
               boost::bind(&connection::Recive,
                           shared_from_this(),
                           ba::placeholders::error,
                           ba::placeholders::bytes_transferred,9));                

    } catch(std::exception& x) {
        
            std::cerr << "Exception: " << x.what() << std::endl;
        }
}

 void connection::Recive(const bs::error_code& err, size_t len,size_t body_lenght)
{
      CSession *ses= create_ses(123456);
      ses->SessionId=123456;
      //если делать  delete_ses(123456);тут то все нормально
      extsrv->ExternalFunc(&ses->s_us);

      delete_ses(123456); ----->а тут error

}


Во внешней функции происходит примерно следующее


void ExternalFunc(ExternalStruct  &s_us)
{
    ExternalStruct st; // в структуре в основном char и int естесно все статическое

    st.field =123;

    s_us=st;
}


При вызове delete_ses происходит ошибка
ругается на это
__CLR_OR_THIS_CALL ~basic_string()
{ // destroy the string
_Tidy(true);
}

не понятно почему он вообще на это ругается
ведь в структуре вообще не используется std::string чисто сишная структура


очень прошу помочь
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.