2 Calf Box, an open source musical instrument.
3 Copyright (C) 2010-2013 Krzysztof Foltman
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
31 uint64_t pad
; // ensure the write-related and read-related structs are on 64 bit boundary
33 uint32_t write_offset
;
38 extern struct cbox_fifo
*cbox_fifo_new(uint32_t size
);
40 static inline uint32_t cbox_fifo_readsize(struct cbox_fifo
*fifo
);
41 static inline uint32_t cbox_fifo_writespace(struct cbox_fifo
*fifo
);
42 static inline gboolean
cbox_fifo_read_atomic(struct cbox_fifo
*fifo
, void *dest
, uint32_t bytes
);
43 static inline gboolean
cbox_fifo_write_atomic(struct cbox_fifo
*fifo
, const void *src
, uint32_t bytes
);
44 static inline gboolean
cbox_fifo_peek(struct cbox_fifo
*fifo
, void *dest
, uint32_t bytes
);
45 static inline gboolean
cbox_fifo_consume(struct cbox_fifo
*fifo
, uint32_t bytes
);
47 extern void cbox_fifo_destroy(struct cbox_fifo
*fifo
);
50 static inline uint32_t cbox_fifo_readsize(struct cbox_fifo
*fifo
)
52 return fifo
->write_count
- fifo
->read_count
;
55 static inline uint32_t cbox_fifo_writespace(struct cbox_fifo
*fifo
)
57 return fifo
->size
- (fifo
->write_count
- fifo
->read_count
);
60 static inline gboolean
cbox_fifo_read_impl(struct cbox_fifo
*fifo
, void *dest
, uint32_t bytes
, gboolean advance
)
63 if (fifo
->write_count
- fifo
->read_count
< bytes
)
68 uint32_t ofs
= fifo
->read_count
- fifo
->read_offset
;
69 assert(ofs
>= 0 && ofs
< fifo
->size
);
70 if (ofs
+ bytes
> fifo
->size
)
73 uint32_t firstpart
= fifo
->size
- ofs
;
74 memcpy(dstb
, fifo
->data
+ ofs
, firstpart
);
75 memcpy(dstb
+ firstpart
, fifo
->data
, bytes
- firstpart
);
78 memcpy(dest
, fifo
->data
+ ofs
, bytes
);
84 // Make sure data are copied before signalling that they can be overwritten
85 fifo
->read_count
+= bytes
;
86 if (fifo
->read_count
- fifo
->read_offset
>= fifo
->size
)
87 fifo
->read_offset
+= fifo
->size
;
94 static inline gboolean
cbox_fifo_read_atomic(struct cbox_fifo
*fifo
, void *dest
, uint32_t bytes
)
96 return cbox_fifo_read_impl(fifo
, dest
, bytes
, TRUE
);
99 static inline gboolean
cbox_fifo_peek(struct cbox_fifo
*fifo
, void *dest
, uint32_t bytes
)
101 return cbox_fifo_read_impl(fifo
, dest
, bytes
, FALSE
);
104 static inline gboolean
cbox_fifo_consume(struct cbox_fifo
*fifo
, uint32_t bytes
)
106 return cbox_fifo_read_impl(fifo
, NULL
, bytes
, TRUE
);
109 static inline gboolean
cbox_fifo_write_atomic(struct cbox_fifo
*fifo
, const void *src
, uint32_t bytes
)
111 if (fifo
->size
- (fifo
->write_count
- fifo
->read_count
) < bytes
)
114 uint32_t ofs
= fifo
->write_count
- fifo
->write_offset
;
115 assert(ofs
>= 0 && ofs
< fifo
->size
);
116 if (ofs
+ bytes
> fifo
->size
)
118 const uint8_t *srcb
= src
;
119 uint32_t firstpart
= fifo
->size
- ofs
;
120 memcpy(fifo
->data
+ ofs
, srcb
, firstpart
);
121 memcpy(fifo
->data
, srcb
+ firstpart
, bytes
- firstpart
);
124 memcpy(fifo
->data
+ ofs
, src
, bytes
);
126 // Make sure data are in the buffer before announcing the availability
127 __sync_synchronize();
128 fifo
->write_count
+= bytes
;
129 if (fifo
->write_count
- fifo
->write_offset
>= fifo
->size
)
130 fifo
->write_offset
+= fifo
->size
;