1. 개요
Executor 인터페이스 클래스.
송신된 Request_Handler task를 실행하는 인터페이스입니다. Executor을 상속하는 구현체는 각 task의 실행방식이나 스케쥴링방식을 구현합니다.
Executor 인터페이스는 task의 실행방식이나 스케쥴링방식으로부터 task의 전달을 분리하는 방법을 제공합니다. 예를들어, 서비스의 상제 구현을 담고 있는 call 메소드를 포함하는 Requet_Handler의 call 메소드를 직접호출하는 대신에, 아래와 같은 코드를 사용할수 있습니다.
| Executor executor = new Single_Executor; executor.execute(new Request_Handler()); |
다만, Executor 인터페이스에서 실행되는 task는 쓰레드 스케쥴링의 불규칙성으로 인하여 실행의 순서를 예측할수 없으며, 순서가 보장되어야 하는 task는 Executor를 상속하는 구현체중 하나인 Single_Executor를 이용한다면, 적어도 Executor에 전송되는 순서에 따라 FIFO 구조를 통해 순서실행보장을 받을수 있습니다.
Executor의 구현체는 Single_Executor, Fixed_Executor, LF_Executor가 있습니다. Single_Executor는 제외하고는, 모두 쓰레드풀을 사용하게 되며, 쓰레드풀의 크기는 Config객체의 EXECUTORS_DISPATH_THREAD_COUNT필드의 값입니다. Single_Executor의 경우 EXECUTORS_DISPATH_THREAD_COUNT필드의 값은 무시되며 쓰레드풀의 크기는 1 입니다.
2. Executor의 선언은 다음과 같습니다.
// -*- C++ -*-
//=============================================================================
/**
* @file executor.h
*
* $Id: executor.h Fri Mon 16 17:23:23 GMT+09:00 2009
*
* @author Copyright 2008-2009 SOPT(Shout Our Passion Together)
*/
//=============================================================================
#ifndef _EXECUTOR_DEFINE
#define _EXECUTOR_DEFINE
#if !defined (ACE_LACKS_PRAGMA_ONCE)
#pragma once
#endif
#include "ace/Task.h"
#include "ace/Synch.h"
#include "ace/Activation_Queue.h"
#include "ace/Method_Request.h"
#if defined(ACE_WIN32)
#include "sopt_export.h"
#elif
typedef SOPT_Export ACE_Export
#endif
namespace libsopt {
class Server;
class Request_Handler;
/**
* @class Executor
*
* @brief Executor 인터페이스 클래스.
*
* 송신된 Request_Handler task를 실행하는 인터페이스입니다.
* Executor을 상속하는 구현체는 각 task의 실행방식이나 스케쥴링방식을 구현합니다.
*
* Executor 인터페이스는 task의 실행방식이나 스케쥴링방식으로부터 task의 전달을
* 분리하는 방법을 제공합니다.
* 예를들어, 서비스의 상제 구현을 담고 있는 call 메소드를 포함하는 Requet_Handler의
* call 메소드를 직접호출하는 대신에, 아래와 같은 코드를 사용할수 있습니다.
*
* Executor executor = new Single_Executor;
* executor.execute(new Request_Handler());
* ...
*
* 다만, Executor 인터페이스에서 실행되는 task는 쓰레드 스케쥴링의 불규칙성으로 인하여
* 실행의 순서를 예측할수 없으며, 순서가 보장되어야 하는 task는 Executor를 상속하는 구현체중 하나인
* Single_Executor를 이용한다면, 적어도 Executor에 전송되는 순서에 따라 FIFO 구조를 통해
* 순서실행보장을 받을수 있습니다.
*
* Executor의 구현체는 Single_Executor, Fixed_Executor, LF_Executor가 있습니다.
* Single_Executor는 제외하고는, 모두 쓰레드풀을 사용하게 되며, 쓰레드풀의 크기는 Config객체의
* EXECUTORS_DISPATH_THREAD_COUNT필드의 값입니다.
* Single_Executor의 경우 EXECUTORS_DISPATH_THREAD_COUNT필드의 값은 무시되며 쓰레드풀의 크기는 1 입니다.
*/
class SOPT_Export Executor :
public ACE_Task<ACE_MT_SYNCH> {
protected :
/// Executor를 소유하는 Server 객체에 대한 포인터
Server *serv_;
/// 송신된 task를 저장하는 Queue
ACE_Activation_Queue request_q_;
/// Executor 타입
int executor_type_;
/// Executor 실행상태
volatile int executor_state_;
/// Executor를 상속하는 구현체를 위한 인터페이스 메소드
virtual int svc() = 0;
/**
* task가 실행된 이후, 리소스 정리를 위해 호출됩니다.
* Executor에서 사용되는 모든 리소스는 RefCount기법을 이용하며,
* 해당 메소드가 호출되면 task와 관련된 모든 리소의 RefCount에서 1이 감소합니다.
* RefCount가 0이된다면, 리소스는 해제될 것입니다.
*
* 관련 리소스에 대한 항목은 Request_Handler의 clear 메소드와
* Stream_Hanlder의 clear 메소드가 참고하기 바랍니다.
*
* @param r task 객체 포인터
* @param retval task 객체의 call메소드 반환값. retvalue이 0이 아니라면, task를 전송한
* Stream_Handler과 연결을 해제할 것입니다.
*/
void execute_done(Request_Handler *r, int retvalue);
public :
/**
* @enum EXECUTOR_TYPE
*
* @brief Executor의 타입
*/
enum EXECUTOR_TYPE { SINGLE_EXECUTOR = 0x01, FIXED_EXECUTOR, LEADER_FOLLOWER_EXECUTOR };
/**
* @enum EXECUTOR_STATE
*
* @brief Executor의 동작상태
*/
enum EXECUTOR_STATE { RUNNING = 0x01, STOPPING, STOPPED };
/**
* Executor 객체를 생성합니다.
*
* @param executor_type Executor 구현체의 타입
*/
explicit Executor(EXECUTOR_TYPE executor_type)
: request_q_(this->msg_queue()), executor_type_(executor_type), executor_state_(STOPPED)
{ request_q_.queue()->high_water_mark(ACE_INT32_MAX); }
/// 기본소멸자
virtual ~Executor()
{ /* empty */ }
/// Executor를 시작합니다.
int run_executor_process();
/// Executor를 정지합니다.
int end_executor_process();
/**
* task를 Executor로 전송합니다.
*
* @param r task 객체 포인터
* @param timeout task전송이 블록된다면, timeout만큼 대기합니다.
*
* @retval 0 성공.
* @retval -1 실패: errno를 확인할수 있습니다.
* - EWOULDBLOCK: timeout
* - ESHUTDOWN: Executor는 task를 수신할수 없습니다.
*/
int exexute(ACE_Method_Request *r, ACE_Time_Value *timeout = 0);
/// Executor에 보관중인 모든 task를 해제합니다.
void clear();
/**
* Executor의 실행상태를 확인합니다.
*
* @param state 확인할 상태
*
* @retval 1 Executor는 state 상태에 있습니다.
* @retval 0 Executor는 state 상태에 있지 않습니다.
*/
int check_executor_state(EXECUTOR_STATE state) const;
/**
* Executor의 실행상태를 변경합니다.
*
* @param to_ch_state 변경할 상태
*/
void change_executor_state(EXECUTOR_STATE to_ch_state);
/// return serv_;
Server *server() const
{ return serv_; }
/// serv_ = serv;
void server(Server *serv)
{ serv_ = serv; }
};
};
#endif
'포트폴리오 > libSOPT' 카테고리의 다른 글
| libSOPT다운로드 (0) | 2010/03/24 |
|---|---|
| libSOPT기반 echo server (0) | 2010/03/24 |
| libSOPT::Server (0) | 2010/03/24 |
| libSOPT::Executor (0) | 2010/03/24 |
| libSOPT::Request_Handler (0) | 2010/03/24 |
| libSOPT::Stream_Handler (0) | 2010/03/24 |
| libSOPT::Acceptor (0) | 2010/03/24 |
| libSOPT 소개 (0) | 2010/03/24 |
