Чего только в жизни не бывает! Похоже, что я оказываюсь в ситуации, когда потребуется поиметь голый владеющий указатель на std::shared_ptr. Что-то вроде (псевдокод для иллюстрации, не претендует на production readyness):
void ready_handler(const mg_connection * conn, void *) {
auto shared_conn_data = std::make_shared<connection_data_t>(...);
auto * owning_ptr = new std::shared_ptr<connection_data_t>{shared_conn_data};
mg_set_user_connection_data(conn, owning_ptr); // Только за этим onwing_ptr и нужен был.
// Нельзя таким образом сохранить весь shared_ptr.
send_to_external_thread(shared_conn_data);
}
...
void close_handler(const mg_connection * conn, void *) {
auto * owning_ptr = reinterpret_cast<std::shared_ptr<connection_data_t>>(
mg_get_user_connection_data(conn));
// Этот экземпляр больше не нужен.
// Если где-то на внешней нити остался свой shared_ptr, то connection_data_t продолжит
// свое существование и после выхода из close_handler.
// Если нет, то connection_data_t умрет прямо сейчас.
delete owning_ptr;
}
Интеграция с написанным на чистом Си коде. Ничего лучшего пока не придумывается :)
intrusive_ptr + IRefCounted ?
ОтветитьУдалить@night beast
ОтветитьУдалитьДа, первая мысль была именно об этом. Но в проекте нет готового intrusive_ptr (и Boost-а нет). Подключать что-то ради одного места в коде... Хотя можно, конечно, заглянуть в потроха SObjectizer-а и поиспользовать функциональность оттуда. Но...
Но все равно в месте вызова mg_set_user_connection_data и msg_get_user_connection_data будет присутствовать голый указатель, с которым еще и специальным образом работать нужно (т.е. вызывать функции инкремента/декремента счетчика вручную).
Так что, имхо, голый владеющий указатель тут даже очевиднее и проще как-то.
Мне кажется, для похожей задачи я использовал std::list. И в самом объекте итератор на самого себя в этом листе. И когда объект больше не нужен, удаляем самого себя из std::list-а. Единственный случай, когда пригодился list :)
ОтветитьУдалить@eao197
ОтветитьУдалитьдля msg_set_user_connection_data/msg_get_user_connection_data можно написать обертки, которые наружу будут отдавать уже типизированные данные
голый указатель на умный указатель выглядит дико )