select.hpp 4.74 KB
Newer Older
Martin Sustrik's avatar
Martin Sustrik committed
1
/*
2
    Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
Martin Sustrik's avatar
Martin Sustrik committed
3

4
    This file is part of libzmq, the ZeroMQ core engine in C++.
Martin Sustrik's avatar
Martin Sustrik committed
5

6 7 8
    libzmq is free software; you can redistribute it and/or modify it under
    the terms of the GNU Lesser General Public License (LGPL) as published
    by the Free Software Foundation; either version 3 of the License, or
Martin Sustrik's avatar
Martin Sustrik committed
9 10
    (at your option) any later version.

11 12 13 14 15 16 17 18 19 20 21 22 23 24
    As a special exception, the Contributors give you permission to link
    this library with independent modules to produce an executable,
    regardless of the license terms of these independent modules, and to
    copy and distribute the resulting executable under terms of your choice,
    provided that you also meet, for each linked independent module, the
    terms and conditions of the license of that module. An independent
    module is a module which is not derived from or based on this library.
    If you modify this library, you must extend this exception to your
    version of the library.

    libzmq is distributed in the hope that it will be useful, but WITHOUT
    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
    License for more details.
Martin Sustrik's avatar
Martin Sustrik committed
25

26
    You should have received a copy of the GNU Lesser General Public License
Martin Sustrik's avatar
Martin Sustrik committed
27 28 29
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

Martin Sustrik's avatar
Martin Sustrik committed
30 31
#ifndef __ZMQ_SELECT_HPP_INCLUDED__
#define __ZMQ_SELECT_HPP_INCLUDED__
Martin Sustrik's avatar
Martin Sustrik committed
32

33 34
//  poller.hpp decides which polling mechanism to use.
#include "poller.hpp"
35
#if defined ZMQ_IOTHREAD_POLLER_USE_SELECT
36

Martin Sustrik's avatar
Martin Sustrik committed
37 38
#include <stddef.h>
#include <vector>
39
#include <map>
Martin Sustrik's avatar
Martin Sustrik committed
40

41
#if defined ZMQ_HAVE_WINDOWS
Martin Sustrik's avatar
Martin Sustrik committed
42
#elif defined ZMQ_HAVE_OPENVMS
Martin Sustrik's avatar
Martin Sustrik committed
43 44 45 46 47 48
#include <sys/types.h>
#include <sys/time.h>
#else
#include <sys/select.h>
#endif

49
#include "ctx.hpp"
Martin Sustrik's avatar
Martin Sustrik committed
50
#include "fd.hpp"
51
#include "poller_base.hpp"
Martin Sustrik's avatar
Martin Sustrik committed
52

Martin Sustrik's avatar
Martin Sustrik committed
53
namespace zmq
Martin Sustrik's avatar
Martin Sustrik committed
54
{
sigiesec's avatar
sigiesec committed
55
struct i_poll_events;
Martin Sustrik's avatar
Martin Sustrik committed
56

sigiesec's avatar
sigiesec committed
57 58
//  Implements socket polling mechanism using POSIX.1-2001 select()
//  function.
59

60
class select_t ZMQ_FINAL : public worker_poller_base_t
sigiesec's avatar
sigiesec committed
61 62 63
{
  public:
    typedef fd_t handle_t;
Martin Sustrik's avatar
Martin Sustrik committed
64

65
    select_t (const thread_ctx_t &ctx_);
66
    ~select_t () ZMQ_FINAL;
Martin Sustrik's avatar
Martin Sustrik committed
67

sigiesec's avatar
sigiesec committed
68 69 70 71 72 73 74 75
    //  "poller" concept.
    handle_t add_fd (fd_t fd_, zmq::i_poll_events *events_);
    void rm_fd (handle_t handle_);
    void set_pollin (handle_t handle_);
    void reset_pollin (handle_t handle_);
    void set_pollout (handle_t handle_);
    void reset_pollout (handle_t handle_);
    void stop ();
76

sigiesec's avatar
sigiesec committed
77
    static int max_fds ();
Martin Sustrik's avatar
Martin Sustrik committed
78

sigiesec's avatar
sigiesec committed
79 80
  private:
    //  Main event loop.
81
    void loop () ZMQ_FINAL;
82

sigiesec's avatar
sigiesec committed
83 84 85 86 87 88 89 90 91 92 93 94 95
    //  Internal state.
    struct fds_set_t
    {
        fds_set_t ();
        fds_set_t (const fds_set_t &other_);
        fds_set_t &operator= (const fds_set_t &other_);
        //  Convenience method to descriptor from all sets.
        void remove_fd (const fd_t &fd_);

        fd_set read;
        fd_set write;
        fd_set error;
    };
Martin Sustrik's avatar
Martin Sustrik committed
96

sigiesec's avatar
sigiesec committed
97 98 99 100 101 102
    struct fd_entry_t
    {
        fd_t fd;
        zmq::i_poll_events *events;
    };
    typedef std::vector<fd_entry_t> fd_entries_t;
Martin Sustrik's avatar
Martin Sustrik committed
103

sigiesec's avatar
sigiesec committed
104 105 106
    void trigger_events (const fd_entries_t &fd_entries_,
                         const fds_set_t &local_fds_set_,
                         int event_count_);
107

sigiesec's avatar
sigiesec committed
108 109 110
    struct family_entry_t
    {
        family_entry_t ();
111

sigiesec's avatar
sigiesec committed
112 113
        fd_entries_t fd_entries;
        fds_set_t fds_set;
114
        bool has_retired;
sigiesec's avatar
sigiesec committed
115
    };
116

sigiesec's avatar
sigiesec committed
117 118 119 120
    void select_family_entry (family_entry_t &family_entry_,
                              int max_fd_,
                              bool use_timeout_,
                              struct timeval &tv_);
Martin Sustrik's avatar
Martin Sustrik committed
121

122
#if defined ZMQ_HAVE_WINDOWS
sigiesec's avatar
sigiesec committed
123
    typedef std::map<u_short, family_entry_t> family_entries_t;
Martin Sustrik's avatar
Martin Sustrik committed
124

sigiesec's avatar
sigiesec committed
125 126 127 128
    struct wsa_events_t
    {
        wsa_events_t ();
        ~wsa_events_t ();
sigiesec's avatar
sigiesec committed
129

sigiesec's avatar
sigiesec committed
130
        //  read, write, error and readwrite
131
        WSAEVENT events[4];
sigiesec's avatar
sigiesec committed
132
    };
133

134
    family_entries_t _family_entries;
sigiesec's avatar
sigiesec committed
135
    // See loop for details.
136
    family_entries_t::iterator _current_family_entry_it;
137

138
    int try_retire_fd_entry (family_entries_t::iterator family_entry_it_,
139
                             zmq::fd_t &handle_);
140

sigiesec's avatar
sigiesec committed
141
    static const size_t fd_family_cache_size = 8;
142
    std::pair<fd_t, u_short> _fd_family_cache[fd_family_cache_size];
143

sigiesec's avatar
sigiesec committed
144 145 146 147 148 149
    u_short get_fd_family (fd_t fd_);

    //  Socket's family or AF_UNSPEC on error.
    static u_short determine_fd_family (fd_t fd_);
#else
    //  on non-Windows, we can treat all fds as one family
150 151
    family_entry_t _family_entry;
    fd_t _max_fd;
152
#endif
Martin Sustrik's avatar
Martin Sustrik committed
153

154 155 156
    void cleanup_retired ();
    bool cleanup_retired (family_entry_t &family_entry_);

sigiesec's avatar
sigiesec committed
157
    //  Checks if an fd_entry_t is retired.
158
    static bool is_retired_fd (const fd_entry_t &entry_);
159

sigiesec's avatar
sigiesec committed
160
    static fd_entries_t::iterator
161
    find_fd_entry_by_handle (fd_entries_t &fd_entries_, handle_t handle_);
Martin Sustrik's avatar
Martin Sustrik committed
162

163
    ZMQ_NON_COPYABLE_NOR_MOVABLE (select_t)
sigiesec's avatar
sigiesec committed
164
};
165

sigiesec's avatar
sigiesec committed
166
typedef select_t poller_t;
Martin Sustrik's avatar
Martin Sustrik committed
167 168 169 170
}

#endif

171
#endif