Open Lighting Architecture  0.9.3
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
KQueuePoller.h
1 /*
2  * This library is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU Lesser General Public
4  * License as published by the Free Software Foundation; either
5  * version 2.1 of the License, or (at your option) any later version.
6  *
7  * This library is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10  * Lesser General Public License for more details.
11  *
12  * You should have received a copy of the GNU Lesser General Public
13  * License along with this library; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
15  *
16  * KQueuePoller.h
17  * A Poller which uses kqueue / kevent
18  * Copyright (C) 2014 Simon Newton
19  */
20 
21 #ifndef COMMON_IO_KQUEUEPOLLER_H_
22 #define COMMON_IO_KQUEUEPOLLER_H_
23 
24 #include <ola/base/Macro.h>
25 #include <ola/Clock.h>
26 #include <ola/ExportMap.h>
27 #include <ola/io/Descriptor.h>
28 #include <sys/event.h>
29 
30 #include <map>
31 #include <set>
32 #include <string>
33 #include <utility>
34 #include <vector>
35 
36 #include "common/io/PollerInterface.h"
37 #include "common/io/TimeoutManager.h"
38 
39 namespace ola {
40 namespace io {
41 
42 class KQueueData;
43 
51 class KQueuePoller : public PollerInterface {
52  public :
58  KQueuePoller(ExportMap *export_map, Clock *clock);
59 
60  ~KQueuePoller();
61 
62  bool AddReadDescriptor(class ReadFileDescriptor *descriptor);
63  bool AddReadDescriptor(class ConnectedDescriptor *descriptor,
64  bool delete_on_close);
65  bool RemoveReadDescriptor(class ReadFileDescriptor *descriptor);
66  bool RemoveReadDescriptor(class ConnectedDescriptor *descriptor);
67 
68  bool AddWriteDescriptor(class WriteFileDescriptor *descriptor);
69  bool RemoveWriteDescriptor(class WriteFileDescriptor *descriptor);
70 
71  const TimeStamp *WakeUpTime() const { return &m_wake_up_time; }
72 
73  bool Poll(TimeoutManager *timeout_manager,
74  const TimeInterval &poll_interval);
75 
76  private:
77  enum { CHANGE_SET_SIZE = 10 };
78 
79  typedef std::map<int, KQueueData*> DescriptorMap;
80  typedef std::vector<KQueueData*> DescriptorList;
81 
82  DescriptorMap m_descriptor_map;
83 
84  // KQueuePoller is re-enterant. Remove may be called while we hold a pointer
85  // to an KQueueData. To avoid deleting data out from underneath
86  // ourselves, we instead move the removed descriptors to this list and then
87  // clean them up outside the callback loop.
88  DescriptorList m_orphaned_descriptors;
89  // A list of pre-allocated descriptors we can use.
90  DescriptorList m_free_descriptors;
91  ExportMap *m_export_map;
92  CounterVariable *m_loop_iterations;
93  CounterVariable *m_loop_time;
94  int m_kqueue_fd;
95 
96  struct kevent m_change_set[CHANGE_SET_SIZE];
97  unsigned int m_next_change_entry;
98 
99  Clock *m_clock;
100  TimeStamp m_wake_up_time;
101 
102  void CheckDescriptor(struct kevent *event);
103  std::pair<KQueueData*, bool> LookupOrCreateDescriptor(int fd);
104  bool ApplyChange(int fd, int16_t filter, uint16_t flags,
105  KQueueData *kqueue_data, bool apply_immediately);
106  bool RemoveDescriptor(int fd, int16_t filter);
107 
108  static const int MAX_EVENTS;
109  static const unsigned int MAX_FREE_DESCRIPTORS;
110 
112 };
113 } // namespace io
114 } // namespace ola
115 #endif // COMMON_IO_KQUEUEPOLLER_H_