Show
Ignore:
Timestamp:
10/27/08 01:30:54 (5 years ago)
Author:
frsyuki
Message:

lang/c/mpio: reformed mp::coroutine into mp::fiber

Files:
1 moved

Legend:

Unmodified
Added
Removed
  • lang/c/mpio/trunk/mp/fiber_impl.h

    r21833 r22190  
    11// 
    2 // mp::coroutine 
     2// mp::fiber 
    33// 
    44// Copyright (C) 2008 FURUHASHI Sadayuki 
     
    1717// 
    1818 
    19 #ifndef MP_COROUTINE_IMPL_H__ 
    20 #define MP_COROUTINE_IMPL_H__ 
     19#ifndef MP_FIBER_IMPL_H__ 
     20#define MP_FIBER_IMPL_H__ 
    2121 
    2222#include "mp/object_callback.h" 
     
    2525 
    2626 
    27 template <typename ThreadTag> 
    28 typename coroutine<ThreadTag>::handler* coroutine<ThreadTag>::s_current = NULL; 
    29  
    30 template <typename ThreadTag> 
    31 std::auto_ptr< coroutine<ThreadTag> > coroutine<ThreadTag>::s_instance; 
    32  
    33  
    34 template <typename ThreadTag> 
    35 void coroutine<ThreadTag>::initialize() 
    36 { 
    37         s_instance.reset(new coroutine<ThreadTag>()); 
    38 } 
    39  
    40 template <typename ThreadTag> 
    41 void coroutine<ThreadTag>::destroy() 
    42 { 
    43         coroutine<ThreadTag>::end(); 
    44         s_instance.reset(NULL); 
    45 } 
    46  
    47 template <typename ThreadTag> 
    48 coroutine<ThreadTag>::coroutine() : 
    49         m_main_coro(coro_t::main()), 
    50         m_end_flag(0) 
    51 { 
    52         // register fdnotify with NULL handler 
    53         if( m_event.add(m_fdnotify.getfd(), EV_READ, (handler*)NULL) < 0 ) { 
    54                 throw std::runtime_error("add fdnotify failed"); 
    55         } 
    56 } 
    57  
    58  
    59 template <typename ThreadTag> 
    60 coroutine<ThreadTag>::~coroutine() 
     27template <typename IMPL> 
     28fiber::handler::handler(IMPL* pimpl) : 
     29        current_fd(-1), 
     30        context( 
     31                        &object_callback<void ()>::mem_fun<IMPL, &IMPL::operator()>, 
     32                        pimpl 
     33                        ) 
    6134{ } 
    6235 
    6336 
    64 template <typename ThreadTag> 
    65 int coroutine<ThreadTag>::run_impl() 
    66 { 
    67         int fd; 
    68         short event; 
    69         while(!m_end_flag) { 
    70  
    71                 // event notify 
    72                 while( m_event.next(&fd, &event) ) { 
    73  
    74                         if( fd == m_fdnotify.getfd() ) { 
    75                                 // event on fdnotify 
    76                                 // receive waked handler 
    77                                 handler* waked; 
    78                                 while( m_fdnotify.try_receive(&waked) ) { 
    79                                         if( waked != NULL ) {  // wake == NULL means interrupt 
    80                                                 call_handler(*waked); 
    81                                         } 
    82                                 } 
    83  
    84                         } else { 
    85                                 // event on fd 
    86                                 cb_t& cb( m_event.data(fd) ); 
    87                                 call_handler(cb.get()); 
    88                         } 
    89                 } 
    90  
    91                 // join notify 
    92                 while( !m_join_notify.empty() ) { 
    93                         join_notify_t tmp; 
    94                         tmp.swap(m_join_notify);  // now m_join_notify is empty 
    95                         for(typename join_notify_t::iterator it(tmp.begin()), it_end(tmp.end()); 
    96                                         it != it_end; 
    97                                         ++it) { 
    98                                 call_handler( *(*it) ); 
    99                         } 
    100                 } 
    101  
    102                 // wait event 
    103                 if( m_event.wait() < 0 ) { 
    104                         return -1; 
    105                 } 
    106  
    107         } 
    108  
    109         return 0; 
    110 } 
    111  
    112 template <typename ThreadTag> 
    113 void coroutine<ThreadTag>::call_handler(handler& target) 
    114 { 
    115         s_current = &target; 
    116         m_main_coro.spawn( target.get_coro() ); 
    117         if( target.exited() ) { 
    118                 std::copy(target.waited.begin(), 
    119                                 target.waited.end(), 
    120                                 std::back_inserter(m_join_notify)); 
    121                 if( target.current_fd >= 0 ) { 
    122                         remove(target); 
    123                 } 
    124         } 
    125 } 
    126  
    127  
    128 template <typename ThreadTag> 
    129 void coroutine<ThreadTag>::end_impl() 
    130 try { 
    131         if(m_end_flag) { return; } 
    132         m_end_flag = 1; 
    133         interrupt_impl(); 
    134 } catch (...) 
    135 { } 
    136  
    137  
    138 template <typename ThreadTag> 
    139 template <typename IMPL> 
    140 coroutine<ThreadTag>::handler::handler(IMPL* pimpl) : 
    141         current_fd(-1), 
    142         m_coro( 
    143                 &object_callback<void ()>::mem_fun<IMPL, &IMPL::operator()>, 
    144                 pimpl 
    145                 ) 
    146 {} 
    147  
    148 template <typename ThreadTag> 
    149 coroutine<ThreadTag>::handler::~handler() {} 
    150  
    151  
    152 template <typename ThreadTag> 
    153 void coroutine<ThreadTag>::add_handler_impl(int fd, short event, handler& routine) 
    154 { 
    155         add(routine, fd, event); 
    156 } 
    157  
    158  
    159 template <typename ThreadTag> 
    160 void coroutine<ThreadTag>::yield_impl(int fd, short event) 
    161 { 
    162         handler& self(*s_current); 
    163  
    164         // modify current state 
    165         if( self.current_event >= 0 ) { 
    166  
    167                 if( fd == self.current_fd ) { 
    168                         // same fd and ... 
    169                         if( self.current_event == event ) { 
    170                                 // same event, modify nothing 
    171                                 goto next; 
    172                         } 
    173  
    174                         // different event, modify event 
    175                         modify(self, event); 
    176                         goto next; 
    177  
    178                 } else { 
    179                         // different fd, change fd 
    180                         remove(self); 
    181                         add(self, fd, event); 
    182                 } 
    183  
    184         // add new event 
    185         } else { 
    186                 add(self, fd, event); 
    187         } 
    188  
    189 next: 
    190         self.yield(); 
    191 } 
    192  
    193  
    194 template <typename ThreadTag> 
    195 void coroutine<ThreadTag>::suspend_impl() 
    196 { 
    197         handler& self(*s_current); 
    198         if( self.current_event >= 0 ) { 
    199                 remove(self); 
    200         } 
    201         self.yield(); 
    202 } 
    203  
    204  
    205 template <typename ThreadTag> 
    206 void coroutine<ThreadTag>::join_impl(handler& target) 
    207 { 
    208         if(target.exited()) { return; } 
    209         handler& self(*s_current); 
    210         target.waited.push_back(&self); 
    211         suspend_impl(); 
    212 } 
    213  
    214  
    215 template <typename ThreadTag> 
    216 void coroutine<ThreadTag>::wake_impl(handler& target) 
    217 { 
    218         m_fdnotify.send(&target); 
    219 } 
    220  
    221  
    222 template <typename ThreadTag> 
    223 void coroutine<ThreadTag>::interrupt_impl() 
    224 { 
    225         m_fdnotify.send((handler*)NULL); 
    226 } 
    227  
    228  
    229 template <typename ThreadTag> 
    230 bool coroutine<ThreadTag>::test_impl(int fd) 
    231 { 
    232         return m_event.test(fd); 
    233 } 
    234  
    235  
    236 template <typename ThreadTag> 
    237 void coroutine<ThreadTag>::modify(handler& target, short event) 
    238 { 
    239         if( m_event.modify(target.current_fd, target.current_event, event) < 0 ) { 
    240                 throw std::runtime_error("modify failed"); 
    241         } 
    242         target.current_event = event; 
    243 } 
    244  
    245  
    246 template <typename ThreadTag> 
    247 void coroutine<ThreadTag>::add(handler& target, int fd, short event) 
    248 { 
    249         if( m_event.add(fd, event, &target) < 0 ) { 
    250                 throw std::runtime_error("add failed"); 
    251         } 
    252         target.current_fd = fd; 
    253         target.current_event = event; 
    254 } 
    255  
    256 template <typename ThreadTag> 
    257 void coroutine<ThreadTag>::remove(handler& target) 
    258 { 
    259         // ignore error 
    260         m_event.remove(target.current_fd, target.current_event); 
    261         target.current_fd = -1; 
    262 } 
     37inline fiber::handler::~handler() { } 
    26338 
    26439 
    26540}  // namespace mp 
    26641 
    267 #endif /* mp/coroutine_impl.h */ 
     42#endif /* mp/fiber_impl.h */ 
    26843