design_pattern_for_c  V 1.00
event_if_select.c
Go to the documentation of this file.
1 #include "tpool_event_if.h"
2 #include "dp_util.h"
3 #include <sys/time.h>
4 #include <sys/types.h>
5 #include <unistd.h>
6 #include <stdlib.h>
7 #include <errno.h>
8 
9 //loop to add event
10 #define EVENT_SELECT_TIMEOUT (50000)
11 
14 
19  void *arg;
20 };
21 
22 typedef struct event_select_fds_t {
23  fd_set readfds;
24  fd_set writefds;
25  fd_set exceptfds;
27 
28 static inline void event_select_reset_fds(event_select_fds_t * fds) {
29  FD_ZERO(&fds->readfds);
30  FD_ZERO(&fds->writefds);
31  FD_ZERO(&fds->exceptfds);
32 }
33 
35  /*this order is from lower fd number*/
40  int maxfd;
41  struct timeval timeout;
42  struct timeval use_timeout;
43  int is_stop;
45 };
47 
48 #define event_select_handler_pull(this, data) dputil_list_pull((DPUtilList)(this), (DPUtilListData)(data))
49 #define event_select_handler_insert(this, prev, data) dputil_list_insert((DPUtilList)(this),(DPUtilListData)(prev), (DPUtilListData)(data))
50 
51 static inline void event_select_set_fds(EventSelect this , EventSubscriber subscriber) {
52  if(subscriber->eventflag&EV_TPOOL_READ ) FD_SET(subscriber->fd, &this->storefds.readfds);
53  if(subscriber->eventflag&EV_TPOOL_WRITE ) FD_SET(subscriber->fd, &this->storefds.writefds);
54  if(subscriber->eventflag&EV_TPOOL_HUNGUP) FD_SET(subscriber->fd, &this->storefds.exceptfds);
55  this->is_updated=1;
56 }
57 
58 static inline void event_select_unset_fds(EventSelect this , EventSubscriber subscriber) {
59  if(subscriber->eventflag&EV_TPOOL_READ ) FD_CLR(subscriber->fd, &this->storefds.readfds);
60  if(subscriber->eventflag&EV_TPOOL_WRITE ) FD_CLR(subscriber->fd, &this->storefds.writefds);
61  if(subscriber->eventflag&EV_TPOOL_HUNGUP) FD_CLR(subscriber->fd, &this->storefds.exceptfds);
62  this->is_updated=1;
63 }
64 
65 static int event_select_get_eventflag_from_fds(EventSelect this, int fd) {
66  int eventflag=0;
67  if(FD_ISSET(fd, &(this->waitfds.readfds)) ) eventflag |= EV_TPOOL_READ;
68  if(FD_ISSET(fd, &(this->waitfds.writefds)) ) eventflag |= EV_TPOOL_WRITE;
69  if(FD_ISSET(fd, &(this->waitfds.exceptfds))) eventflag |= EV_TPOOL_HUNGUP;
70  return eventflag;
71 }
72 
77  //create main instance
78  EventSelect instance = calloc(1,sizeof(*instance));
79  if(!instance) return NULL;
80 
81  //set member value
82  instance->timeout.tv_usec=EVENT_SELECT_TIMEOUT;
83  event_select_reset_fds(&instance->storefds);
84  event_select_reset_fds(&instance->waitfds);
85 
86  return instance;
87 err:
88  event_if_free(instance);
89  return NULL;
90 }
91 
94 
95  EventSelect base = (EventSelect)this;
96 
97  EventSelectHandler instance = calloc(1, sizeof(*instance));
98  if(!instance) {
99  DEBUG_ERRPRINT("#######calloc error!\n");
100  return NULL;
101  }
102 
103  //use subscriber for handler to get fd and delete event
104  memcpy(&instance->subscriber, subscriber, sizeof(instance->subscriber));
105  instance->arg = arg;
106 
107  EventSelectHandler prev=NULL;
108  EventSelectHandler current = base->head;
109  while(current) {
110  /*list is sorted, so inset place == before over fd num place*/
111  if(instance->subscriber.fd < current->subscriber.fd) {
112  break;
113  }
114  prev = current;
115  current = current->next;
116  }
117  event_select_handler_insert(base, prev, instance);
118 
119  /*change max fd*/
120  if(base->tail == instance) {
121  base->maxfd = instance->subscriber.fd;
122  }
123 
124  DEBUG_PRINT("maxfd [%d]\n" , base->maxfd);
125  /*add set flag*/
126  event_select_set_fds(base, &instance->subscriber);
127  return instance;
128 }
129 
131 void * event_if_update(EventInstance this, EventHandler handler, EventSubscriber subscriber, void *arg) {
132  EventSelect base = (EventSelect)this;
133  EventSelectHandler instance = (EventSelectHandler) handler;
134 
135  DEBUG_PRINT("event_update [%d]\n" , instance->subscriber.fd);
136  /*is different event?*/
137  if(instance->subscriber.eventflag != subscriber->eventflag) {
138  /*unset old, and set new*/
139  event_select_unset_fds(base, &instance->subscriber);
140  event_select_set_fds(base, subscriber);
141  }
142 
143  /*copy subscribe*/
144  memcpy(&instance->subscriber, subscriber, sizeof(instance->subscriber));
145  instance->arg = arg;
146 
147  return instance;
148 }
149 
152  EventSelect base = (EventSelect)this;
153  EventSelectHandler instance = (EventSelectHandler) handler;
154 
155  DEBUG_PRINT("event_del [%d]\n" , instance->subscriber.fd);
156  /*change maxfd*/
157  if(base->tail == instance) {
158  if(base->tail->prev) {
159  base->maxfd = base->tail->prev->subscriber.fd;
160  } else {
161  base->maxfd = 0;
162  }
163  }
164 
165  /*clear fd event*/
166  event_select_unset_fds(base, &instance->subscriber);
167 
168  /*pull and free data*/
169  event_select_handler_pull(base, instance);
170  free(instance);
171 }
172 
174  return ((EventSelectHandler)handler)->subscriber.fd;
175 }
176 
179  EventSelect base = (EventSelect)this;
180  int i=0, ret=0;
181  int eventflag;
182  EventSelectHandler handler;
183  EventSubscriber subscriber;
184  base->is_stop=0;
185  while(!base->is_stop) {
186  /*reset fds*/
187  memcpy(&base->waitfds, &base->storefds, sizeof(base->storefds));
188  memcpy(&base->use_timeout, &base->timeout, sizeof(base->use_timeout));
189 
190 // DEBUG_ERRPRINT("Wait!\n" );
191  ret = select(base->maxfd + 1, &base->waitfds.readfds, &base->waitfds.writefds, &base->waitfds.exceptfds, &base->use_timeout);
192  if(ret<0) {
193  DEBUG_ERRPRINT("Exit loop! errno=%d\n", errno );
194  break;
195  }
196  /*timeout*/
197  if(ret==0) {
198 // DEBUG_ERRPRINT("Timeout!\n" );
199  continue;
200  }
201 
202  handler = base->tail;
203  while(handler) {
204  subscriber = &handler->subscriber;
205  //DEBUG_ERRPRINT("check event [%d]\n" , subscriber->fd);
206  eventflag = event_select_get_eventflag_from_fds(base, subscriber->fd);
207  if(eventflag & subscriber->eventflag) {
208  // DEBUG_ERRPRINT("call handler of [%d]\n", subscriber->fd);
209  subscriber->event_callback(subscriber->fd, eventflag, handler->arg);
210  // DEBUG_ERRPRINT("call handler of [%d] end\n", subscriber->fd);
211  }
212  /*if updated, skip current event to cross waiting event and update/delete event fdset*/
213  if(base->is_updated) {
214  base->is_updated=0;
215  break;
216  }
217  handler=handler->prev;
218  }
219  }
220  DEBUG_PRINT("###exit main loop\n");
221  return ret;
222 }
223 
226  EventSelect base = (EventSelect)this;
227  base->is_stop=1;
228 }
229 
232  return;
233 }
234 
237  EventSelect instance = (EventSelect)this;
238  if(!instance) return;
239  free(instance);
240 }
#define EV_TPOOL_READ
struct event_select_fds_t event_select_fds_t
static void event_select_reset_fds(event_select_fds_t *fds)
Utility headers
struct event_select_handler_t * EventSelectHandler
EventHandler event_if_add(EventInstance this, EventSubscriber subscriber, void *arg)
add new event
event_select_fds_t waitfds
EventSelectHandler prev
void(* free)(EventInstance this)
Definition: event_thread.c:39
EventSelectHandler next
void event_if_del(EventInstance this, EventHandler handler)
delete event
EventSelectHandler tail
int event_if_getfd(EventHandler handler)
get fd related to handler
int event_if_loop(EventInstance this)
main loop of this event
void event_if_free(EventInstance this)
free event if instance
#define EV_TPOOL_WRITE
#define DEBUG_PRINT(...)
Definition: dp_debug.h:55
void(* event_callback)(int socketfd, int eventflag, void *event_arg)
void * EventHandler
Event handler related to fd.
event_select_fds_t storefds
struct event_select_t * EventSelect
void * event_if_update(EventInstance this, EventHandler handler, EventSubscriber subscriber, void *arg)
update registered event
EventInstance event_if_new(void)
event new
EventSubscriber class instance definition, this is storaged in any threads.
static void event_select_set_fds(EventSelect this, EventSubscriber subscriber)
#define EVENT_SELECT_TIMEOUT
static int event_select_get_eventflag_from_fds(EventSelect this, int fd)
#define event_select_handler_insert(this, prev, data)
int eventflag
OR value of EV_TPOOL_XXX definition.
#define EV_TPOOL_HUNGUP
EventSelectHandler head
int fd
file descripter of this subscriber
static void event_select_unset_fds(EventSelect this, EventSubscriber subscriber)
void * EventInstance
Event management instance which get from event_if_new.
#define DEBUG_ERRPRINT(...)
Definition: dp_debug.h:69
void event_if_exit(EventInstance this)
exit after main loop
#define event_select_handler_pull(this, data)
struct timeval use_timeout
struct timeval timeout
event_subscriber_t subscriber
void event_if_loopbreak(EventInstance this)
break event