Передача владения указателем сокета с помощью tcp :: acceptor :: async_accept - PullRequest
3 голосов
/ 21 июня 2010

Я недавно начал использовать Boost.Asio в проекте и хотел бы знать, знает ли кто-нибудь чистое решение для передачи владения вновь созданным сокетом в tcp :: acceptor :: async_accept, который, в свою очередь, передаст это владение к функции обработчика подтверждения.

Заметьте, это не бессвязное желание, так как обработчик должен быть вызван ровно один раз.

Я заметил, что не могу использовать std :: bind () и std :: unique_ptr <> в качестве параметра, поскольку std :: bind () требует, чтобы его параметры были CopyConstructible, и это справедливо. Кроме того, концепция Boost AcceptHandler также должна быть CopyConstructible.

Так что мои варианты будут:

  • Используйте устаревший способ перемещения объектов std :: auto_ptr <> с помощью конструктора копирования, что может привести к неясным ошибкам в новых выпусках Boost.Asio.
  • Используйте std :: shared_ptr <> и не можете отменить общее владение указателем, если он больше не нужен, т.е. когда он достигает фактической функции-обработчика (именно так выполняется работа в примерах на * 1012). *http://www.boost.org/doc/libs/1_43_0/doc/html/boost_asio/examples.html насколько я читал).

или

  • У меня есть идея получше.

Я довольно сильно растерялся. Может ли кто-нибудь просветить меня?

1 Ответ

1 голос
/ 03 марта 2011

Я пытался найти способ сделать это, используя стандартную библиотеку c ++ 0x, но не смог.В конце концов я решил написать свой собственный удобный класс rvalue_reference_wrapper и rvalue_ref ().Как обычно с std :: bind, вам нужно обернуть свой не копируемый объект во что-то, что можно скопировать (лучший пример - reference_wrapper).Вы могли также просто передать указатель, но это означает изменение вашего интерфейса.

Это сработало на моей машине:

#include <iostream>
#include <functional>
#include <memory>

template< class T >
struct rvalue_reference_wrapper
{
    rvalue_reference_wrapper( T&& t )
        : t_(std::move(t))
    {}

    operator T&&() const volatile
    {
        return std::move(t_);
    }

private:
    T&& t_; 
};

template< class T >
rvalue_reference_wrapper<T> rvalue_ref( T&& t )
{
    return rvalue_reference_wrapper<T>(std::move(t));
}

void go( std::unique_ptr<int> i )
{
    std::cout << *i << std::endl;
}

int main()
{
    std::unique_ptr<int> i(new int(1));

    auto b = std::bind( go, rvalue_ref(std::move(i)) );
    //auto b = std::bind( go, std::ref(std::move(i)) ); // Wont work

    b();
}

Я не сделал код пуленепробиваемым, но приветствую некоторые обсуждения онеобходимость в rvalue_reference_wrapper или как его смоделировать с использованием std :: reference_wrapper.

Кроме того, для вашего конкретного случая вам, вероятно, потребуется написать разностную версию rvalue_reference_wrapper, которая содержит объект по значению неСсылка на rvalue, поскольку ваш оригинальный unique_ptr, вероятно, покинет область видимости (и будет уничтожен), поскольку вы используете асинхронные вызовы asio.

...