Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

std::async

Ostatnio zmodyfikowano 2017-07-26 04:44
Autor Wiadomość
Rashmistrz
Temat założony przez niniejszego użytkownika
std::async
» 2017-07-24 00:48:55
Mam taką deklarację funkcji składowej:
C/C++
class Connection
    : public protocol::packets::PacketHandler
     , public util::ObserverSubject < ConnectionListener >
{
private:
    // ...
    std::future < protocol::packets::Packet *> CreatePacket( DataBuffer & buffer );
    // ...
};

Mam taką definicję funkcji składowej:
C/C++
std::future < protocol::packets::Packet *> Connection::CreatePacket( DataBuffer & buffer ) {
    std::size_t readOffset = buffer.GetReadOffset();
    VarInt length;
   
    try {
        buffer >> length;
    } catch( const std::out_of_range & ) {
        // This will happen when the buffer only contains part of the VarInt,
        // so only part of the packet was received so far.
        // The buffer read offset isn't advanced when the exception is thrown, so no need to set it back to what it was.
        return std::future < protocol::packets::Packet *>();
    }
   
    if( length.GetInt() == 0 || buffer.GetRemaining() <( u32 ) length.GetInt() ) {
        // Reset the read offset back to what it was because the full packet hasn't been received yet.
        buffer.SetReadOffset( readOffset );
        return std::future < protocol::packets::Packet *>();
    }
   
    DataBuffer decompressed = m_Compressor->Decompress( buffer, length.GetInt() );
    return std::async( std::launch::async, & protocol::packets::PacketFactory::CreatePacket, m_Protocol, m_ProtocolState, decompressed, length.GetInt(), this );
}

Mam takie flagi:
-O2 -m64 -std=c++17 -march=native

Dostaję taki log:
||=== Build: Release Win32 in mclib (compiler: GNU GCC Compiler) ===|
C:\DISK\CODE\mclib-master\mclib\src\mclib\core\Connection.cpp||In member function 'std::future<mc::protocol::packets::Packet*> mc::core::Connection::CreatePacket(mc::DataBuffer&)':|
C:\DISK\CODE\mclib-master\mclib\src\mclib\core\Connection.cpp|256|error: no matching function for call to 'async(std::launch, mc::protocol::packets::Packet* (*)(mc::protocol::Protocol&, mc::protocol::State, mc::DataBuffer, std::size_t, mc::core::Connection*), mc::protocol::Protocol&, mc::protocol::State&, mc::DataBuffer&, s32, mc::core::Connection*)'|
C:\msys\mingw64\include\c++\7.1.0\future|1711|note: candidate: template<class _Fn, class ... _Args> std::future<typename std::result_of<typename std::decay<_Tp>::type(typename std::decay<_Args>::type ...)>::type> std::async(std::launch, _Fn&&, _Args&& ...)|
C:\msys\mingw64\include\c++\7.1.0\future|1711|note:   template argument deduction/substitution failed:|
C:\DISK\CODE\mclib-master\mclib\src\mclib\core\Connection.cpp|256|required from here|
C:\msys\mingw64\include\c++\7.1.0\future|1711|error: no type named 'type' in 'class std::result_of<mc::protocol::packets::Packet* (*(mc::protocol::Protocol, mc::protocol::State, mc::DataBuffer, int, mc::core::Connection*))(mc::protocol::Protocol&, mc::protocol::State, mc::DataBuffer, long long unsigned int, mc::core::Connection*)>'|
C:\msys\mingw64\include\c++\7.1.0\future|1744|note: candidate: template<class _Fn, class ... _Args> std::future<typename std::result_of<typename std::decay<_Tp>::type(typename std::decay<_Args>::type ...)>::type> std::async(_Fn&&, _Args&& ...)|
C:\msys\mingw64\include\c++\7.1.0\future|1744|note:   template argument deduction/substitution failed:|
C:\DISK\CODE\mclib-master\mclib\src\mclib\core\Connection.cpp|256|required from here|
C:\msys\mingw64\include\c++\7.1.0\future|1744|error: no type named 'type' in 'class std::result_of<std::launch(mc::protocol::packets::Packet* (*)(mc::protocol::Protocol&, mc::protocol::State, mc::DataBuffer, long long unsigned int, mc::core::Connection*), mc::protocol::Protocol, mc::protocol::State, mc::DataBuffer, int, mc::core::Connection*)>'|
||=== Build failed: 3 error(s), 2 warning(s) (0 minute(s), 13 second(s)) ===|

Wywala przy tej linijce:
return std::async( std::launch::async, & protocol::packets::PacketFactory::CreatePacket, m_Protocol, m_ProtocolState, decompressed, length.GetInt(), this );


Dlaczego to nie działa i jak to naprawić?
Co on bredzi, że nie ma jakiej funkcji wywołać?
Czy to przez przyszłe zmiany w standardzie?

P-163524
Gibas11
» 2017-07-24 08:27:32
this
 nie powinno być pierwszym parametrem po
& protocol::packets::PacketFactory::CreatePacket
?
//Edit: O, teraz zauważyłem że to metoda innej klasy. Czym jest m_Protocol?
P-163526
mokrowski
» 2017-07-24 10:26:12
Metoda CreatePacket nie jest statyczna. W wywołaniu async powinieneś przekazać na rzecz jakiego obiektu jest wywoływana.
P-163528
Rashmistrz
Temat założony przez niniejszego użytkownika
» 2017-07-25 01:17:29
Trochę namieszałem... :F


Metoda CreatePacket nie jest statyczna.
Huh?
C/C++
class PacketFactory {
public:
    static MCLIB_API Packet * CreatePacket( Protocol & protocol, State state, DataBuffer data, std::size_t length, core::Connection * connection = nullptr );
    static void MCLIB_API FreePacket( Packet * packet );
};

W wywołaniu async powinieneś przekazać na rzecz jakiego obiektu jest wywoływana.
Nie powinna... :F BTW Jak to zrobić? Wystarczy dodać wtedy wskaźnik na obiekt tej metody?

Czym jest m_Protocol?
Przechowuje ID typów pakietów i je zwraca.
Każdy połączenie ma referencję na daną wersję protokołu.
Jak chce się użyć innej wersji to wystarczy przysłonić. :F

C/C++
class Protocol {
public:
    typedef std::unordered_map < State, PacketMap > StateMap;
   
protected:
    StateMap m_InboundMap;
    Version m_Version;
   
public:
    Protocol( Version version, StateMap inbound )
        : m_InboundMap( inbound )
         , m_Version( version )
    {
       
    }
   
    virtual Version GetVersion() const noexcept { return m_Version; }
   
    // Creates an inbound packet from state and packet id
    virtual packets::InboundPacket * CreateInboundPacket( State state, s32 id );
   
    // Convert the protocol id into a protocol agnostic id.
    // This is used as the dispatching id.
    bool GetAgnosticId( State state, s32 protocolId, s32 & agnosticId );
   
    // Handshake
    virtual s32 GetPacketId( packets::out::HandshakePacket ) { return 0x00; }
   
    // Login
    virtual s32 GetPacketId( packets::out::LoginStartPacket ) { return 0x00; }
    virtual s32 GetPacketId( packets::out::EncryptionResponsePacket ) { return 0x01; }
   
    // Status
    virtual s32 GetPacketId( packets::out::status::RequestPacket ) { return 0x00; }
    virtual s32 GetPacketId( packets::out::status::PingPacket ) { return 0x01; }
   
    // Play
    virtual s32 GetPacketId( packets::out::TeleportConfirmPacket ) { return 0x00; }
    virtual s32 GetPacketId( packets::out::TabCompletePacket ) { return 0x01; }
    virtual s32 GetPacketId( packets::out::ChatPacket ) { return 0x02; }
    // ... wyciąłem bo ilość
    virtual s32 GetPacketId( packets::out::SpectatePacket ) { return 0x1B; }
    virtual s32 GetPacketId( packets::out::PlayerBlockPlacementPacket ) { return 0x1C; }
    virtual s32 GetPacketId( packets::out::UseItemPacket ) { return 0x1D; }
   
    virtual s32 GetPacketId( packets::out::PrepareCraftingGridPacket ) { throw UnsupportedPacketException( "PrepareCraftingGridPacket requires protocol 1.12.0" ); }
    virtual s32 GetPacketId( packets::out::CraftingBookDataPacket ) { throw UnsupportedPacketException( "CraftingBookDataPacket requires protocol 1.12.0" ); }
    virtual s32 GetPacketId( packets::out::AdvancementTabPacket ) { throw UnsupportedPacketException( "AdvancementTabPacket requires protocol 1.12.0" ); }
   
    static Protocol & GetProtocol( Version version );
};
P-163542
Monika90
» 2017-07-25 10:51:00
m_protocol przekazujemy przez std::ref
C/C++
return std::async( std::launch::async, & protocol::packets::PacketFactory::CreatePacket, std::ref( m_Protocol ), m_ProtocolState, decompressed, length.GetInt(), this );
P-163547
Rashmistrz
Temat założony przez niniejszego użytkownika
» 2017-07-26 04:44:47
m_protocol przekazujemy przez std::ref
Właśnie to rozwiązuje całą sprawę...
Dziękuję serdeczne pani Moniko. C:

Wszystko przez to, że CreatePacket przyjmuje protocol
przez referencję a async już nie, a dalej to już nie rozumiem...  :D

Wystarczyło tylko opakować w std::ref() argument, który
miał być przekazany przez referencję do oryginalnej metody.

Jeszcze raz dziękuję wszystkim za udzielone odpowiedzi. :)
P-163574
« 1 »
  Strona 1 z 1