libevfibers
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
fiber.h
Go to the documentation of this file.
1 /********************************************************************
2 
3  Copyright 2012 Konstantin Olkhovskiy <lupus@oxnull.net>
4 
5  This file is part of libevfibers.
6 
7  libevfibers is free software: you can redistribute it and/or modify
8  it under the terms of the GNU Lesser General Public License as
9  published by the Free Software Foundation, either version 3 of the
10  License, or any later version.
11 
12  libevfibers is distributed in the hope that it will be useful, but
13  WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  Lesser General Public License for more details.
16 
17  You should have received a copy of the GNU Lesser General
18  Public License along with libevfibers. If not, see
19  <http://www.gnu.org/licenses/>.
20 
21  ********************************************************************/
22 
143 #ifndef _FBR_FIBER_H_
144 #define _FBR_FIBER_H_
145 
149 #include <unistd.h>
150 #include <stdarg.h>
151 #include <stddef.h>
152 #include <string.h>
153 #include <sys/types.h>
154 #include <sys/socket.h>
155 #include <sys/queue.h>
156 #include <assert.h>
157 #include <ev.h>
158 
162 #define FBR_CALL_STACK_SIZE 16
163 
166 #define FBR_STACK_SIZE (64 * 1024) /* 64 KB */
167 
172 #ifdef NDEBUG
173 #define fbr_assert(context, expr) ((void)(0))
174 #else
175 #define fbr_assert(context, expr) \
176  do { \
177  __typeof__(expr) ex = (expr); \
178  if (ex) \
179  (void)(0); \
180  else { \
181  fbr_dump_stack(context, fbr_log_e); \
182  __assert_fail(__STRING(expr), __FILE__, __LINE__, __ASSERT_FUNCTION); \
183  } \
184  } while (0)
185 #endif
186 
192 #define fbr_container_of(ptr, type, member) ({ \
193  const typeof( ((type *)0)->member ) *__mptr = (ptr); \
194  (type *)( (char *)__mptr - offsetof(type,member) ); \
195  })
196 
197 struct fbr_context_private;
198 struct fbr_logger;
204 typedef __uint128_t fbr_id_t;
205 
214  FBR_SUCCESS = 0,
215  FBR_EINVAL,
216  FBR_ENOFIBER,
217  FBR_ESYSTEM,
218  FBR_EBUFFERMMAP,
219  FBR_ENOKEY,
220 };
221 
229 struct fbr_context {
230  struct fbr_context_private *__p;
233  struct fbr_logger *logger;
234 };
235 
239 #define FBR_P struct fbr_context *fctx
240 
244 #define FBR_PU __attribute__((unused)) FBR_P
245 
250 #define FBR_P_ FBR_P,
251 
255 #define FBR_PU_ __attribute__((unused)) FBR_P_
256 
260 #define FBR_A fctx
261 
266 #define FBR_A_ FBR_A,
267 
277 typedef void (*fbr_fiber_func_t)(FBR_P_ void *_arg);
278 
291 typedef void (*fbr_alloc_destructor_func_t)(FBR_P_ void *ptr, void *context);
292 
299  FBR_LOG_ERROR = 0,
300  FBR_LOG_WARNING,
301  FBR_LOG_NOTICE,
302  FBR_LOG_INFO,
303  FBR_LOG_DEBUG
304 };
305 
306 struct fbr_logger;
307 
320 typedef void (*fbr_log_func_t)(FBR_P_ struct fbr_logger *logger,
321  enum fbr_log_level level, const char *format, va_list ap);
322 
331 typedef void (*fbr_logutil_func_t)(FBR_P_ const char *format, ...);
332 
338 struct fbr_logger {
341  void *data;
342 };
343 
351 static inline int fbr_need_log(FBR_P_ enum fbr_log_level level)
352 {
353  return level <= fctx->logger->level;
354 }
355 
359 static inline void fbr_set_log_level(FBR_P_ enum fbr_log_level desired_level)
360 {
361  fctx->logger->level = desired_level;
362 }
363 
372 };
373 
374 struct fbr_ev_base;
375 
385 typedef void (*fbr_destructor_func_t)(FBR_P_ void *arg);
386 
408  void *arg;
409  TAILQ_ENTRY(fbr_destructor) entries; //Private
410  int active; //Private
411 };
412 
413 #define FBR_DESTRUCTOR_INITIALIZER { \
414  .func = NULL, \
415  .arg = NULL, \
416  .active = 0, \
417 };
418 
419 struct fbr_id_tailq;
420 
422  /* Private structure */
423  fbr_id_t id;
424  struct fbr_ev_base *ev;
425  TAILQ_ENTRY(fbr_id_tailq_i) entries;
426  struct fbr_destructor dtor;
427  struct fbr_id_tailq *head;
428 };
429 
430 TAILQ_HEAD(fbr_id_tailq, fbr_id_tailq_i);
431 
440 struct fbr_ev_base {
443  int arrived;
444  struct fbr_context *fctx; //Private
445  void *data; //Private
446  struct fbr_id_tailq_i item; //Private
447 };
448 
457 #define fbr_ev_upcast(ptr, type_no_struct) \
458  fbr_container_of(ptr, struct type_no_struct, ev_base)
459 
470  ev_watcher *w;
471  struct fbr_ev_base ev_base;
472 };
473 
481 struct fbr_ev_mutex {
482  struct fbr_mutex *mutex;
483  struct fbr_ev_base ev_base;
484 };
485 
494  struct fbr_cond_var *cond;
496  struct fbr_mutex *mutex;
497  struct fbr_ev_base ev_base;
498 };
499 
507 struct fbr_mutex {
508  fbr_id_t locked_by;
509  struct fbr_id_tailq pending;
510  TAILQ_ENTRY(fbr_mutex) entries;
511 };
512 
520 struct fbr_cond_var {
521  struct fbr_mutex *mutex;
522  struct fbr_id_tailq waiting;
523 };
524 
525 struct vrb;
533 struct fbr_buffer {
534  struct vrb *vrb;
535  size_t prepared_bytes;
536  size_t waiting_bytes;
537  struct fbr_cond_var committed_cond;
538  struct fbr_mutex write_mutex;
539  struct fbr_cond_var bytes_freed_cond;
540  struct fbr_mutex read_mutex;
541 };
542 
551 typedef unsigned int fbr_key_t;
552 
553 
557 #define FBR_MAX_KEY 64
558 
568 void fbr_destructor_add(FBR_P_ struct fbr_destructor *dtor);
569 
579 void fbr_destructor_remove(FBR_P_ struct fbr_destructor *dtor,
580  int call);
581 
591 static inline void fbr_destructor_init(struct fbr_destructor *dtor)
592 {
593  memset(dtor, 0x00, sizeof(*dtor));
594 }
595 
604 void fbr_ev_watcher_init(FBR_P_ struct fbr_ev_watcher *ev, ev_watcher *w);
605 
614 void fbr_ev_mutex_init(FBR_P_ struct fbr_ev_mutex *ev,
615  struct fbr_mutex *mutex);
616 
625 void fbr_ev_cond_var_init(FBR_P_ struct fbr_ev_cond_var *ev,
626  struct fbr_cond_var *cond, struct fbr_mutex *mutex);
627 
637 int fbr_ev_wait_one(FBR_P_ struct fbr_ev_base *one);
638 
650 int fbr_ev_wait(FBR_P_ struct fbr_ev_base *events[]);
651 
661 int fbr_transfer(FBR_P_ fbr_id_t to);
662 
673 void fbr_init(struct fbr_context *fctx, struct ev_loop *loop);
674 
683 void fbr_destroy(FBR_P);
684 
695 void fbr_enable_backtraces(FBR_P, int enabled);
696 
703 const char *fbr_strerror(FBR_P_ enum fbr_error_code code);
704 
716 void fbr_log_e(FBR_P_ const char *format, ...)
717  __attribute__ ((format (printf, 2, 3)));
718 
730 void fbr_log_w(FBR_P_ const char *format, ...)
731  __attribute__ ((format (printf, 2, 3)));
732 
744 void fbr_log_n(FBR_P_ const char *format, ...)
745  __attribute__ ((format (printf, 2, 3)));
746 
758 void fbr_log_i(FBR_P_ const char *format, ...)
759  __attribute__ ((format (printf, 2, 3)));
760 
772 void fbr_log_d(FBR_P_ const char *format, ...)
773  __attribute__ ((format (printf, 2, 3)));
774 
778 #define FBR_MAX_FIBER_NAME 64
779 
806 fbr_id_t fbr_create(FBR_P_ const char *name, fbr_fiber_func_t func, void *arg,
807  size_t stack_size);
808 
822 const char *fbr_get_name(FBR_P_ fbr_id_t id);
823 
835 int fbr_set_name(FBR_P_ fbr_id_t id, const char *name);
836 
853 int fbr_disown(FBR_P_ fbr_id_t parent);
854 
864 fbr_id_t fbr_parent(FBR_P);
865 
881 int fbr_reclaim(FBR_P_ fbr_id_t fiber);
882 
888 int fbr_is_reclaimed(FBR_P_ fbr_id_t fiber);
889 
894 fbr_id_t fbr_self(FBR_P);
895 
901 int fbr_key_create(FBR_P_ fbr_key_t *key);
902 
907 int fbr_key_delete(FBR_P_ fbr_key_t key);
908 
913 int fbr_key_set(FBR_P_ fbr_id_t id, fbr_key_t key, void *value);
914 
919 void *fbr_key_get(FBR_P_ fbr_id_t id, fbr_key_t key);
920 
932 void fbr_yield(FBR_P);
933 
946 void *fbr_alloc(FBR_P_ size_t size);
947 
965  void *context);
966 
977 void *fbr_calloc(FBR_P_ unsigned int nmemb, size_t size);
978 
988 void fbr_free(FBR_P_ void *ptr);
989 
999 void fbr_free_nd(FBR_P_ void *ptr);
1000 
1010 int fbr_fd_nonblock(FBR_P_ int fd);
1011 
1030 ssize_t fbr_read(FBR_P_ int fd, void *buf, size_t count);
1031 
1052 ssize_t fbr_read_all(FBR_P_ int fd, void *buf, size_t count);
1053 
1071 ssize_t fbr_readline(FBR_P_ int fd, void *buffer, size_t n);
1072 
1089 ssize_t fbr_write(FBR_P_ int fd, const void *buf, size_t count);
1090 
1109 ssize_t fbr_write_all(FBR_P_ int fd, const void *buf, size_t count);
1110 
1128 ssize_t fbr_recvfrom(FBR_P_ int sockfd, void *buf, size_t len, int flags,
1129  struct sockaddr *src_addr, socklen_t *addrlen);
1130 
1148 ssize_t fbr_sendto(FBR_P_ int sockfd, const void *buf, size_t len, int flags, const
1149  struct sockaddr *dest_addr, socklen_t addrlen);
1150 
1165 int fbr_accept(FBR_P_ int sockfd, struct sockaddr *addr, socklen_t *addrlen);
1166 
1175 ev_tstamp fbr_sleep(FBR_P_ ev_tstamp seconds);
1176 
1182 void fbr_dump_stack(FBR_P_ fbr_logutil_func_t log);
1183 
1197 void fbr_mutex_init(FBR_P_ struct fbr_mutex *mutex);
1198 
1211 void fbr_mutex_lock(FBR_P_ struct fbr_mutex *mutex);
1212 
1226 int fbr_mutex_trylock(FBR_P_ struct fbr_mutex *mutex);
1227 
1240 void fbr_mutex_unlock(FBR_P_ struct fbr_mutex *mutex);
1241 
1253 void fbr_mutex_destroy(FBR_P_ struct fbr_mutex *mutex);
1254 
1267 void fbr_cond_init(FBR_P_ struct fbr_cond_var *cond);
1268 
1279 void fbr_cond_destroy(FBR_P_ struct fbr_cond_var *cond);
1280 
1296 int fbr_cond_wait(FBR_P_ struct fbr_cond_var *cond, struct fbr_mutex *mutex);
1297 
1309 void fbr_cond_broadcast(FBR_P_ struct fbr_cond_var *cond);
1310 
1322 void fbr_cond_signal(FBR_P_ struct fbr_cond_var *cond);
1323 
1335 int fbr_buffer_init(FBR_P_ struct fbr_buffer *buffer, size_t size);
1336 
1344 void fbr_buffer_destroy(FBR_P_ struct fbr_buffer *buffer);
1345 
1361 void *fbr_buffer_alloc_prepare(FBR_P_ struct fbr_buffer *buffer, size_t size);
1362 
1371 void fbr_buffer_alloc_commit(FBR_P_ struct fbr_buffer *buffer);
1372 
1382 void fbr_buffer_alloc_abort(FBR_P_ struct fbr_buffer *buffer);
1383 
1397 void *fbr_buffer_read_address(FBR_P_ struct fbr_buffer *buffer, size_t size);
1398 
1408 void fbr_buffer_read_advance(FBR_P_ struct fbr_buffer *buffer);
1409 
1419 void fbr_buffer_read_discard(FBR_P_ struct fbr_buffer *buffer);
1420 
1429 size_t fbr_buffer_bytes(FBR_P_ struct fbr_buffer *buffer);
1430 
1439 size_t fbr_buffer_free_bytes(FBR_P_ struct fbr_buffer *buffer);
1440 
1446 static inline struct fbr_cond_var *fbr_buffer_cond_read(FBR_PU_
1447  struct fbr_buffer *buffer)
1448 {
1449  return &buffer->committed_cond;
1450 }
1451 
1457 static inline struct fbr_cond_var *fbr_buffer_cond_write(FBR_PU_
1458  struct fbr_buffer *buffer)
1459 {
1460  return &buffer->bytes_freed_cond;
1461 }
1462 
1472 static inline int fbr_buffer_wait_read(FBR_P_ struct fbr_buffer *buffer,
1473  size_t size)
1474 {
1475  struct fbr_mutex mutex;
1476  int retval;
1477  fbr_mutex_init(FBR_A_ &mutex);
1478  fbr_mutex_lock(FBR_A_ &mutex);
1479  while (fbr_buffer_bytes(FBR_A_ buffer) < size) {
1480  retval = fbr_cond_wait(FBR_A_ &buffer->committed_cond, &mutex);
1481  assert(0 == retval);
1482  }
1483  fbr_mutex_unlock(FBR_A_ &mutex);
1484  fbr_mutex_destroy(FBR_A_ &mutex);
1485  return 1;
1486 }
1487 
1497 static inline int fbr_buffer_can_read(FBR_P_ struct fbr_buffer *buffer,
1498  size_t size)
1499 {
1500  return fbr_buffer_bytes(FBR_A_ buffer) >= size;
1501 }
1502 
1512 static inline int fbr_buffer_wait_write(FBR_P_ struct fbr_buffer *buffer,
1513  size_t size)
1514 {
1515  struct fbr_mutex mutex;
1516  int retval;
1517  fbr_mutex_init(FBR_A_ &mutex);
1518  fbr_mutex_lock(FBR_A_ &mutex);
1519  while (fbr_buffer_free_bytes(FBR_A_ buffer) < size) {
1520  retval = fbr_cond_wait(FBR_A_ &buffer->bytes_freed_cond,
1521  &mutex);
1522  assert(0 == retval);
1523  }
1524  fbr_mutex_unlock(FBR_A_ &mutex);
1525  fbr_mutex_destroy(FBR_A_ &mutex);
1526  return 1;
1527 }
1528 
1538 static inline int fbr_buffer_can_write(FBR_P_ struct fbr_buffer *buffer,
1539  size_t size)
1540 {
1541  return fbr_buffer_free_bytes(FBR_A_ buffer) >= size;
1542 }
1543 
1552 void *fbr_get_user_data(FBR_P_ fbr_id_t id);
1553 
1563 int fbr_set_user_data(FBR_P_ fbr_id_t id, void *data);
1564 
1565 #endif