티스토리 툴바


포트폴리오/libSOPT2010/03/24 16:06
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
Posted by BONZOA
TAG , ,