JasonWoof / cmus-unofficial
- Source
- Commits
- Network (2)
- Issues (0)
- Downloads (0)
- Wiki (1)
- Graphs
-
Tree:
9e8eb53
Jason Woofenden (committer)
Thu May 28 15:30:57 -0700 2009
cmus-unofficial / buffer.c
| f35b01de » | Timo Hirvonen | 2006-02-27 | 1 | #include "buffer.h" | |
| 2 | #include "xmalloc.h" | ||||
| 3 | #include "locking.h" | ||||
| 4 | #include "debug.h" | ||||
| 5 | |||||
| 6 | /* | ||||
| 7 | * chunk can be accessed by either consumer OR producer, not both at same time | ||||
| 8 | * -> no need to lock | ||||
| 9 | */ | ||||
| 10 | struct chunk { | ||||
| 11 | char data[CHUNK_SIZE]; | ||||
| 12 | |||||
| 13 | /* index to data, first filled byte */ | ||||
| 14 | unsigned int l; | ||||
| 15 | |||||
| 16 | /* index to data, last filled byte + 1 | ||||
| 17 | * | ||||
| 18 | * there are h - l bytes available (filled) | ||||
| 19 | */ | ||||
| 20 | unsigned int h : 31; | ||||
| 21 | |||||
| 22 | /* if chunk is marked filled it can only be accessed by consumer | ||||
| 23 | * otherwise only producer is allowed to access the chunk | ||||
| 24 | */ | ||||
| 25 | unsigned int filled : 1; | ||||
| 26 | }; | ||||
| 27 | |||||
| 28 | unsigned int buffer_nr_chunks; | ||||
| 29 | |||||
| 30 | static pthread_mutex_t buffer_mutex = CMUS_MUTEX_INITIALIZER; | ||||
| 31 | static struct chunk *buffer_chunks = NULL; | ||||
| 32 | static unsigned int buffer_ridx; | ||||
| 33 | static unsigned int buffer_widx; | ||||
| 34 | |||||
| 35 | void buffer_init(void) | ||||
| 36 | { | ||||
| 37 | free(buffer_chunks); | ||||
| 38 | buffer_chunks = xnew(struct chunk, buffer_nr_chunks); | ||||
| 39 | buffer_reset(); | ||||
| 40 | } | ||||
| 41 | |||||
| 42 | /* | ||||
| c8121dda » | Timo Hirvonen | 2006-02-27 | 43 | * @pos: returned pointer to available data | |
| 44 | * | ||||
| 45 | * Returns number of bytes available at @pos | ||||
| f35b01de » | Timo Hirvonen | 2006-02-27 | 46 | * | |
| 47 | * After reading bytes mark them consumed calling buffer_consume(). | ||||
| 48 | */ | ||||
| c8121dda » | Timo Hirvonen | 2006-02-27 | 49 | int buffer_get_rpos(char **pos) | |
| f35b01de » | Timo Hirvonen | 2006-02-27 | 50 | { | |
| 51 | struct chunk *c; | ||||
| c8121dda » | Timo Hirvonen | 2006-02-27 | 52 | int size = 0; | |
| f35b01de » | Timo Hirvonen | 2006-02-27 | 53 | ||
| 54 | cmus_mutex_lock(&buffer_mutex); | ||||
| 55 | c = &buffer_chunks[buffer_ridx]; | ||||
| 56 | if (c->filled) { | ||||
| c8121dda » | Timo Hirvonen | 2006-02-27 | 57 | size = c->h - c->l; | |
| 58 | *pos = c->data + c->l; | ||||
| f35b01de » | Timo Hirvonen | 2006-02-27 | 59 | } | |
| 60 | cmus_mutex_unlock(&buffer_mutex); | ||||
| c8121dda » | Timo Hirvonen | 2006-02-27 | 61 | ||
| 62 | return size; | ||||
| f35b01de » | Timo Hirvonen | 2006-02-27 | 63 | } | |
| 64 | |||||
| 65 | /* | ||||
| c8121dda » | Timo Hirvonen | 2006-02-27 | 66 | * @pos: pointer to buffer position where data can be written | |
| 67 | * | ||||
| 68 | * Returns number of bytes can be written to @pos. If the return value is | ||||
| 69 | * non-zero it is guaranteed to be >= 1024. | ||||
| f35b01de » | Timo Hirvonen | 2006-02-27 | 70 | * | |
| 71 | * After writing bytes mark them filled calling buffer_fill(). | ||||
| 72 | */ | ||||
| c8121dda » | Timo Hirvonen | 2006-02-27 | 73 | int buffer_get_wpos(char **pos) | |
| f35b01de » | Timo Hirvonen | 2006-02-27 | 74 | { | |
| 75 | struct chunk *c; | ||||
| c8121dda » | Timo Hirvonen | 2006-02-27 | 76 | int size = 0; | |
| f35b01de » | Timo Hirvonen | 2006-02-27 | 77 | ||
| 78 | cmus_mutex_lock(&buffer_mutex); | ||||
| 79 | c = &buffer_chunks[buffer_widx]; | ||||
| c8121dda » | Timo Hirvonen | 2006-02-27 | 80 | if (!c->filled) { | |
| 81 | size = CHUNK_SIZE - c->h; | ||||
| 82 | *pos = c->data + c->h; | ||||
| f35b01de » | Timo Hirvonen | 2006-02-27 | 83 | } | |
| 84 | cmus_mutex_unlock(&buffer_mutex); | ||||
| c8121dda » | Timo Hirvonen | 2006-02-27 | 85 | ||
| 86 | return size; | ||||
| f35b01de » | Timo Hirvonen | 2006-02-27 | 87 | } | |
| 88 | |||||
| 89 | void buffer_consume(int count) | ||||
| 90 | { | ||||
| 91 | struct chunk *c; | ||||
| 92 | |||||
| 93 | BUG_ON(count <= 0); | ||||
| 94 | cmus_mutex_lock(&buffer_mutex); | ||||
| 95 | c = &buffer_chunks[buffer_ridx]; | ||||
| 96 | BUG_ON(!c->filled); | ||||
| 97 | c->l += count; | ||||
| 98 | if (c->l == c->h) { | ||||
| 99 | c->l = 0; | ||||
| 100 | c->h = 0; | ||||
| 101 | c->filled = 0; | ||||
| 102 | buffer_ridx++; | ||||
| 103 | buffer_ridx %= buffer_nr_chunks; | ||||
| 104 | } | ||||
| 105 | cmus_mutex_unlock(&buffer_mutex); | ||||
| 106 | } | ||||
| 107 | |||||
| c8121dda » | Timo Hirvonen | 2006-02-27 | 108 | /* chunk is marked filled if free bytes < 1024 or count == 0 */ | |
| 26c3ab52 » | Timo Hirvonen | 2006-10-15 | 109 | int buffer_fill(int count) | |
| f35b01de » | Timo Hirvonen | 2006-02-27 | 110 | { | |
| 111 | struct chunk *c; | ||||
| 26c3ab52 » | Timo Hirvonen | 2006-10-15 | 112 | int filled = 0; | |
| f35b01de » | Timo Hirvonen | 2006-02-27 | 113 | ||
| 114 | cmus_mutex_lock(&buffer_mutex); | ||||
| 115 | c = &buffer_chunks[buffer_widx]; | ||||
| 116 | BUG_ON(c->filled); | ||||
| 117 | c->h += count; | ||||
| 118 | |||||
| 119 | if (CHUNK_SIZE - c->h < 1024 || (count == 0 && c->h > 0)) { | ||||
| 120 | c->filled = 1; | ||||
| 121 | buffer_widx++; | ||||
| 122 | buffer_widx %= buffer_nr_chunks; | ||||
| 26c3ab52 » | Timo Hirvonen | 2006-10-15 | 123 | filled = 1; | |
| f35b01de » | Timo Hirvonen | 2006-02-27 | 124 | } | |
| 125 | |||||
| 126 | cmus_mutex_unlock(&buffer_mutex); | ||||
| 26c3ab52 » | Timo Hirvonen | 2006-10-15 | 127 | return filled; | |
| f35b01de » | Timo Hirvonen | 2006-02-27 | 128 | } | |
| 129 | |||||
| 130 | void buffer_reset(void) | ||||
| 131 | { | ||||
| 132 | int i; | ||||
| 133 | |||||
| 134 | cmus_mutex_lock(&buffer_mutex); | ||||
| 135 | buffer_ridx = 0; | ||||
| 136 | buffer_widx = 0; | ||||
| 137 | for (i = 0; i < buffer_nr_chunks; i++) { | ||||
| 138 | buffer_chunks[i].l = 0; | ||||
| 139 | buffer_chunks[i].h = 0; | ||||
| 140 | buffer_chunks[i].filled = 0; | ||||
| 141 | } | ||||
| 142 | cmus_mutex_unlock(&buffer_mutex); | ||||
| 143 | } | ||||
| 144 | |||||
| 145 | int buffer_get_filled_chunks(void) | ||||
| 146 | { | ||||
| 147 | int c; | ||||
| 148 | |||||
| 149 | cmus_mutex_lock(&buffer_mutex); | ||||
| 150 | if (buffer_ridx < buffer_widx) { | ||||
| 151 | /* | ||||
| 152 | * |__##########____| | ||||
| 153 | * r w | ||||
| 154 | * | ||||
| 155 | * |############____| | ||||
| 156 | * r w | ||||
| 157 | */ | ||||
| 158 | c = buffer_widx - buffer_ridx; | ||||
| 159 | } else if (buffer_ridx > buffer_widx) { | ||||
| 160 | /* | ||||
| 161 | * |#######______###| | ||||
| 162 | * w r | ||||
| 163 | * | ||||
| 164 | * |_____________###| | ||||
| 165 | * w r | ||||
| 166 | */ | ||||
| 167 | c = buffer_nr_chunks - buffer_ridx + buffer_widx; | ||||
| 168 | } else { | ||||
| 169 | /* | ||||
| 170 | * |################| | ||||
| 171 | * r | ||||
| 172 | * w | ||||
| 173 | * | ||||
| 174 | * |________________| | ||||
| 175 | * r | ||||
| 176 | * w | ||||
| 177 | */ | ||||
| 178 | if (buffer_chunks[buffer_ridx].filled) { | ||||
| 179 | c = buffer_nr_chunks; | ||||
| 180 | } else { | ||||
| 181 | c = 0; | ||||
| 182 | } | ||||
| 183 | } | ||||
| 184 | cmus_mutex_unlock(&buffer_mutex); | ||||
| 185 | return c; | ||||
| 186 | } | ||||
