Использование std :: packaged_task для постановки в очередь задач CAsyncSocket-Detach-socket вызывает ошибку компиляции при вызове нестатического Attach из статического метода

Я реализую код, чтобы я мог принимать сетевые соединения по мере их поступления, отсоединять их от их сокета прибытия, создавать задачу std :: packaged_task, ставить эту задачу в очередь в контейнере deque и затем выполнять эти задачи в потоке их задач позже. Облегчить это можно на лекции Бо Цяня на YouTube «C ++ Threading # 9: packaged_task», в которой показано, как это сделать.

#include "stdafx.h"#include <afxsock.h>
#include <condition_variable>
#include <deque>
#include <future>

std::condition_variable notifyDequeNotEmptyCondVar;
std::mutex decodeMu;

class MyRxDecode : public CAsyncSocket
{
public:
static std::deque< std::packaged_task< bool() > > rxAcceptedTasks;

static bool StartDecode( SOCKET socket )
{
bool result = true;

// Attach detached socket to this socket
//result = Attach( socket ); //  error C2352: 'CAsyncSocket::Attach': illegal call of non-static member function
return result;
}

static bool DecodeTaskThread()
{
std::packaged_task< bool() > DecodingTask;

{
std::unique_lock< std::mutex > dequeLocker( decodeMu ); // makes sure all deque actions are atomic
notifyDequeNotEmptyCondVar.wait( dequeLocker, [] () { return !rxAcceptedTasks.empty(); } ); // wait until notified that deque is not empty
DecodingTask = std::move( rxAcceptedTasks.front() );
rxAcceptedTasks.pop_front();
}

DecodingTask(); // has no arg because the arg was previously bound to the functor passed in

return true;
}
};class MyListener : CAsyncSocket
{
virtual void OnAccept( int nErrorCode ) // is called when other socket does a connect on this socket's endpoint
{
CAsyncSocket syncSocket; // msdn prescribes creating stack socket
if( Accept( syncSocket ) )
{
AsyncSelect( FD_READ | FD_CLOSE ); // msdn
SOCKET socket = syncSocket.Detach(); // msdn

// Bo Qian's lecture explains how this packaged task code works and is made thread safe.
// Create task in separate thread to process this connection and push onto deque. The main advantage of a packaged task compared to using a functor is the former links the callable object to a future, which is useful in a multi-threaded environment (Bo Qian).
std::thread decodeThread( MyRxDecode::DecodeTaskThread ); // pass-by-value ctor
std::packaged_task< bool() > rxAcceptTask( std::bind( MyRxDecode::StartDecode, socket ) ); // binds function with its param to create functor wh is passed to packaged task's ctor
std::future< bool > rxAcceptTaskFuture = rxAcceptTask.get_future();

{
std::lock_guard< std::mutex > locker( decodeMu );
MyRxDecode::rxAcceptedTasks.push_back( std::move( rxAcceptTask ) );
}
notifyDequeNotEmptyCondVar.notify_one();
bool taskResult = rxAcceptTaskFuture.get();
decodeThread.join();

CAsyncSocket::OnAccept( nErrorCode ); // msdn
}
}
};

std::deque< std::packaged_task< bool() > > MyRxDecode::rxAcceptedTasks;

int main()
{
return 0;
}

Код не компилируется в моем случае, потому что мой StartDecode является статическим методом, пытающимся вызвать нестатическое Attach. StartDecode — статический метод, потому что std :: bind используется для привязки «гнезда» к задаче. «Socket» обычно передается методу StartDecode, но для того, чтобы «будущее» в упакованной задаче работало должным образом, любые передаваемые параметры должны быть связаны заранее с использованием std :: bind. Но как только StartDecode становится статичным, вызов Attach CAsyncSocket, который не является статическим, вызывает ошибку C2352.

Как я могу вызвать нестатический метод Attach из static MyRxDecode :: StartDecode? Есть ли способ избежать привязки параметра сокета к задаче, не делая его статичным?

0

Решение

std :: bind позволяет вам вызывать нестатические функции-члены. Смотрите cppreference.com-> std :: bind:

Notes
… when invoking a pointer to non-static member function or pointer to
non-static data member, the first argument has to be a reference or pointer (including,
possibly, smart pointer such as std::shared_ptr and std::unique_ptr) to an object whose
member will be accessed.

Замена определения для rxAcceptTask в приведенном выше коде со следующим:

std::packaged_task< bool() > rxAcceptTask( std::bind( &MyRxDecode::StartDecode, &myRxDecode, socket ) );

позволяет bool StartDecode (гнездо SOCKET) функция-член становится нестатичной.

0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]