// // mp::fdnotify // // Copyright (C) 2008 FURUHASHI Sadayuki // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef MP_FDNOTIFY_IMPL_H__ #define MP_FDNOTIFY_IMPL_H__ #include #include namespace mp { template fdnotify::fdnotify() : m_head(m_buffer), m_tail(m_buffer) { if( ::pipe(m_pipe) < 0 ) { throw fdnotify_exception("can't create pipe"); } if( ::fcntl(m_pipe[0], F_SETFL, O_NONBLOCK) < 0 ) { close(m_pipe[0]); close(m_pipe[1]); throw fdnotify_exception("can't set non-blocking mode"); } } template fdnotify::~fdnotify() { close(m_pipe[0]); close(m_pipe[1]); } template inline bool fdnotify::try_receive(NotifyObject* result) { if(m_tail - m_head >= static_cast(sizeof(NotifyObject))) { *result = *((NotifyObject*)m_head); m_head += sizeof(NotifyObject); return true; } else { return receive_next(result); } } template inline void fdnotify::send(const NotifyObject& obj) { ssize_t len; while(1) { len = ::write(m_pipe[1], (void*)&obj, sizeof(NotifyObject)); if(len >= static_cast(sizeof(NotifyObject))) { return; } if(len < 0) { if(errno != EAGAIN && errno != EINTR) { throw fdnotify_exception("write-side pipe is broken"); } } } } template bool fdnotify::receive_next(NotifyObject* result) { size_t carry = m_tail - m_head; std::memcpy(m_buffer, m_head, carry); m_head = m_buffer; m_tail = m_buffer + carry; ssize_t len = ::read(m_pipe[0], m_tail, sizeof(m_buffer)-carry); if(len < 0) { if(errno == EAGAIN || errno == EINTR) { return false; } else { throw fdnotify_exception("read-side pipe is broken"); } } else if(len == 0) { throw fdnotify_exception("read-side pipe is closed"); } m_tail += len; if(m_tail - m_head >= static_cast(sizeof(NotifyObject))) { *result = *((NotifyObject*)m_head); m_head += sizeof(NotifyObject); return true; } else { return false; } } } // namespace mp #endif /* mp/fdnotify_impl.h */