design_pattern_for_c  V 1.00
event_if_epoll.c
Go to the documentation of this file.
1 #include "tpool_event_if.h"
2 #include "dp_debug.h"
3 #include <sys/epoll.h>
4 #include <sys/eventfd.h>
5 #include <unistd.h>
6 #include <errno.h>
7 
8 #define EVENT_EPOLL_DEFMAX (4096)
9 //loop to add event
10 #define EVENT_EPOLL_TIMEOUT (50)
11 
12 struct event_epoll_t {
13  int epfd;
14  int maxevents;
16  int is_stop;
17 };
18 
20 
23  void *arg;
24 };
26 
27 static inline int convert_etpoll_eveid2own(int eventflag) {
28  int ret_eveflag=0;
29  if(eventflag&EV_TPOOL_READ) ret_eveflag |= EPOLLIN;
30  if(eventflag&EV_TPOOL_WRITE) ret_eveflag |= EPOLLOUT;
31  if(eventflag&EV_TPOOL_HUNGUP) ret_eveflag |= EPOLLHUP;
32  return ret_eveflag;
33 }
34 
35 static inline short convert_etpoll_ownid2eve(int eventflag) {
36  int ret_eveflag=0;
37  if(eventflag&EPOLLIN) ret_eveflag |= EV_TPOOL_READ;
38  if(eventflag&EPOLLOUT) ret_eveflag |= EV_TPOOL_WRITE;
39  if(eventflag&EPOLLHUP) ret_eveflag |= EV_TPOOL_HUNGUP;
40  return ret_eveflag;
41 }
42 
47  //create main instance
48  EventEpoll instance = calloc(1,sizeof(*instance));
49  if(!instance) return NULL;
50 
51  //set member value
52  instance->maxevents = EVENT_EPOLL_DEFMAX;
53  instance->epfd = epoll_create(EVENT_EPOLL_DEFMAX);
54  if(instance->epfd == -1) {
55  DEBUG_ERRPRINT("Failed to open epoll!\n" );
56  instance->epfd=0;
57  goto err;
58  }
59 
60  return instance;
61 err:
62  event_if_free(instance);
63  return NULL;
64 }
65 
68 
69  EventEpoll base = (EventEpoll)this;
70  /*max size reached*/
71  if(base->maxevents <= base->curevent_cnt) {
72  DEBUG_ERRPRINT("#######Oversize of event!\n");
73  return NULL;
74  }
75 
76  EventEpollHandler instance = calloc(1, sizeof(*instance));
77  if(!instance) {
78  DEBUG_ERRPRINT("#######calloc error!\n");
79  return NULL;
80  }
81 
82  //use subscriber for handler to get fd and delete event
83  memcpy(&instance->subscriber, subscriber, sizeof(instance->subscriber));
84  instance->arg = arg;
85 
86  struct epoll_event ev;
87  ev.events = convert_etpoll_eveid2own(subscriber->eventflag);
88  ev.data.ptr = instance;
89 
90  /*add event*/
91  if(epoll_ctl(base->epfd, EPOLL_CTL_ADD, subscriber->fd, &ev) == -1) {
92  DEBUG_ERRPRINT("Failed to new event! %s\n" , strerror(errno));
93  goto err;
94  }
95 
96  base->curevent_cnt++;
97 
98  return instance;
99 err:
100  free(instance);
101  return NULL;
102 }
103 
105 void * event_if_update(EventInstance this, EventHandler handler, EventSubscriber subscriber, void *arg) {
106  EventEpoll base = (EventEpoll)this;
107  EventEpollHandler instance = (EventEpollHandler) handler;
108 
109  /*is different event?*/
110  if(instance->subscriber.eventflag != subscriber->eventflag) {
111  /*update event*/
112  struct epoll_event event;
113  event.events = convert_etpoll_eveid2own(subscriber->eventflag);
114  event.data.ptr = handler;
115  if(epoll_ctl(base->epfd, EPOLL_CTL_MOD, subscriber->fd, &event)==-1) {
116  DEBUG_ERRPRINT("Failed to modify event! %s\n" , strerror(errno));
117  }
118  }
119 
120  /*copy subscribe*/
121  memcpy(&instance->subscriber, subscriber, sizeof(instance->subscriber));
122  instance->arg = arg;
123 
124  return handler;
125 }
126 
129  EventEpoll base = (EventEpoll)this;
130  EventEpollHandler instance = (EventEpollHandler) handler;
131  if(epoll_ctl(base->epfd, EPOLL_CTL_DEL, instance->subscriber.fd, NULL)) {
132  DEBUG_ERRPRINT("Failed to delete event! %s\n", strerror(errno) );
133  }
134  DEBUG_PRINT("free handle %p!\n", handler );
135  free(handler);
136  base->curevent_cnt--;
137 }
138 
140  return ((EventEpollHandler)handler)->subscriber.fd;
141 }
142 
145  EventEpoll base = (EventEpoll)this;
146  int old_maxevents;
147  int ret=0;
148  struct epoll_event *events = malloc(base->maxevents * sizeof(struct epoll_event));
149  if(!events) {
150  return -1;
151  }
152  memset(events, 0, base->maxevents * sizeof(struct epoll_event));
153 
154  old_maxevents = base->maxevents;
155  int cnt=0, i=0, loop=0;
156  short eventflag;
157  EventEpollHandler handler;
158  base->is_stop=0;
159  while(!base->is_stop) {
160  loop=0;
161  memset(events, 0, base->maxevents * sizeof(struct epoll_event));
162  cnt = epoll_wait(base->epfd, events, base->maxevents, EVENT_EPOLL_TIMEOUT);
163  if(cnt<0) {
164  DEBUG_PRINT("Exit loop!\n" );
165  ret = -1;
166  break;
167  }
168 
169  for(i=0;i<cnt;i++) {
170  DEBUG_PRINT("check event [%d]\n" , i);
171  if(!events[i].data.ptr) continue;
172  eventflag = convert_etpoll_ownid2eve(events[i].events);
173  handler = (EventEpollHandler)events[i].data.ptr;
174  handler->subscriber.event_callback(handler->subscriber.fd, eventflag, handler->arg);
175  }
176  }
177  DEBUG_PRINT("exit main\n" );
178 
179  free(events);
180  return ret;
181 }
182 
185  EventEpoll base = (EventEpoll)this;
186  base->is_stop=1;
187 }
188 
191  return;
192 }
193 
196  EventEpoll instance = (EventEpoll)this;
197  if(!instance) return;
198  if(instance->epfd) close(instance->epfd);
199  free(instance);
200 }
#define EV_TPOOL_READ
event_subscriber_t subscriber
int event_if_getfd(EventHandler handler)
get fd related to handler
struct event_epoll_handler_t * EventEpollHandler
void(* free)(EventInstance this)
Definition: event_thread.c:39
void event_if_loopbreak(EventInstance this)
break event
#define EV_TPOOL_WRITE
#define DEBUG_PRINT(...)
Definition: dp_debug.h:55
static int convert_etpoll_eveid2own(int eventflag)
EventInstance event_if_new(void)
event new
void(* event_callback)(int socketfd, int eventflag, void *event_arg)
void * EventHandler
Event handler related to fd.
struct event_epoll_t * EventEpoll
int(* loop)(EventInstance this)
Definition: event_thread.c:36
static short convert_etpoll_ownid2eve(int eventflag)
EventSubscriber class instance definition, this is storaged in any threads.
int event_if_loop(EventInstance this)
main loop of this event
int eventflag
OR value of EV_TPOOL_XXX definition.
#define EV_TPOOL_HUNGUP
For using debug log.
int fd
file descripter of this subscriber
void * EventInstance
Event management instance which get from event_if_new.
void event_if_free(EventInstance this)
free event if instance
void event_if_exit(EventInstance this)
exit after main loop
#define DEBUG_ERRPRINT(...)
Definition: dp_debug.h:69
#define EVENT_EPOLL_TIMEOUT
#define EVENT_EPOLL_DEFMAX
Definition: event_if_epoll.c:8
EventHandler event_if_add(EventInstance this, EventSubscriber subscriber, void *arg)
add new event
void * event_if_update(EventInstance this, EventHandler handler, EventSubscriber subscriber, void *arg)
update registered event
void event_if_del(EventInstance this, EventHandler handler)
delete event