Skip to content

Commit

Permalink
A new example for so_agent_name added.
Browse files Browse the repository at this point in the history
  • Loading branch information
eao197 committed Mar 19, 2024
1 parent 4856bd3 commit 5066e39
Show file tree
Hide file tree
Showing 10 changed files with 231 additions and 1 deletion.
1 change: 1 addition & 0 deletions dev/sample/so_5/CMakeLists.txt
Expand Up @@ -81,4 +81,5 @@ add_subdirectory(unique_subscribers_mbox)
add_subdirectory(introduce_named_mbox)
add_subdirectory(child_soenv)
add_subdirectory(bind_transformer)
add_subdirectory(agent_name)

9 changes: 9 additions & 0 deletions dev/sample/so_5/agent_name/CMakeLists.txt
@@ -0,0 +1,9 @@
set(SAMPLE sample.so_5.agent_name)
add_executable(${SAMPLE} main.cpp)
target_link_libraries(${SAMPLE} sobjectizer::SharedLib)
install(TARGETS ${SAMPLE} DESTINATION bin)

set(SAMPLE_S sample.so_5.agent_name_s)
add_executable(${SAMPLE_S} main.cpp)
target_link_libraries(${SAMPLE_S} sobjectizer::StaticLib)
install(TARGETS ${SAMPLE_S} DESTINATION bin)
190 changes: 190 additions & 0 deletions dev/sample/so_5/agent_name/main.cpp
@@ -0,0 +1,190 @@
/*
* A sample of usage of agent name.
*/

#include <so_5/all.hpp>

#include <iostream>
#include <set>

// Name of mbox for sending information to agents registry.
const std::string registry_mbox_name{ "agents_registry" };

// Agent that plays role of agents registry.
class agents_registry final : public so_5::agent_t
{
public:
// Message for informing about start of an agent.
struct agent_started final : public so_5::message_t
{
const std::string m_name;

agent_started( std::string name ) : m_name{ std::move(name) }
{}
};

// Message for informing that agent finished its work.
struct agent_finished final : public so_5::message_t
{
const std::string m_name;

agent_finished( std::string name ) : m_name{ std::move(name) }
{}
};

agents_registry( context_t ctx )
: so_5::agent_t{ std::move(ctx) }
{}

void so_define_agent() override
{
so_subscribe( so_environment().create_mbox( registry_mbox_name ) )
.event( &agents_registry::evt_agent_started )
.event( &agents_registry::evt_agent_finished )
;

so_subscribe_self()
.event( &agents_registry::evt_show_registry )
;
}

void so_evt_start() override
{
// Initiate periodic message for showing the content of the registry.
m_show_timer = so_5::send_periodic< show_registry >( *this,
std::chrono::milliseconds{ 20 },
std::chrono::milliseconds{ 20 } );
}

private:
// Periodic signal for showing the current content of the registry.
struct show_registry final : public so_5::signal_t {};

// A list of currently working agents.
std::set< std::string > m_registry;

// Timer for showing the current content of the registry.
so_5::timer_id_t m_show_timer;

void evt_agent_started( mhood_t<agent_started> cmd )
{
m_registry.insert( cmd->m_name );

std::cout << " started: " << cmd->m_name << std::endl;
}

void evt_agent_finished( mhood_t<agent_finished> cmd )
{
m_registry.erase( cmd->m_name );

std::cout << "finished: " << cmd->m_name << std::endl;

if( m_registry.empty() )
// It's time to complete.
so_deregister_agent_coop_normally();
}

void evt_show_registry( mhood_t<show_registry> )
{
std::cout << "--- registry begin ---" << std::endl;
for( const auto & name : m_registry )
std::cout << " " << name << std::endl;
std::cout << "--- registry end ---" << std::endl;
}
};

// Base class for worker. Agents of this type have no names.
class simple_worker : public so_5::agent_t
{
public:
simple_worker( context_t ctx, std::chrono::milliseconds work_time )
: so_5::agent_t{ std::move(ctx) }
, m_work_time{ work_time }
{}

void so_define_agent() override
{
so_subscribe_self().event( &simple_worker::evt_done );
}

void so_evt_start() override
{
// Should inform about the start.
so_5::send< agents_registry::agent_started >(
so_environment().create_mbox( registry_mbox_name ),
so_agent_name().to_string() );

// Limit the work time.
so_5::send_delayed< done >( *this, m_work_time );
}

void so_evt_finish() override
{
// Should inform about the finish.
so_5::send< agents_registry::agent_finished >(
so_environment().create_mbox( registry_mbox_name ),
so_agent_name().to_string() );
}

private:
// Signal for limiting work time of the agent.
struct done final : public so_5::signal_t {};

// How long the agent should work.
const std::chrono::milliseconds m_work_time;

void evt_done( mhood_t<done> )
{
so_deregister_agent_coop_normally();
}
};

// Type of worker with name.
//
// It's derived from simple_worker just to make example code shorter.
class named_worker : public simple_worker
{
public:
named_worker( context_t ctx, std::string_view name, std::chrono::milliseconds work_time )
: simple_worker{ ctx + name_for_agent(name), work_time }
{}

// There is no need to define something else.
};

int main()
{
try
{
// Starting SObjectizer.
so_5::launch(
// A function for SO Environment initialization.
[]( so_5::environment_t & env )
{
// Starting the registry.
env.register_agent_as_coop(
env.make_agent< agents_registry >() );

// Starting workers.
using namespace std::chrono_literals;
env.register_agent_as_coop(
env.make_agent< simple_worker >( 30ms ) );
env.register_agent_as_coop(
env.make_agent< simple_worker >( 50ms ) );
env.register_agent_as_coop(
env.make_agent< named_worker >( "Alice", 50ms ) );
env.register_agent_as_coop(
env.make_agent< simple_worker >( 70ms ) );
env.register_agent_as_coop(
env.make_agent< named_worker >( "Bob", 90ms ) );
} );
}
catch( const std::exception & ex )
{
std::cerr << "Error: " << ex.what() << std::endl;
return 1;
}

return 0;
}

10 changes: 10 additions & 0 deletions dev/sample/so_5/agent_name/prj.rb
@@ -0,0 +1,10 @@
require 'mxx_ru/cpp'

MxxRu::Cpp::exe_target {

required_prj 'so_5/prj.rb'
target 'sample.so_5.agent_name'

cpp_source 'main.cpp'
}

10 changes: 10 additions & 0 deletions dev/sample/so_5/agent_name/prj_s.rb
@@ -0,0 +1,10 @@
require 'mxx_ru/cpp'

MxxRu::Cpp::exe_target {

required_prj 'so_5/prj_s.rb'
target 'sample.so_5.agent_name_s'

cpp_source 'main.cpp'
}

1 change: 1 addition & 0 deletions dev/sample/so_5/build_samples.rb
Expand Up @@ -87,4 +87,5 @@
example[ 'introduce_named_mbox' ]
example[ 'child_soenv' ]
example[ 'bind_transformer' ]
example[ 'agent_name' ]
}
3 changes: 3 additions & 0 deletions dev/test/so_5/samples_as_unit_tests/agent_name-static.ut.rb
@@ -0,0 +1,3 @@
require_relative 'details.rb'

setup_sample_as_unit_test
3 changes: 3 additions & 0 deletions dev/test/so_5/samples_as_unit_tests/agent_name.ut.rb
@@ -0,0 +1,3 @@
require_relative 'details.rb'

setup_sample_as_unit_test
4 changes: 3 additions & 1 deletion dev/test/so_5/samples_as_unit_tests/build_tests.rb
Expand Up @@ -112,5 +112,7 @@

required_prj "#{path}/bind_transformer.ut.rb"
required_prj "#{path}/bind_transformer-static.ut.rb"
}

required_prj "#{path}/agent_name.ut.rb"
required_prj "#{path}/agent_name-static.ut.rb"
}
1 change: 1 addition & 0 deletions doxygen/dox/so_5/samples.dox
@@ -1,5 +1,6 @@
/*!
* \example so_5/adv_thread_pool_fifo/main.cpp
* \example so_5/agent_name/main.cpp
* \example so_5/bind_transformer/main.cpp
* \example so_5/blinking_led/main.cpp
* \example so_5/chameneos_prealloc_msgs/main.cpp
Expand Down

0 comments on commit 5066e39

Please sign in to comment.