Show
Ignore:
Timestamp:
08/27/08 15:40:53 (4 months ago)
Author:
frsyuki
Message:

lang/c/mpio: re-implemented mp::fdnotify with readv() system call

Files:
1 modified

Legend:

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

    r18183 r18301  
    1717// 
    1818 
    19 #ifndef MP_FD_NOTIFY_IMPL_H__ 
    20 #define MP_FD_NOTIFY_IMPL_H__ 
     19#ifndef MP_FDNOTIFY_IMPL_H__ 
     20#define MP_FDNOTIFY_IMPL_H__ 
    2121 
    22 #include <sys/types.h> 
    23 #include <sys/uio.h> 
    24 #include <unistd.h> 
    2522#include <fcntl.h> 
    2623#include <errno.h> 
     
    3027 
    3128template <typename NotifyObject> 
    32 fdnotify<NotifyObject>::fdnotify() : m_pos(0) 
     29fdnotify<NotifyObject>::fdnotify() : m_head(m_iovec), m_tail(m_iovec) 
    3330{ 
    34         if( pipe(m_pipe) < 0 ) { 
     31        if( ::pipe(m_pipe) < 0 ) { 
    3532                throw fdnotify_exception("can't create pipe"); 
    3633        } 
    37         if( fcntl(m_pipe[PIPE_READ], F_SETFL, O_NONBLOCK) < 0 ) { 
     34        if( ::fcntl(m_pipe[0], F_SETFL, O_NONBLOCK) < 0 ) { 
    3835                close(m_pipe[0]); 
    3936                close(m_pipe[1]); 
    4037                throw fdnotify_exception("can't set non-blocking mode"); 
     38        } 
     39        struct iovec* p = m_iovec; 
     40        struct iovec* const endp = m_iovec + MP_FDNOTIFY_VECTOR_SIZE; 
     41        NotifyObject* b = (NotifyObject*)m_buffer; 
     42        for(; p != endp; ++p, ++b) { 
     43                p->iov_base = (char*)b; 
     44                p->iov_len = sizeof(NotifyObject); 
    4145        } 
    4246} 
     
    5054 
    5155template <typename NotifyObject> 
    52 bool fdnotify<NotifyObject>::try_receive(NotifyObject* result) 
     56inline bool fdnotify<NotifyObject>::try_receive(NotifyObject* result) 
    5357{ 
    54         ssize_t len = read(m_pipe[PIPE_READ], m_buffer + m_pos, sizeof(NotifyObject) - m_pos); 
    55         if( len < 0 ) { 
    56                 if(errno == EAGAIN || errno == EINTR ) { 
     58        if(m_head < m_tail) { 
     59                *result = *((NotifyObject*)m_head->iov_base); 
     60                ++m_head; 
     61                return true; 
     62        } else { 
     63                return receive_next(result); 
     64        } 
     65} 
     66 
     67template <typename NotifyObject> 
     68inline void fdnotify<NotifyObject>::send(const NotifyObject& obj) 
     69{ 
     70        ssize_t len = ::write(m_pipe[1], (void*)&obj, sizeof(NotifyObject)); 
     71        if(len != sizeof(NotifyObject)) { 
     72                throw fdnotify_exception("write-side pipe is broken or closed"); 
     73        } 
     74} 
     75 
     76template <typename NotifyObject> 
     77bool fdnotify<NotifyObject>::receive_next(NotifyObject* result) 
     78{ 
     79        ssize_t len = ::readv(m_pipe[0], m_iovec, MP_FDNOTIFY_VECTOR_SIZE); 
     80        if(len < 0) { 
     81                if(errno == EAGAIN || errno == EINTR) { 
    5782                        return false; 
    5883                } else { 
    5984                        throw fdnotify_exception("read-side pipe is broken"); 
    6085                } 
    61         } else if( len == 0 ) { 
     86        } else if(len == 0) { 
    6287                throw fdnotify_exception("read-side pipe is closed"); 
    6388        } 
    64  
    65         m_pos += len; 
    66         if( m_pos == sizeof(NotifyObject) ) { 
    67                 *result = *reinterpret_cast<NotifyObject*>(m_buffer); 
    68                 m_pos = 0; 
    69                 return true; 
     89        if(static_cast<size_t>(len) > sizeof(NotifyObject)) { 
     90                m_head = m_iovec+1; 
     91                m_tail = (struct iovec*)(((char*)m_iovec) + len); 
    7092        } 
    71         return false; 
    72 } 
    73  
    74  
    75 template <typename NotifyObject> 
    76 void fdnotify<NotifyObject>::send(const NotifyObject& obj) 
    77 { 
    78         const char* p = reinterpret_cast<const char*>(&obj); 
    79         ssize_t len = ::write(m_pipe[PIPE_WRITE], p, sizeof(NotifyObject)); 
    80         if( len < static_cast<ssize_t>(sizeof(NotifyObject)) ) { 
    81                 if( len < 0 && errno != EINTR && errno != EAGAIN  ) { 
    82                         throw fdnotify_exception("write-side pipe is broken"); 
    83                 } 
    84                 send_all(p, p + sizeof(NotifyObject) - len); 
    85         } 
    86 } 
    87  
    88  
    89 template <typename NotifyObject> 
    90 void fdnotify<NotifyObject>::send_all(const char* p, const char* const endp) 
    91 { 
    92         do { 
    93                 ssize_t len = ::write(m_pipe[PIPE_WRITE], p, endp - p); 
    94                 if( len < 0 ) { 
    95                         if( errno != EINTR && errno != EAGAIN ) { 
    96                                 throw fdnotify_exception("write-side pipe is broken"); 
    97                         } 
    98                 } else if( len == 0 ) { 
    99                         throw fdnotify_exception("write-side pipe is closed"); 
    100                 } else { 
    101                         p += len; 
    102                 } 
    103         } while( p < endp ); 
     93        *result = *((NotifyObject*)m_iovec[0].iov_base); 
     94        return true; 
    10495} 
    10596