your traktor the tarjetas tarjeta suficientes suena sound sonido reconoce que probably para not integradas hay error cómo connected configurar canales asio4all asio c++ boost c++11 boost-asio move-semantics

c++ - traktor - Cómo engañar boost:: asio para permitir manejadores de solo movimiento



error in the asio sound driver your soundcard is probably not connected (2)

En un protocolo de comunicación RPC, después de la invocación de un método, estoy enviando mensajes "finalizados" a la persona que llama. Dado que los métodos se invocan de manera concurrente, el búfer que contiene la respuesta (una std::string debe estar protegido por una exclusión mutua. Lo que estoy tratando de lograr es lo siguiente:

void connection::send_response() { // block until previous response is sent std::unique_lock<std::mutex> locker(response_mutex_); // prepare response response_ = "foo"; // send response back to caller. move the unique_lock into the binder // to keep the mutex locked until asio is done sending. asio::async_write(stream_, asio::const_buffers_1(response_.data(), response_.size()), std::bind(&connection::response_sent, shared_from_this(), _1, _2, std::move(locker)) ); } void connection::response_sent(const boost::system::error_code& err, std::size_t len) { if (err) handle_error(err); // the mutex is unlocked when the binder is destroyed }

Sin embargo, esto no se compila, ya que boost::asio requiere que los manejadores sean CopyConstructible .

El problema se puede solucionar (aunque no con mucha elegancia) utilizando la siguiente clase de casillero compartido en lugar de unique_lock :

template <typename Mutex> class shared_lock { public: shared_lock(Mutex& m) : p_(&m, std::mem_fn(&Mutex::unlock)) { m.lock(); } private: std::shared_ptr<Mutex> p_; };

¿Cuál es el razonamiento detrás de boost::asio no permite a los manejadores de solo movimiento?


Aquí hay una solución más simple:

shared_ptr<mutex> lock(mutex & m) { m.lock(); return shared_ptr<mutex>(&m, mem_fn(&mutex::unlock)); }

No hay necesidad de escribir envoltorios personalizados.

Refiriéndose a las técnicas de programación de punteros inteligentes, incluso puede utilizar:

class shared_lock { private: shared_ptr<void> pv; public: template<class Mutex> explicit shared_lock(Mutex & m): pv((m.lock(), &m), mem_fn(&Mutex::unlock)) {} };

shared_lock ahora se puede utilizar como:

shared_lock lock(m);

Tenga en cuenta que shared_lock no tiene una plantilla en el tipo de shared_ptr<void> , gracias a la shared_ptr<void> de shared_ptr<void> para ocultar información de tipo.

Es posible que cueste más, pero también tiene algo a su favor (el receptor puede tomar shared_lock y usted podría pasarle un bloqueo actualizable, único y compartido, scope_guard, de básicamente cualquier BasicLockable o "mejor"


Hasta que Chris Kohlhoff responde al error que he presentado, aquí hay una solución simple:

template <typename F> struct move_wrapper : F { move_wrapper(F&& f) : F(std::move(f)) {} move_wrapper(move_wrapper&&) = default; move_wrapper& operator=(move_wrapper&&) = default; move_wrapper(const move_wrapper&); move_wrapper& operator=(const move_wrapper&); }; template <typename T> auto move_handler(T&& t) -> move_wrapper<typename std::decay<T>::type> { return std::move(t); }

La envoltura declara un constructor de copias, engañando a la maquinaria de asio para que la envíe, pero nunca la define, por lo que la copia resultaría en un error de enlace.

Ahora uno puede finalmente hacer esto:

std::packaged_task<int()> pt([] { std::this_thread::sleep_for(std::chrono::seconds(1)); return 42; }); std::future<int> fu = pt.get_future(); boost::asio::io_service io; io.post(move_handler(pt)); std::thread(&boost::asio::io_service::run, &io).detach(); int result = fu.get(); assert(result == 42);