GCS  0.2.3
gcs_fifo_lite.h
1 /*
2  * Copyright (C) 2008-2011 Codership Oy <info@codership.com>
3  *
4  * $Id: gcs_fifo_lite.h 3473 2014-02-28 02:03:19Z alex $
5  *
6  * FIFO "class" customized for particular purpose
7  * (here I decided to sacrifice generality for efficiency).
8  * Implements fixed size "mallocless" FIFO (read "ring buffer").
9  * Except gcs_fifo_create() there are two types of fifo
10  * access methods - protected and unprotected. Unprotected
11  * methods assume that calling routines implement their own
12  * protection, and thus are simplified for speed.
13  */
14 
15 #ifndef _GCS_FIFO_LITE_H_
16 #define _GCS_FIFO_LITE_H_
17 
18 #include <stdlib.h>
19 #include <unistd.h>
20 #include <string.h>
21 #include <errno.h>
22 #include <stdbool.h>
23 
24 #include <galerautils.h>
25 
26 #include "gcs.h"
27 
28 typedef struct gcs_fifo_lite
29 {
30  long length;
31  ulong item_size;
32  ulong mask;
33  ulong head;
34  ulong tail;
35  long used;
36  bool closed;
37  bool destroyed;
38  long put_wait;
39  long get_wait;
40  gu_cond_t put_cond;
41  gu_cond_t get_cond;
42  gu_mutex_t lock;
43  void* queue;
44 }
46 
47 /* Creates FIFO object. Since it practically consists of array of (void*),
48  * the length can be chosen arbitrarily high - to minimize the risk
49  * of overflow situation.
50  */
51 gcs_fifo_lite_t* gcs_fifo_lite_create (size_t length, size_t item_size);
52 void gcs_fifo_lite_close (gcs_fifo_lite_t* fifo);
53 void gcs_fifo_lite_open (gcs_fifo_lite_t* fifo);
54 long gcs_fifo_lite_destroy (gcs_fifo_lite_t* fifo);
55 
56 static inline void*
57 _gcs_fifo_lite_tail (gcs_fifo_lite_t* f)
58 {
59  return ((char*)f->queue + f->tail * f->item_size);
60 }
61 
62 static inline void*
63 _gcs_fifo_lite_head (gcs_fifo_lite_t* f)
64 {
65  return ((char*)f->queue + f->head * f->item_size);
66 }
67 
68 #define GCS_FIFO_LITE_LOCK \
69  if (gu_unlikely (gu_mutex_lock (&fifo->lock))) { \
70  gu_fatal ("Mutex lock failed."); \
71  abort(); \
72  }
73 
76 static inline void*
77 gcs_fifo_lite_get_tail (gcs_fifo_lite_t* fifo)
78 {
79  void* ret = NULL;
80 
81  GCS_FIFO_LITE_LOCK;
82 
83  while (!fifo->closed && fifo->used >= fifo->length) {
84  fifo->put_wait++;
85  gu_cond_wait (&fifo->put_cond, &fifo->lock);
86  }
87 
88  if (gu_likely(!fifo->closed)) {
89  assert (fifo->used < fifo->length);
90  ret = _gcs_fifo_lite_tail (fifo);
91  }
92  else {
93  gu_mutex_unlock (&fifo->lock);
94  }
95 
96  return ret;
97 }
98 
100 static inline void
101 gcs_fifo_lite_push_tail (gcs_fifo_lite_t* fifo)
102 {
103  fifo->tail = (fifo->tail + 1) & fifo->mask;
104  fifo->used++;
105 
106  assert (fifo->used <= fifo->length);
107 
108  if (fifo->get_wait > 0) {
109  fifo->get_wait--;
110  gu_cond_signal (&fifo->get_cond);
111  }
112 
113  gu_mutex_unlock (&fifo->lock);
114 }
115 
119 static inline void*
120 gcs_fifo_lite_get_head (gcs_fifo_lite_t* fifo)
121 {
122  void* ret = NULL;
123 
124  GCS_FIFO_LITE_LOCK;
125 
126 /* Uncomment this for blocking behaviour
127  while (!fifo->closed && 0 == fifo->used) {
128  fifo->get_wait++;
129  gu_cond_wait (&fifo->get_cond, &fifo->lock);
130  }
131 */
132  if (gu_likely(fifo->used > 0)) {
133  ret = _gcs_fifo_lite_head (fifo);
134  }
135  else {
136  gu_mutex_unlock (&fifo->lock);
137  }
138 
139  return ret;
140 }
141 
143 static inline void
144 gcs_fifo_lite_pop_head (gcs_fifo_lite_t* fifo)
145 {
146  fifo->head = (fifo->head + 1) & fifo->mask;
147  fifo->used--;
148 
149  assert (fifo->used != -1);
150 
151  if (fifo->put_wait > 0) {
152  fifo->put_wait--;
153  gu_cond_signal (&fifo->put_cond);
154  }
155 
156  gu_mutex_unlock (&fifo->lock);
157 }
158 
160 static inline long
161 gcs_fifo_lite_release (gcs_fifo_lite_t* fifo)
162 {
163  return (gu_mutex_unlock (&fifo->lock));
164 }
165 
167 static inline bool
168 gcs_fifo_lite_remove (gcs_fifo_lite_t* const fifo)
169 {
170  bool ret = false;
171  assert (fifo);
172 
173  GCS_FIFO_LITE_LOCK;
174 
175  if (fifo->used) {
176  fifo->tail = (fifo->tail - 1) & fifo->mask;
177  fifo->used--;
178  ret = true;
179 
180  if (fifo->put_wait > 0) {
181  fifo->put_wait--;
182  gu_cond_signal (&fifo->put_cond);
183  }
184  }
185 
186  gu_mutex_unlock (&fifo->lock);
187 
188  return ret;
189 }
190 
191 static inline bool
192 gcs_fifo_lite_not_full (const gcs_fifo_lite_t* const fifo)
193 {
194  return (fifo->used < fifo->length);
195 }
196 
197 #endif /* _GCS_FIFO_LITE_H_ */
Definition: gcs_fifo_lite.h:28