root/lang/c/mpio/trunk/mp/fdnotify_impl.h @ 19040

Revision 19040, 2.6 kB (checked in by frsyuki, 6 years ago)

lang/c/mpio: bug fixed mp::fdnotify

Line 
1//
2// mp::fdnotify
3//
4// Copyright (C) 2008 FURUHASHI Sadayuki
5//
6//    Licensed under the Apache License, Version 2.0 (the "License");
7//    you may not use this file except in compliance with the License.
8//    You may obtain a copy of the License at
9//
10//        http://www.apache.org/licenses/LICENSE-2.0
11//
12//    Unless required by applicable law or agreed to in writing, software
13//    distributed under the License is distributed on an "AS IS" BASIS,
14//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15//    See the License for the specific language governing permissions and
16//    limitations under the License.
17//
18
19#ifndef MP_FDNOTIFY_IMPL_H__
20#define MP_FDNOTIFY_IMPL_H__
21
22#include <fcntl.h>
23#include <errno.h>
24
25namespace mp {
26
27
28template <typename NotifyObject>
29fdnotify<NotifyObject>::fdnotify() : m_head(m_buffer), m_tail(m_buffer)
30{
31        if( ::pipe(m_pipe) < 0 ) {
32                throw fdnotify_exception("can't create pipe");
33        }
34        if( ::fcntl(m_pipe[0], F_SETFL, O_NONBLOCK) < 0 ) {
35                close(m_pipe[0]);
36                close(m_pipe[1]);
37                throw fdnotify_exception("can't set non-blocking mode");
38        }
39}
40
41template <typename NotifyObject>
42fdnotify<NotifyObject>::~fdnotify()
43{
44        close(m_pipe[0]);
45        close(m_pipe[1]);
46}
47
48template <typename NotifyObject>
49inline bool fdnotify<NotifyObject>::try_receive(NotifyObject* result)
50{
51        if(m_tail - m_head >= static_cast<ptrdiff_t>(sizeof(NotifyObject))) {
52                *result = *((NotifyObject*)m_head);
53                m_head += sizeof(NotifyObject);
54                return true;
55        } else {
56                return receive_next(result);
57        }
58}
59
60template <typename NotifyObject>
61inline void fdnotify<NotifyObject>::send(const NotifyObject& obj)
62{
63        ssize_t len;
64        while(1) {
65                len = ::write(m_pipe[1], (void*)&obj, sizeof(NotifyObject));
66                if(len >= static_cast<ssize_t>(sizeof(NotifyObject))) {
67                        return;
68                }
69                if(len < 0) {
70                        if(errno != EAGAIN && errno != EINTR) {
71                                throw fdnotify_exception("write-side pipe is broken");
72                        }
73                }
74        }
75}
76
77template <typename NotifyObject>
78bool fdnotify<NotifyObject>::receive_next(NotifyObject* result)
79{
80        size_t carry = m_tail - m_head;
81
82        std::memcpy(m_buffer, m_head, carry);
83        m_head = m_buffer;
84        m_tail = m_buffer + carry;
85
86        ssize_t len = ::read(m_pipe[0], m_tail, sizeof(m_buffer)-carry);
87        if(len < 0) {
88                if(errno == EAGAIN || errno == EINTR) {
89                        return false;
90                } else {
91                        throw fdnotify_exception("read-side pipe is broken");
92                }
93        } else if(len == 0) {
94                throw fdnotify_exception("read-side pipe is closed");
95        }
96
97        m_tail += len;
98        if(m_tail - m_head >= static_cast<ptrdiff_t>(sizeof(NotifyObject))) {
99                *result = *((NotifyObject*)m_head);
100                m_head += sizeof(NotifyObject);
101                return true;
102        } else {
103                return false;
104        }
105}
106
107
108}  // namespace mp
109
110#endif /* mp/fdnotify_impl.h */
111
Note: See TracBrowser for help on using the browser.