Skip to content

Commit

Permalink
refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
Alex0vSky committed Jun 8, 2024
1 parent 69dbfbd commit b816379
Show file tree
Hide file tree
Showing 9 changed files with 148 additions and 162 deletions.
34 changes: 5 additions & 29 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,12 +66,13 @@ static_assert( std::is_assignable_v< SDL_Point, Acme::SDL_Point >
namespace pb = boost::process::v2;
boost::asio::io_context ctx;
auto pathCurrentProcess = std::filesystem::canonical( args[ 0 ] );
std::unique_ptr< std::thread > terminateSelfIfParent;
struct jthread : std::thread { using std::thread::thread; ~jthread() { join( ); } };
std::unique_ptr< jthread > terminateSelfIfParent;
bool isServer = ( argc > 1 );
if ( !isServer )
if ( !isServer ) {
pb::process( ctx, pathCurrentProcess, { std::to_string( pb::current_pid( ) ) } ).detach( );
else {
terminateSelfIfParent = std::make_unique< std::thread >( [&ctx, pidParent = pb::pid_type( std::stoi( args[ 1 ] ) )] {
} else {
terminateSelfIfParent = std::make_unique< jthread >( [&ctx, pidParent = pb::pid_type( std::stoi( args[ 1 ] ) )] {
//__debugbreak( );
while ( std::this_thread::sleep_for( std::chrono::milliseconds( 300 ) ), true )
try {
Expand All @@ -82,29 +83,6 @@ static_assert( std::is_assignable_v< SDL_Point, Acme::SDL_Point >
}
std::exit( 0 );
} );
//boost::process::v2::process parent( ctx.get_executor( ), pidParent );
//while ( true ) {
// std::this_thread::sleep_for( std::chrono::milliseconds( 300 ) );
// boost::system::error_code ec;
// bool b;
// try {
// b = parent.running( ec );
// if ( b )
// __nop( );
// else
// __nop( );
// if ( boost::system::errc::io_error == ec )
// __nop( );
// else
// __nop( );
// __nop( );
// } catch (boost::system::system_error const& system_error) {
// auto code = system_error.code( );
// std::string message = system_error.what( );
// __nop( );
// }
//}
__nop( );
}
#endif // A0S_SCHEMA_CISTA

Expand Down Expand Up @@ -192,8 +170,6 @@ static_assert( std::is_assignable_v< SDL_Point, Acme::SDL_Point >
App app;
#ifdef A0S_SCHEMA_CISTA
app.run( isServer );
if ( terminateSelfIfParent )
terminateSelfIfParent ->join( );
#else // A0S_SCHEMA_CISTA
app.run();
#endif // A0S_SCHEMA_CISTA
Expand Down
100 changes: 43 additions & 57 deletions src/net/net.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,6 @@ void NetPlayer::update(Uint32 dt) {
stop = false;
}

NetGame::NetGame(int players_count, bool isServer) :
Game( 1 )
, m_isServer( isServer )
{}

template<typename T1, typename T2>
void assignment(T1& lhs, T2 const& rhs) {
lhs.reserve( rhs.size( ) );
Expand All @@ -66,65 +61,56 @@ void assignment(T1& lhs, T2 const& rhs) {
);
}

NetGame::NetGame(int players_count, bool isServer) :
Game( 1 )
, m_isServer( isServer )
, m_tx( [this](Tx *tx) mutable ->Tx::awaitable {
cista::byte_buf buffer;
if ( co_await tx ->clientSide( Tx::Command::GetFullMap, &buffer ) ) {
level_t level = *deserialize_< level_t >( buffer );
std::copy( level.begin( ), level.end( ), NetGame::m_level.begin( ) );

forEachLevel_( [this](int i, int j, Object *&object) {
auto &ref = NetGame::m_level[ i ][ j ];
if ( auto* pval = std::get_if< Object >( &ref ) )
*object = *pval;
if ( auto* pval = std::get_if< Brick >( &ref ) )
*object = *pval;
} );
//std::vector< std::vector< element_t > > level1_;
//assignment( level1_, NetGame::m_level ); // tmp check
//__nop( );
}
if ( co_await tx ->clientSide( Tx::Command::Something, &buffer ) )
*m_playerPtr = *deserialize_< NetPlayer >( buffer );
}
, [this](Tx *tx) mutable ->Tx::awaitable {
forEachLevel_( [this](int i, int j, Object *&object) {
auto &ref = NetGame::m_level[ i ][ j ];
if ( Brick* brick = dynamic_cast< Brick* >( object ) )
ref = *brick;
else
ref = *object;
} );
//std::vector< std::vector< element_t > > level_;
//assignment( level_, NetGame::m_level ); // tmp check
co_await tx ->serverSide( )
->on( Tx::Command::GetFullMap, serialize_( NetGame::m_level ) )
->on( Tx::Command::Something, serialize_( *m_playerPtr ) )
->finish( )
;
}
)
{}

void NetGame::update(Uint32 dt) {
if ( m_playerPtr ) {
//NetPlayer *player;
//cista::byte_buf buffer = serialize( *m_playerPtr );
//player = deserialize< c_MODE >( buffer );
//*m_playerPtr = *player;

using Tx = tx::Exchanger;
Tx::function_t clientCode, serverCode;
if ( !m_isServer )
clientCode = [this](Tx *tx) mutable ->Tx::awaitable {
cista::byte_buf buffer;
if ( co_await tx ->clientSide( Tx::Command::GetFullMap, &buffer ) ) {

level_t level = *deserialize< level_t >( buffer );

//std::vector< std::vector< element_t > > level0_;
//assignment( level0_, level ); // tmp check
//__nop( );

std::copy( level.begin( ), level.end( ), NetGame::m_level.begin( ) );

forEachLevel( [this](int i, int j, Object *&object) {
auto &ref = NetGame::m_level[ i ][ j ];
if ( auto* pval = std::get_if< Object >( &ref ) ) {
*object = *pval;
}
if ( auto* pval = std::get_if< Brick >( &ref ) ) {
*object = *pval;
}
} );

//std::vector< std::vector< element_t > > level1_;
//assignment( level1_, NetGame::m_level ); // tmp check
//__nop( );
}
if ( co_await tx ->clientSide( Tx::Command::Something, &buffer ) )
*m_playerPtr = *deserialize< NetPlayer >( buffer );
};
else
serverCode = [this](Tx *tx) mutable ->Tx::awaitable {
forEachLevel( [this](int i, int j, Object *&object) {
auto &ref = NetGame::m_level[ i ][ j ];
if ( Brick* brick = dynamic_cast< Brick* >( object ) )
ref = *brick;
else
ref = *object;
} );

//std::vector< std::vector< element_t > > level_;
//assignment( level_, NetGame::m_level ); // tmp check

co_await tx ->serverSide( )
->on( Tx::Command::GetFullMap, serialize( NetGame::m_level ) )
->on( Tx::Command::Something, serialize( *m_playerPtr ) )
->finish( )
;
};
m_tx.update( clientCode, serverCode );
m_tx.update( m_isServer );
}
// Initial rewrite
if ( !m_playerPtr ) {
Expand Down
21 changes: 7 additions & 14 deletions src/net/net.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,6 @@ class NetGame : public ::Game {
| cista::mode::WITH_INTEGRITY
| cista::mode::DEEP_CHECK
;
template <class C>
struct TypeIdentifier {
constexpr static int _id{ };
constexpr static auto id() {
return &_id;
}
};
static constexpr auto c_idBrick = TypeIdentifier< Brick >::id( );
static constexpr auto c_idObject = TypeIdentifier< Object >::id( );

public:
/**
Expand All @@ -36,31 +27,33 @@ class NetGame : public ::Game {
NetGame(int players_count, bool isServer);

void draw() override;
void update(Uint32 dt) override;

// default-constructed variant holds a value of its first alternative: nullptr_t
using element_t = std::variant< nullptr_t, Object, Brick >;

private:
template<typename T> using container_t = cista::offset::vector< T >;
using level_t = container_t< container_t< element_t > >;
using Tx = tx::Exchanger;

bool m_isServer;
// TODO(alex): uglyAndFast, omitt `static`, delete in App::run
inline static std::shared_ptr< NetPlayer > m_playerPtr;
tx::Exchanger m_tx;
Tx m_tx;
level_t m_level;

template <typename... Args>
static constexpr auto serialize(Args&&... args) {
static constexpr auto serialize_(Args&&... args) {
return cista::serialize< c_MODE >( std::forward< Args >( args )... );
}
template <typename T>
static constexpr auto deserialize(cista::byte_buf const& buffer) {
static constexpr auto deserialize_(cista::byte_buf const& buffer) {
return cista::deserialize< T, c_MODE >( buffer);
}

using func_t = std::function< void(int i, int j, Object *&object) >;
void forEachLevel(func_t cb) {
void forEachLevel_(func_t cb) {
std::for_each( Game::m_level.begin( ), Game::m_level.end( ), [this, cb](std::vector<Object *> &element) {
int i = &element - &Game::m_level[ 0 ];
int j = -1;
Expand All @@ -72,6 +65,6 @@ class NetGame : public ::Game {
}
} );
}
void update(Uint32 dt) override;
void setTxUpdate_();
};
} // namespace net
56 changes: 33 additions & 23 deletions src/net/tx/base.cpp
Original file line number Diff line number Diff line change
@@ -1,35 +1,45 @@
#pragma once // Copyright 2024 Alex0vSky (https://github.com/Alex0vSky), Copyright 2015-2021 (https://github.com/KrystianKaluzny/Tanks)
#include "net/tx/base.h"

namespace net::tx {
Base::Base() :
Base::Base(function_t client, function_t server) :
m_ioContext( 1 )
, c_endpointClient{ boost::asio::ip::address_v4( c_host ), c_port }
, m_acceptor( m_ioContext, c_endpointServer )
, m_acceptor( m_ioContext )
, m_client( client ), m_server( server )
, m_exchanger( reinterpret_cast< Exchanger * >( this ) )
, m_socketClient( m_ioContext ), m_socketServer( m_ioContext )
{}

void Base::update(function_t client, function_t server) {
bool stop = false;
if ( server )
co_spawn_( [this, server]() mutable ->awaitable {
co_await server( reinterpret_cast< Exchanger * >( this ) );
void Base::update(bool isServer) {
boost::asio::io_context::count_type count;
if (
!isServer &&
!m_socketClient.is_open( ) ) {
co_spawn_( [this]() mutable ->awaitable {
m_acceptor.open( c_endpointServer.protocol( ) ), m_acceptor.bind( c_endpointServer ), m_acceptor.listen( 1 );
do m_socketClient = std::get< 1 >( co_await m_acceptor.async_accept( c_tuple ) );
while ( !m_socketClient.is_open( ) && sleep_( ) );
__nop( );
} );
else
m_acceptor.close( );
if ( client )
co_spawn_( [this, client, &stop]() mutable ->awaitable {
co_await client( reinterpret_cast< Exchanger * >( this ) );
stop = true;
}
if (
isServer &&
!m_socketServer.is_open( ) ) {
co_spawn_( [this]() mutable ->awaitable {
do co_await m_socketServer.async_connect( c_endpointClient, c_tuple );
while ( !m_socketServer.is_open( ) && sleep_( ) );
__nop( );
} );
while ( true ) {
m_ioContext.run_one_for( std::chrono::milliseconds{ 300 } );
if ( stop ) {
if ( server ) {
m_acceptor.cancel( );
m_ioContext.run( );
}
break;
}
}
count = m_ioContext.run( );
m_ioContext.restart( );
__nop( );

if ( !isServer )
co_spawn_( m_client( m_exchanger ) );
else
co_spawn_( m_server( m_exchanger ) );
count = m_ioContext.run( );
__nop( );
}
} // namespace net::tx
13 changes: 10 additions & 3 deletions src/net/tx/base.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,20 @@ class Base {
/**
* Call client and server simultaneously
*/
void update(function_t client, function_t server);
void update(bool isServer);

protected:
/**
* Create network transmission
*/
Base();
Base(function_t client, function_t server);

protected:
boost::asio::io_context m_ioContext;
const tcp::endpoint c_endpointClient, c_endpointServer{ tcp::v4( ), c_port };
tcp::acceptor m_acceptor;
function_t m_client, m_server;
Exchanger *m_exchanger;
tcp::socket m_socketClient, m_socketServer;
static constexpr auto c_detached = boost::asio::detached;
static constexpr auto c_tuple = as_tuple( boost::asio::use_awaitable_t{ } );

Expand All @@ -43,5 +46,9 @@ class Base {
co_spawn_(F&& f) {
return co_spawn( m_ioContext.get_executor( ), std::forward<F>(f), c_detached );
}

bool sleep_() {
return std::this_thread::sleep_for( std::chrono::milliseconds{ 300 } ), true;
}
};
} // namespace net::tx
28 changes: 20 additions & 8 deletions src/net/tx/commander.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,28 @@
#include "net/tx/commander.h"

namespace net::tx {
boost::asio::awaitable<Commander::Command> Commander::readCommand_(Base::tcp::socket &socket) {
boost::asio::awaitable<Commander::Command> Commander::readCommand_(Base::tcp::socket &socket, commandsBuffer_t const& commandsBuffer) {
command_t commandRaw;
auto [error, n] = co_await socket.async_read_some( boost::asio::buffer( &commandRaw, c_sizeof ), Base::c_tuple );
if ( n == c_sizeof && !error )
co_return static_cast< Command >( commandRaw );
co_return Command::undefined;
auto [error1, n] = co_await socket.async_read_some( boost::asio::buffer( &commandRaw, c_sizeofCommand ), Base::c_tuple );
if ( n != c_sizeofCommand || error1 )
co_return Command::undefined;
auto command = static_cast< Command >( commandRaw );
answerSize_t answerSize = 0;
if ( auto it = commandsBuffer.find( command ); it != commandsBuffer.end( ) )
answerSize = it ->second.size( );
auto [error2, nwritten] = co_await boost::asio::async_write( socket, boost::asio::buffer( &answerSize, c_sizeofAnswer ), Base::c_tuple );
if ( nwritten != c_sizeofAnswer || error2 )
co_return Command::undefined;
co_return command;
}
boost::asio::awaitable<bool> Commander::writeCommand_(Base::tcp::socket &socket, Command command) {
boost::asio::awaitable<bool> Commander::writeCommand_(Base::tcp::socket &socket, Command command, answerSize_t *answerSize) {
const auto commandRaw = static_cast< command_t >( command );
auto [error, nwritten] = co_await boost::asio::async_write( socket, boost::asio::buffer( &commandRaw, c_sizeof ), Base::c_tuple );
co_return ( nwritten == c_sizeof && !error );
auto [error1, nwritten] = co_await boost::asio::async_write( socket, boost::asio::buffer( &commandRaw, c_sizeofCommand ), Base::c_tuple );
if ( nwritten != c_sizeofCommand || error1 )
co_return false;
auto [error2, n] = co_await socket.async_read_some( boost::asio::buffer( answerSize, c_sizeofAnswer ), Base::c_tuple );
if ( n != c_sizeofAnswer || error2 )
co_return false;
co_return true;
}
} // namespace net::tx
Loading

0 comments on commit b816379

Please sign in to comment.