sample/inheritance/main.cpp

/*
  Демонстрация наследования агентов.

  Определяется базовый класс транзакции. От него
  производятся классы конкретной транзакции и
  прерываемой по таймеру транзакции. От классов
  конкретной транзакции и прерываемой по таймеру
  транзакции производится класс конкретной,
  прерываемой по таймеру транзакции.
*/

#include <iostream>
#include <memory>

#include <ace/OS_main.h>

#include <so_4/rt/h/rt.hpp>
#include <so_4/api/h/api.hpp>

#include <so_4/timer_thread/simple/h/pub.hpp>
#include <so_4/disp/one_thread/h/pub.hpp>

/*
  Базовый класс для транзакции.

  Играет роль интерфейса, т.к. только определяет основные
  сообщения и состояния. Но не выполняет никаких действий.

  Виртуально наследуется от so_4::rt::agent_t, т.к.
  впоследствии будет использоваться во множественном
  наследовании.
*/
class a_trx_t :
  public virtual so_4::rt::agent_t
{
  typedef so_4::rt::agent_t agent_type_t;
  public :
    a_trx_t();
    virtual ~a_trx_t();

    virtual const char *
    so_query_type() const;

    virtual void
    so_on_subscription();

    // Сообщение о начале транзакции.
    struct  msg_start {};

    // Сообщение о необходимости завершить
    // транзакцию с сохранением всех изменений.
    struct  msg_commit {};

    // Сообщение о необходимости откатить
    // транзакцию в начальное состояние.
    struct  msg_rollback {};

  protected :
    // Реальная подписка.
    /*
      Ничего не делает, но введен для того,
      чтобы при множественном наследовании
      избежать ошибки множественного
      вызова a_trx_t::so_on_subscription().
    */
    void
    do_subscription();
};

SOL4_CLASS_START( a_trx_t )

  SOL4_MSG_START( msg_start, a_trx_t::msg_start )
  SOL4_MSG_FINISH()

  SOL4_MSG_START( msg_commit, a_trx_t::msg_commit )
  SOL4_MSG_FINISH()

  SOL4_MSG_START( msg_rollback, a_trx_t::msg_rollback )
  SOL4_MSG_FINISH()

SOL4_CLASS_FINISH()

a_trx_t::a_trx_t()
  :
    agent_type_t( "a_trx" )
{
}

a_trx_t::~a_trx_t()
{
}

void
a_trx_t::so_on_subscription()
{
  do_subscription();
}

void
a_trx_t::do_subscription()
{
}


/*
  Класс конкретной транзакции, которая выполняет
  какую-то работу.

  Виртуально производится от a_trx_t, т.к. впоследствии
  будет использоваться во множественном наследовании.
*/
class a_concrete_trx_t :
  public virtual a_trx_t
{
  typedef so_4::rt::agent_t agent_type_t;
  public :
    a_concrete_trx_t(
      // Время (в миллисекундах) через которое
      // будет сымитировано сообщение msg_commit.
      unsigned int commit_timeout,
      // Время (в миллисекундах) через которое
      // будет сымитировано сообщение msg_rollback.
      unsigned int rollback_timeout );
    virtual ~a_concrete_trx_t();

    virtual const char *
    so_query_type() const;

    virtual void
    so_on_subscription();

    /*
      Реакция на появление агента в системе.

      Для имитации работы начинает транзакцию.
    */
    void
    evt_start();

    /*
      Начинает транзакцию.
    */
    void
    evt_trx_start();

    /*
      Подтверждает транзакцию.
    */
    void
    evt_trx_commit();

    /*
      Откатывает транзакцию.
    */
    void
    evt_trx_rollback();

  protected :
    // Реальная подписка.
    void
    do_subscription();

  private :
    // Время (в миллисекундах) через которое
    // будет сымитировано сообщение msg_commit.
    unsigned int m_commit_timeout;
    // Время (в миллисекундах) через которое
    // будет сымитировано сообщение msg_rollback.
    unsigned int m_rollback_timeout;
};

SOL4_CLASS_START( a_concrete_trx_t )
  // Указываем наследование.
  SOL4_SUPER_CLASS( a_trx_t )

  // Поскольку есть наследование, нужно
  // сразу определить начальное состояние.
  SOL4_INITIAL_STATE( st_not_started )

  SOL4_EVENT( evt_start )
  SOL4_EVENT( evt_trx_start )
  SOL4_EVENT( evt_trx_commit )
  SOL4_EVENT( evt_trx_rollback )

  SOL4_STATE_START( st_not_started )
    SOL4_STATE_EVENT( evt_start )
    SOL4_STATE_EVENT( evt_trx_start )
  SOL4_STATE_FINISH()

  SOL4_STATE_START( st_started )
    SOL4_STATE_EVENT( evt_trx_commit )
    SOL4_STATE_EVENT( evt_trx_rollback )
  SOL4_STATE_FINISH()

  // Конечное состояние, в которое осуществляется
  // переход по подтверждению транзакции.
  SOL4_STATE_START( st_commited )
  SOL4_STATE_FINISH()

SOL4_CLASS_FINISH()

a_concrete_trx_t::a_concrete_trx_t(
  unsigned int commit_timeout,
  unsigned int rollback_timeout )
:
  agent_type_t( "a_concrete_trx" ),
  m_commit_timeout( commit_timeout ),
  m_rollback_timeout( rollback_timeout )
{
  std::cout << "commit_timeout: " << commit_timeout
    << "\nrollback_timeout: " << rollback_timeout
    << std::endl;
}

a_concrete_trx_t::~a_concrete_trx_t()
{
}

void
a_concrete_trx_t::so_on_subscription()
{
  a_trx_t::do_subscription();
  do_subscription();
}

void
a_concrete_trx_t::evt_start()
{
  // Имитируем начало транзакции.
  so_4::api::send_msg( so_query_name(), "msg_start" );

  // Имитируем успешное завершение транзакции.
  so_4::api::send_msg( so_query_name(), "msg_commit", 0,
    so_query_name(), m_commit_timeout );
  // Имитируем откат транзакции.
  so_4::api::send_msg( so_query_name(), "msg_rollback", 0,
    so_query_name(), m_rollback_timeout );
}

void
a_concrete_trx_t::evt_trx_start()
{
  // Начинаем транзакцию.
  so_change_state( "st_started" );

  std::cout << "trx started" << std::endl;
}

void
a_concrete_trx_t::evt_trx_commit()
{
  // Подтверждаем транзакцию.
  so_change_state( "st_commited" );

  std::cout << "trx commited" << std::endl;

  so_4::api::send_msg(
    so_4::rt::sobjectizer_agent_name(),
    "msg_normal_shutdown" );
}

void
a_concrete_trx_t::evt_trx_rollback()
{
  // Откатываем транзакцию.
  so_change_state( "st_not_started" );

  std::cout << "trx rolled back" << std::endl;

  so_4::api::send_msg(
    so_4::rt::sobjectizer_agent_name(),
    "msg_normal_shutdown" );
}

void
a_concrete_trx_t::do_subscription()
{
  so_subscribe( "evt_start",
    so_4::rt::sobjectizer_agent_name(), "msg_start" );

  so_subscribe( "evt_trx_start", "msg_start" );

  so_subscribe( "evt_trx_commit", "msg_commit" );

  so_subscribe( "evt_trx_rollback", "msg_rollback" );
}

/*
  Класс прерываемой по таймеру транзакции. Не
  выполняет никаких действий и предназначен
  быть примесью (mixin-ом) для конкретных
  классов транзакций.

  Виртуально производится от a_trx_t, т.к. впоследствии
  будет использоваться во множественном наследовании.
*/
class a_timed_trx_t :
  public virtual a_trx_t
{
  typedef so_4::rt::agent_t agent_type_t;
  public :
    a_timed_trx_t(
      // Время (в миллисекундах) через которое
      // будет работа транзакции будет прервана.
      unsigned int lifetime );
    virtual ~a_timed_trx_t();

    virtual const char *
    so_query_type() const;

    virtual void
    so_on_subscription();

    // Сообщение об истечении времени работы
    // транзакции.
    struct  msg_lifetime_left {};

    /*
      Реакция на истечение времени работы
      транзакции. Отсылает самому себе
      сообщение msg_rollback.
    */
    void
    evt_lifetime_left(
      const msg_lifetime_left * );

    /*
      Обработчик входа в состояние, означающее
      начало транзакции. Производный класс
      должен либо указать его в качестве обработчика
      входа в состояние, либо вызвать из собственного
      обработчика.
    */
    void
    on_enter_appropriate_state(
      const std::string & );

  protected :
    // Реальная подписка.
    void
    do_subscription();

  private :
    // Время (в миллисекундах) через которое
    // будет работа транзакции будет прервана.
    unsigned int m_lifetime;
};

SOL4_CLASS_START( a_timed_trx_t )
  // Указываем наследование.
  SOL4_SUPER_CLASS( a_trx_t )

  // Начальное состояние не указывается,
  // т.к. мы не вводим здесь своих состояний.

  SOL4_MSG_START( msg_lifetime_left,
    a_timed_trx_t::msg_lifetime_left )
  SOL4_MSG_FINISH()

  SOL4_EVENT_STC( evt_lifetime_left,
    a_timed_trx_t::msg_lifetime_left )

SOL4_CLASS_FINISH()

a_timed_trx_t::a_timed_trx_t(
  unsigned int lifetime )
  :
    agent_type_t( "a_timed_trx" ),
    m_lifetime( lifetime )
{
  std::cout << "lifetime: " << lifetime
    << std::endl;
}

a_timed_trx_t::~a_timed_trx_t()
{
}

void
a_timed_trx_t::so_on_subscription()
{
  a_trx_t::do_subscription();
  do_subscription();
}

void
a_timed_trx_t::evt_lifetime_left(
  const msg_lifetime_left * )
{
  // Транзакцию пора прерывать.
  so_4::api::send_msg( so_query_name(), "msg_rollback" );

  std::cout << "no time left" << std::endl;
}

void
a_timed_trx_t::on_enter_appropriate_state(
  const std::string & )
{
  // Начинаем отсчет времени работы транзакции.
  so_4::api::send_msg( so_query_name(), "msg_lifetime_left", 0,
    so_query_name(), m_lifetime );
}

void
a_timed_trx_t::do_subscription()
{
  so_subscribe( "evt_lifetime_left", "msg_lifetime_left" );
}

/*
  Класс конкретной, прерываемой по таймеру транзакции,
  которая выполняет какую-то работу.
*/
class a_concrete_timed_trx_t :
  public virtual a_concrete_trx_t,
  public virtual a_timed_trx_t
{
  typedef so_4::rt::agent_t agent_type_t;
  public :
    a_concrete_timed_trx_t(
      // Время (в миллисекундах) через которое
      // будет сымитировано сообщение msg_commit.
      unsigned int commit_timeout,
      // Время (в миллисекундах) через которое
      // будет сымитировано сообщение msg_rollback.
      unsigned int rollback_timeout,
      // Время (в миллисекундах) через которое
      // будет работа транзакции будет прервана.
      unsigned int lifetime );
    virtual ~a_concrete_timed_trx_t();

    virtual const char *
    so_query_type() const;

    virtual void
    so_on_subscription();

  protected :
    // Реальная подписка.
    /*
      Ничего не делает. Введен для единообразия
      и с расчетом на возможное наполнение в
      будущем.
    */
    void
    do_subscription();
};

SOL4_CLASS_START( a_concrete_timed_trx_t )
  // Указываем наследование.
  SOL4_SUPER_CLASS( a_concrete_trx_t )
  SOL4_SUPER_CLASS( a_timed_trx_t )

  // Поскольку есть наследование, нужно
  // сразу определить начальное состояние.
  SOL4_INITIAL_STATE( st_not_started )

  // Своих событий и состояний не вводится,
  // но событие st_started нужно преопределить
  // с учетом требований класса a_timed_trx_t.

  SOL4_STATE_START( st_started )
    SOL4_STATE_MERGE( a_concrete_trx_t, st_started )

    SOL4_STATE_EVENT( evt_lifetime_left )

    SOL4_STATE_ON_ENTER( on_enter_appropriate_state )
  SOL4_STATE_FINISH()

SOL4_CLASS_FINISH()

a_concrete_timed_trx_t::a_concrete_timed_trx_t(
  unsigned int commit_timeout,
  unsigned int rollback_timeout,
  unsigned int lifetime )
:
  agent_type_t( "a_concrete_timed_trx" ),
  a_concrete_trx_t( commit_timeout, rollback_timeout ),
  a_timed_trx_t( lifetime )
{
}

a_concrete_timed_trx_t::~a_concrete_timed_trx_t()
{
}

void
a_concrete_timed_trx_t::so_on_subscription()
{
  a_trx_t::do_subscription();
  a_concrete_trx_t::do_subscription();
  a_timed_trx_t::do_subscription();
  do_subscription();
}

void
a_concrete_timed_trx_t::do_subscription()
{
}

int
main( int, char ** )
{
  std::auto_ptr< so_4::timer_thread::timer_thread_t >
    timer_ptr( so_4::timer_thread::simple::create_timer_thread() );

  std::auto_ptr< so_4::rt::dispatcher_t >
    disp_ptr( so_4::disp::one_thread::create_disp( *timer_ptr ) );

  // Эти значения нужно варьировать, чтобы получать
  // различные результаты работы примера.
  a_concrete_timed_trx_t agent( 2500, 2000, 1500 );
  so_4::rt::agent_coop_t coop( agent );

  so_4::ret_code_t rc = so_4::api::start( *disp_ptr, &coop );
  if( rc ) {
    std::cerr << "start: " << rc << std::endl;
  }

  return int( rc );
}

Документация по SObjectizer v.4.4 'Тебуломста'. Последние изменения: Thu Sep 18 10:26:45 2008. Создано системой  doxygen1.5.6 Intervale SourceForge.net Logo