æè¿ããããããã¡ã€ã«ãªãœãŒã¹ã§ãããããã°ã©ããŒã
ãã¹ããªãŒã ãæäœããããã«MMOãµãŒããŒã§äœã䜿çšããã®ã§ããïŒããšãã質åãããŸããã ããã°ã©ããŒã¯
Intel TBBã«åŸåããŠããŸããããåºæ¬çãªããªããã£ãã§ã¯ãªããã«ã¹ã¿ã ã¿ã¹ã¯ã¹ã±ãžã¥ãŒãªã³ã°ã«åŸåããŠããŸããã ãŸããTBBã®ããã«-ãŸãã倧äžå€«ã ãããŠå°ãåŸã«ãMMOãµãŒããŒã®ãœãŒã¹ã³ãŒããå¥ã®ããã°ã©ããŒãèŠãŸãããåœŒã¯æè¿ãã¢ãŒããã¯ãã£ãæ¹åããããã«æåããããã«å¯Ÿå¿ãå§ããŸããã ãŸããboostãªã©ã®ãµãŒãããŒãã£ã³ã³ããŒãã³ãã䜿çšãã代ããã«ãããã°ã©ããŒèªèº«ãæžããèªè»¢è»ããããããããŸããïŒããšãã°ãpthreadã®ã©ãããŒã®ã¯ã©ã¹ãããã¯2010幎ã§ã
boost.threadã¯ã»ãŒæšæºã§ãïŒã ã¿ã¹ã¯ã¹ã±ãžã¥ãŒã©ã䜿çšããã¹ã¬ããããŒã«ã®ãµããŒããå®è£
ãããŸããã ãã®ãããã¯ã¯ç§ã«ãšã£ãŠéåžžã«è峿·±ããã®ã§ãããã¿ã¹ã¯èšç»ïŒTBBãªã©ïŒã®æ¢è£œã®ãœãªã¥ãŒã·ã§ã³ã«é¢ããæ
å ±ãæãå§ãã
boost.taskãèŠã€ããŸããã
å®çŸ©
ã¿ã¹ã¯ã¯ãè«ççã«çµ±åãããã¢ã¯ã·ã§ã³ã®ã»ããã§ãã ã¿ã¹ã¯ã¹ã±ãžã¥ãŒã©ã¯ãã©ã®ã¹ã¬ããã§èª°ãã©ã®ç¬éã«å®è¡ããããéžæããããã®ç¹å®ã®æŠç¥ã«ãã£ãŠå°ãããã¿ã¹ã¯ãéåæçã«å®è¡ããŸãã
ã¿ã¹ã¯ã䜿çšãããšãéåžžã®ãããŒããæœè±¡åããããé«ãã¬ãã«ã§æäœã§ããŸãã
ãªãã¿ã¹ã¯ã¹ã±ãžã¥ãŒã©ãå¿
èŠãªã®ã§ããïŒ
çç¶ãµãŒããŒã¯ç空ã§ã©ã®ããã«æ©èœããŸããïŒ éåžžã«ã·ã³ãã«ïŒ
- ã¯ã©ã€ã¢ã³ããããªã¯ãšã¹ããæ¥ãŸã
- 圌ã¯åŠçãããŠããŸãïŒ
- è¿ä¿¡ãéä¿¡ããŸãã
ããã«ããµãŒããŒã§ã¯ã©ã€ã¢ã³ãã®ãªã¯ãšã¹ããªãã«å®è¡ãããããã»ã¹ãçºçããå¯èœæ§ããããŸãã ããšãã°ããŠãŒã¶ãŒããŒã¿ããŒã¹å
šäœã«éç¥ãéä¿¡ããããããŒã¿ããŒã¹ããå€ãããŒã¿ïŒãã©ã±ããïŒãåé€ããããæ¯æ¥ã®çµ±èšæ
å ±ãåŠçãããããŸãã
ãã£ããã¯ããªã¯ãšã¹ãã®åŠçæ¹æ³ãã®ãã®ã§ãã ãããåŠçããæ¹æ³ãçè§£ããå¿
èŠããããŸãã
ããšãã°ãmemcachedã®ãããªãµãŒããŒãèããŠã¿ãŸããããhash_mapã«ã¯ããŒã¿ããããèªã¿åãèŠæ±ããããæžã蟌ã¿èŠæ±ã¯ããã·ã¥ããããç°¡åã«æ€çŽ¢ããŠããŒã¿ãè¿ãããããã·ã¥ãããã«æžã蟌ã¿ãŸãã ãã¹ãŠã1ã€ã®ã¹ã¬ããã§è¡ãããŸãããã·ã¹ãã ã®ãã¹ãŠã®ããã»ããµã䜿çšããå¿
èŠãããå Žåã¯ã©ãã§ããããã
ã³ã¢ãšåãæ°ã®ã¹ã¬ãããäœæããŸãã åã¹ã¬ããã§ã¯ãæ¥ç¶ãäœæãããšãã«
ã©ãŠã³ãããã³ã®ååã«åŸã£ãŠæ£ãã°ã£ãŠãããŠãŒã¶ãŒãåŠçããŸãã ã³ã³ããã«ã¢ã¯ã»ã¹ãããšããrwlockïŒboost :: shared_mutexïŒã䜿çšããŸãã çŽ æŽãããã ããããã³ã³ããããèŠçŽ ãåé€ããã®ã¯ã©ãã§ããïŒ Nç§ããšã«èµ·åããã³ã³ãããŒãã¯ãªãŒã³ã¢ããããã¹ããªãŒã ãäœæããŸãã
ããã¯åçŽãªäŸã§ããããçŸåšã¯ããè€éãªäŸã§ãããŠãŒã¶ãŒã®ãªã¯ãšã¹ãã«å¿ããŠãããŒã¿ããŒã¹ã«ãªã¯ãšã¹ããéä¿¡ããWebãµã€ãã«httpãªã¯ãšã¹ããéä¿¡ã§ãããµãŒãã¹ã§ãã ãµãŒããŒã以åã®ã¢ãã«ã«åŸã£ãŠäœæããããšã©ããªããŸããïŒä»ã®ã³ã³ããŒãã³ããžã®ãã¹ãŠã®ãªã¯ãšã¹ãã¯åæçã«å®è¡ãããŸãïŒïŒ ããŠãããŒã¿ããŒã¹ã¯ãµãŒããŒãšåããã©ãããã©ãŒã äžã«ãããçãã¯æ°ããªç§ã®éè·¯ã«ãããŸãã é»åã¡ãŒã«ã®éä¿¡ãåé¡ã§ã¯ãããŸãããåããã·ã³ã«sendmailãé
眮ããããŒã¿ãéä¿¡ãããšã圌èªèº«ãæçŽã®éä¿¡æ¹æ³ãèŠã€ããŸãã
çŽ æŽãããã æ¬åœã«ããã§ã¯ãããŸãããã httpãªã¯ãšã¹ããã©ãããŸããïŒ éåžžã«é·ãæéããããå ŽåããããŸã-ããã¯ãã¹ãŠã©ããé ãã«ãããµã€ãã«äŸåãããªã¯ãšã¹ããåŠçãããæéã¯ããããŸããã ãã®å Žåããã¥ãŒã«ã¯å®è¡å¯èœãªèŠæ±ã倿°ãããŸãããã¹ã¬ããã¯éã¢ã¯ãã£ãã«ãªããŸããããã®ã¹ã¬ãããè§£æŸããããŸã§åŸ
æ©ããŸãã
ãã®ãããªèŠæ±ã¯éåæã§å®è¡ããå¿
èŠããããŸãã æ¬¡ã®ããã«å®è£
ã§ããŸãã
class LongRequestHandler
{
public :
void Handle()
{
// read client request parameters
// mysql request 1
// mysql request 2
HttpRequestExecutor::GetInstance()->Execute(
"example.com?x=1" ,
boost::bind( this , &LongRequestHandler::HandleStage2)
);
}
void HandleStage2( const std:: string & http_request_result)
{
// mysql request 3
// write response to client
}
};
* This source code was highlighted with Source Code Highlighter .
HttpRequestExecutorã¯ãèŠæ±ã®URLãšãèŠæ±ã®å®äºæã«åŒã³åºãå¿
èŠãããã³ãŒã«ããã¯ãåãå
¥ããŸãïŒã³ãŒã«ããã¯ã®ã¿ã€ãã¯boost :: functionã§ãïŒã
ãããŠããã®ã¢ãããŒãã¯æ©èœããŸãããããŸãçŸããã¯ãããŸããã
C ++ã§éåæçã«èããããã°ã§ã¯ãéåæã¿ã¹ã¯ã®è峿·±ãå®è£
ã瀺ãããŠããŸãã çµæã¯æ¬¡ã®ãšããã§ãã
template <typename Handler> void async_echo(
tcp::socket& socket,
mutable_buffer working_buffer,
Handler handler,
// coroutine state:
coroutine coro = coroutine(),
error_code ec = error_code(),
size_t length = 0)
{
reenter (coro)
{
entry:
while (!ec)
{
yield socket.async_read_some(
buffer(working_buffer),
bind(&async_echo<handler>,
ref (socket), working_buffer,
box(handler), coro, _1, _2));
if (ec) break ;
yield async_write(socket,
buffer(working_buffer, length),
bind(&async_echo<handler>,
ref (socket), working_buffer,
box(handler), coro, _1, _2));
}
handler(ec);
}
}
* This source code was highlighted with Source Code Highlighter .
C ++ã®ã³ã«ãŒãã³ãšyieldã¯ç°åžžã«èŠããŸã;ïŒããã¯defineã«å®è£
ãã
ãŠãããããã°ã§èè
ãã©ããã£ãŠç®¡çããããèªãããšãã§ããŸãã
åŸã
ã«ãããžãã¯ãè€éã«ãªããéåæçã«åŠçããå¿
èŠãããæ°ããèŠçŽ ã远å ãããå®è£
ãè€éã«ãªããŸãã ä»åŸã®èª²é¡
mysqlãªã¯ãšã¹ã1
mysqlãªã¯ãšã¹ã2
httpãªã¯ãšã¹ã1
mysqlãªã¯ãšã¹ã3
httpãªã¯ãšã¹ã2
mysqlãªã¯ãšã¹ã4
mysqlãªã¯ãšã¹ã5
ãããŠãhttpãªã¯ãšã¹ãã§åæ¢ããŠé 次å®è¡ãããšããã®ãªã¯ãšã¹ãã衚瀺ãããŸã
mysqlãªã¯ãšã¹ã2
httpãªã¯ãšã¹ã1
ãããŠ
mysqlãªã¯ãšã¹ã3
httpãªã¯ãšã¹ã2
mysqlãªã¯ãšã¹ã4
䞊è¡ããŠè¡ãããšãã§ããŸãããããè¡ãã«ã¯ãããžãã¯ãããã«è€éã«ããå¿
èŠããããŸãã ããšãã°ã次ã®ãããªç°¡åãªã³ãŒããæžããããšæããŸãã
mysqlãªã¯ãšã¹ã1
x =å®è¡ïŒfunc1ïŒ
y =å®è¡ïŒfunc2ïŒ
åŸ
æ©ïŒxãyïŒ
mysqlãªã¯ãšã¹ã5
func1ïŒ
mysqlãªã¯ãšã¹ã2
httpãªã¯ãšã¹ã1
func2ïŒ
mysqlãªã¯ãšã¹ã3
httpãªã¯ãšã¹ã2
mysqlãªã¯ãšã¹ã4
ããã¯ãã¿ã¹ã¯ã¹ã±ãžã¥ãŒã©ã圹ç«ã€å Žæã§ãã
å®è£
ããã§ãæ°ãã0xæšæºã®ã¿ã¹ã¯ã¹ã±ãžã¥ãŒã©ãµããŒãã«ã€ããŠèªãããšãã§ã
ãŸã ã
boost.taskãäžçªå¥œãã§ããã ããã«è©³çŽ°ãªæ€èšã
boost.taskã®èª¬æ
boost.task-
C ++ 0xæšæºã®ææ¡ã®å®è£
ã ã¿ã¹ã¯å®è¡æŠç¥ã®èšå®ããµãã¿ã¹ã¯ã®äœæãã¿ã¹ã¯ã®äžæããµããŒãããŸãã
ã©ã€ãã©ãªã¯ä»¥äžã«äŸåããŸãã
boost.taskããã³boost.fiberã³ã³ãã€ã«æžã¿ã©ã€ãã©ãªïŒboost.atomicããã³boost.move-ããããŒã®ã¿ïŒ-ãããã£ãŠãããããåéããå¿
èŠããããŸãã å®éšããã䟿å©ã«ããããã«ããã¹ãŠã®äŸåé¢ä¿ã1ãæã«åéããcmakeã§å³ä»ãããŠããããžã§ã¯ãã
githubã«ã¢ããããŒãããŸããã Linuxäžã§åäœããWindowsã§ãã«ãããŸããcmakeã«ãã¡ã€ã«ã远å ããã«ã¯2ã3è¡ããããŸãã
䜿çšäŸ
ã©ã€ãã©ãªAPIã¯éåžžã«ã·ã³ãã«ã§ãäžèšã®ãªã¯ãšã¹ããã³ãã©ã®å®è£
ã¯é£ãããããŸããã ç§ã¯åã³ããããããããŸãïŒ
mysqlãªã¯ãšã¹ã1
mysqlãªã¯ãšã¹ã2
httpãªã¯ãšã¹ã1
mysqlãªã¯ãšã¹ã3
httpãªã¯ãšã¹ã2
mysqlãªã¯ãšã¹ã4
mysqlãªã¯ãšã¹ã5
mysqlãžã®ã¯ãšãªã®ãšãã¥ã¬ãŒã·ã§ã³ãšããŠãã©ã³ãã ãªæéã®éåžžã®ã¹ãªãŒãã䜿çšããŸãã
boost::this_thread::sleep(boost::posix_time::milliseconds(rand()%100 + 10));
boost::this_thread::sleep(boost::posix_time::milliseconds(rand()%100 + 10));
boost :: asioããã®éåæã¿ã€ããŒã¯ãå€éšhttpèŠæ±ãšããŠäœ¿çšãããŸãã
ã ããïŒ
èŠæ±-èŠæ±ã¯ã©ã¹ã
class Request
{
public :
Request( const std:: string & data);
const std:: string & Read() const ;
void Write( const std:: string & answer);
};
* This source code was highlighted with Source Code Highlighter .
ãŸããRequestHandlerã¯èŠæ±ãã³ãã©ãŒã®ã¯ã©ã¹ã§ãã
class RequestHandler
{
public :
RequestHandler(boost::asio::io_service & io_service, const RequestPtr & request);
void Process() const ;
};
* This source code was highlighted with Source Code Highlighter .
io_service-å€éšåŒã³åºããè¡ãããšãã§ããããã«æž¡ãããŸãïŒboost :: asio :: deadline_timerã¿ã€ããŒã䜿çšããŸãïŒã ã¿ã¹ã¯ãåŠçããã¹ã¬ããã®ããŒã«ãå®çŸ©ããŸãã
boost::tasks::static_pool< boost::tasks::unbounded_fifo > pool( boost::tasks::poolsize( 5) );
* This source code was highlighted with Source Code Highlighter .
boost.taskã¯ã2ã€ã®äž»èŠãªã¿ã¹ã¯ã¹ã±ãžã¥ãŒãªã³ã°æŠç¥ããµããŒãããŠããŸãã
- å¶é ïŒå¶éããïŒ-å®è¡ãããã¿ã¹ã¯ã®æ°ã«ãããå€ããããããã«éãããšãæ°ããã¿ã¹ã¯ã远å ãããšãã®ã¢ã¯ã·ã§ã³ãå®è¡ããã¹ã¬ããããããã¯ãããŸãã äž»ãªã¿ã¹ã¯ã¯ãã¿ã¹ã¯ã®è¿œå é床ãå®è¡é床ãè¶
ããå Žåã®ãªãœãŒã¹ã®æ¯æžãåé¿ããããšã§ã
- ç¡å¶é -ç¡éã®æ°ã®ã¿ã¹ã¯ããã¥ãŒã«è¿œå ã§ããŸã
ãã¥ãŒå
ã®ã¿ã¹ã¯ãåŠçããããã®æŠç¥ãèšå®ããããšãã§ããŸãã
- fifo-æåã«è¿œå ãããã¿ã¹ã¯ãæåã«å®è¡ãããŸã
- åªå
床 -ã¿ã¹ã¯ã«åªå
床ããããæãåªå
床ã®é«ãã¿ã¹ã¯ãå®è¡ã®ããã«éžæãããŸã
- smart-ãã®ã¿ã€ãã®ãã¥ãŒã¯ããã©ã¡ãŒã¿ãŒããã³ãã¬ãŒãã«æž¡ãããšã§åŒ·åã«ã«ã¹ã¿ãã€ãºã§ããŸãã ããã©ã«ãã§ã¯ãä»»æã®ããŒã§ã¿ã¹ã¯ã®ã€ã³ããã¯ã¹ãäœæããå€ãã¿ã¹ã¯ãååšããå Žåã¯æ°ããã¿ã¹ã¯ã§çœ®ãæããããšãã§ããŸã
ãããã£ãŠãèšè¿°ãããã³ãŒãè¡ã¯ãã¿ã€ãfifoã®ç¡å¶éã®ãã¥ãŒãæã€5ã€ã®ã¹ã¬ããã®ããŒã«ãäœæããŸãã
次ã«ãå€éšãªã¯ãšã¹ããåŠçããããã«io_serviceãš3ã€ã®ã¹ã¬ããã®ããŒã«ãäœæããå¿
èŠããããŸãã
boost::asio::io_service io_service;
* This source code was highlighted with Source Code Highlighter .
io_service :: callã«ã¿ã¹ã¯ããªããšãã«åŒã³åºããå Žåãã¡ãœããã¯ããã«çµäºããŸããéåžžã®æäœã§ã¯ãäœæ¥ã¹ã¬ãããå¿
èŠã§ãã éåžžãããã¯io_serviceãã¯ã©ã€ã¢ã³ããæ¥ç¶ããããã®åãå
¥ãããŒãã远å ãããšããäºå®ã«ãã£ãŠéæãããŸãããã®å Žåãã¿ã€ããŒã®å®è¡ãåŸ
æ©ããio_serviceãåãããšãã§ããŸãïŒ
boost::asio::deadline_timer dummy_timer(io_service);
dummy_timer.expires_from_now(boost::posix_time::seconds(10));
// void dummy_handler(const boost::system::error_code&) {}
dummy_timer.async_wait(&dummy_handler);
* This source code was highlighted with Source Code Highlighter .
ãã®åŸãã¹ã¬ããããŒã«ãäœæã§ããŸãã
boost::thread_group io_service_thread_pool;
for ( int i = 0; i < 3; ++i)
io_service_thread_pool.create_thread(
boost::bind(&boost::asio::io_service::run, &io_service)
);
* This source code was highlighted with Source Code Highlighter .
次ã«ããªã¯ãšã¹ããäœæããŸãã
RequestPtr request( new Request( "some data" ));
RequestHandlerPtr handler( new RequestHandler(io_service, request));
* This source code was highlighted with Source Code Highlighter .
ãã¹ãŠã®æºåãæŽã£ãããæ¬¡ã®ã¿ã¹ã¯ãå®è¡ã§ããŸãã
boost::tasks::handle< void > request_processing(
boost::tasks::async(
boost::tasks::make_task( &RequestHandler::Process, handler ),
pool));
* This source code was highlighted with Source Code Highlighter .
boost :: tasks :: make_taskïŒïŒRequestHandler :: ProcessãhandlerïŒ-å®è¡å¯èœãªãã³ãã©ãŒãªããžã§ã¯ãã§ProcessãåŒã³åºãã¿ã¹ã¯ãäœæããŸãã boost ::ã¿ã¹ã¯:: asyncã¯éåæã¿ã¹ã¯ã®å®è¡ãéå§ããŸãã boost ::ã¿ã¹ã¯::ã¿ã¹ã¯ã®å®äºã¹ããŒã¿ã¹ã远跡ã§ãããªããžã§ã¯ããåŠçããçµæãããã°ãããååŸããŸãã
boost ::ã¿ã¹ã¯:: asyncã¯4ã€ã®ã¿ã¹ã¯å®è¡ã¢ã«ãŽãªãºã ããµããŒãããŠããŸãïŒ
- own_thread-åãã¹ã¬ããã§ã®åæå®è¡
- new_thread-ã¹ã¬ããã¯ãå®è¡ãããã¿ã¹ã¯çšã«äœæããããã®åŸãã¹ã¬ããã¯å®äºããŸã
- as_sub_task-çŸåšã®ã¿ã¹ã¯ãããŒã«ã§å®è¡ãããŠããå Žå-æ°ããã¿ã¹ã¯ã远å ããŸãããã以å€ã®å Žåã¯ãnew_threadãªã©ã®æ°ããã¹ã¬ãããäœæããŸãã ãããããã©ã«ãã®åäœã§ãã
- static_pool-ã¹ã¬ããããŒã«ã§ã¿ã¹ã¯ãå®è¡ãã
次ã«ãã¿ã¹ã¯ãå®äºãããŸã§åŸ
ã¡ãŸãã
request_processing.wait();
* This source code was highlighted with Source Code Highlighter .
ãããŠãio_serviceã忢ããŸãã
io_service.stop();
io_service_thread_pool.join_all();
* This source code was highlighted with Source Code Highlighter .
ããã»ã¹é¢æ°ã¯é©ãã»ã©ç°¡åã§ãã
void Subtask1() const
{
Request( "query2" );
ExternalRequest( "extquery1" );
}
void Subtask2() const
{
Request( "query3" );
ExternalRequest( "extquery2" );
Request( "query4" );
}
void Process() const
{
std:: string data = request_->Read();
Request( "query1" );
boost::tasks::handle< void > subtask1(
boost::tasks::async(
boost::tasks::make_task( &RequestHandler::Subtask1, this )));
boost::tasks::handle< void > subtask2(
boost::tasks::async(
boost::tasks::make_task( &RequestHandler::Subtask2, this )));
boost::tasks::waitfor_all( subtask1, subtask2);
Request( "query5" );
request_->Write( "some answer" );
}
* This source code was highlighted with Source Code Highlighter .
ãµãã¿ã¹ã¯ã¯ãå®è¡ããããªã·ãŒãæå®ããã«boost :: tasks :: asyncã䜿çšããŠå®è¡ããã芪ã¿ã¹ã¯ãšåãã¹ã¬ããããŒã«ã§ã¿ã¹ã¯ãå®è¡ããas_sub_taskã¢ã«ãŽãªãºã ãèªåçã«éžæãããŸãã ãµãã¿ã¹ã¯é¢æ°ã®å®è£
ãç°¡åã§ãã
RequestHandler :: Request-boost :: this_thread :: sleepãåŒã³åºããExternalRequestã§ã¯å°ãè€éã§ãïŒ
void ExternalRequest( const std:: string & what) const
{
ExternalRequestHandler external_handler(io_service_);
boost::tasks::spin::auto_reset_event ev;
external_handler.PerformExternalReqeust(what, &ev);
ev.wait();
}
* This source code was highlighted with Source Code Highlighter .
ãã³ãã©ãŒãšãèªåãªã»ããã䌎ãã€ãã³ããäœæãããŸã-ããŒã¹ã::ã¿ã¹ã¯::ã¹ãã³:: auto_reset_eventã ãã®ã€ãã³ãã¯å€éšãªã¯ãšã¹ããã³ãã©ã«æž¡ããããã®å®äºæã«ev.setïŒïŒãåŒã³åºãããev.waitïŒïŒãã¿ã¹ã¯ããããã¯ãããŸã§åŒã³åºãããŸãã
éåžžã®ã¹ã¬ããããã³åæããªããã£ãïŒboost :: conditionïŒãšã¯å¯Ÿç
§çã«ãev.waitïŒïŒã¯ã¹ããªãŒã ããããã¯ããŸããããã¿ã¹ã¯ããããã¯ããŸãïŒã«ãŒãã§this_task :: yieldïŒïŒãåŒã³åºããŸãïŒã ããã¯ãããã»ããµãªãœãŒã¹ãä»ã®ã¿ã¹ã¯ã«ãã£ãŠäœ¿çšãããããšãæå³ããŸãã
ãã¡ã€ã«å
šäœã¯
ãã¡ãã«ãããŸã ã
çµè«
boost.taskã¯ãã¿ã¹ã¯ãã¹ã±ãžã¥ãŒã«ããããã®éåžžã«äŸ¿å©ãªã©ã€ãã©ãªã§ãã ããã«ãããéåæã³ãŒãå®è¡ã®ãµããŒããæ°ããC ++ 0xæšæºã§ã©ã®ããã«èŠãããã確èªã§ããæšæºã®ãªãªãŒã¹ãåŸ
ããã«ããã«äœ¿çšã§ããŸãã
boost.taskã䜿çšããã³ãŒãã¯ãéåžžã®ã¹ã¬ããã®äœ¿çšãããå°ãããªããçè§£ãããããªããŸãã
確ãã«æ¬ ç¹ããããŸããã³ãŒãã¯ãŸã æé©åãããŠãããããŸãã«åé¡ãåŒãèµ·ããå¯èœæ§ããããŸãã ã©ã€ãã©ãªã¯ïŒäŸåé¢ä¿ãšå
±ã«ïŒããŒã¹ãã§ãŸã åãå
¥ããããŠããŸããã
ãããã¯ã«ã€ããŠäœãèªãã¹ãã§ããïŒ