1 #include "WindowedFifo.h"
\r
7 WindowedFifo::WindowedFifo(char* name, unsigned size = 20) {
\r
8 //std::cout << "Create WindowedFifo." << std::endl;
\r
10 _buffer = new char[_size];
\r
16 //indicates whether Fifo is empty or full if _head == _tail
\r
18 _isHeadReserved = false;
\r
19 _isTailReserved = false;
\r
20 _name = new char[strlen(name) + 1];
\r
21 strcpy(_name, name);
\r
22 _mutex = new Mutex();
\r
23 _readCondition = new Condition(_mutex);
\r
24 _writeCondition = new Condition(_mutex);
\r
30 WindowedFifo::~WindowedFifo() {
\r
31 //std::cout << "Delete WindowedFifo." << std::endl;
\r
38 if (_readCondition) {
\r
39 delete _readCondition;
\r
41 if (_writeCondition) {
\r
42 delete _writeCondition;
\r
53 _writeCondition = 0;
\r
55 //std::cout << "Deleted WindowedFifo." << std::endl;
\r
61 unsigned WindowedFifo::reserve(void** dest, unsigned len) {
\r
62 char** destination = (char**)dest;
\r
63 //std::cout << "Attempt to reserve " << len << " bytes." << std::endl;
\r
65 //can only reserve once piece at a time
\r
66 if (_isHeadReserved) {
\r
72 while (unused() == 0) {
\r
73 _readCondition->wait();
\r
76 //reserve at most as much memory as still available in the buffer
\r
77 unsigned write = (len <= _size - _use ? len : _size - _use);
\r
80 //if wrap-around in buffer: return only buffer for the
\r
81 //contiguous buffer space
\r
82 if (_head + write > _size) {
\r
83 write = _size - _head;
\r
86 _headRoom = (_head + write) == _size? 0 : _head + write;
\r
87 *destination = &(_buffer[_head]);
\r
88 _isHeadReserved = true;
\r
90 //the following comparison is unsafe in a multi-threaded
\r
91 //environment and potentially leads to race-conditions
\r
92 /*if (_headRoom == _tail) {
\r
98 _writeReserve = write;
\r
101 //std::cout << "Reserved " << write << " bytes." << std::endl;
\r
108 void WindowedFifo::release() {
\r
109 if (_isHeadReserved) {
\r
110 //std::cout << "Released " << _headRoom - _head << " bytes." << std::endl;
\r
112 _use += _writeReserve;
\r
113 _isHeadReserved = false;
\r
114 _writeCondition->notify();
\r
121 unsigned WindowedFifo::capture(void **dest, unsigned len) {
\r
122 char** destination = (char**)dest;
\r
123 //std::cout << "Attempt to capture " << len << " bytes." << std::endl;
\r
125 if (_isTailReserved) {
\r
126 //std::cout << "Only one attempt to capture allowed." << std::endl;
\r
132 while (used() == 0) {
\r
133 _writeCondition->wait();
\r
136 //capture at most as much data as available in the buffer
\r
137 unsigned read = (len <= _use ? len : _use);
\r
140 //if wrap-around in buffer: return only buffer for the
\r
141 //contiguous buffer space
\r
142 if (_tail + read> _size) {
\r
143 read = _size - _tail;
\r
146 _tailRoom = (_tail + read) == _size ? 0 : _tailRoom = _tail + read;
\r
147 *destination = &(_buffer[_tail]);
\r
148 _isTailReserved = true;
\r
150 _readReserve = read;
\r
152 //std::cout << "Captured " << read << " bytes." << std::endl;
\r
160 void WindowedFifo::consume() {
\r
162 if (_isTailReserved) {
\r
163 //std::cout << "Consumed " << _tailRoom - _tail << " bytes." << std::endl;
\r
166 _use -= _readReserve;
\r
167 _isTailReserved = false;
\r
168 _readCondition->notify();
\r
176 unsigned WindowedFifo::size() const {
\r
183 unsigned WindowedFifo::unused() const {
\r
184 return _size - _use;
\r
190 unsigned WindowedFifo::used() const {
\r
192 /*if (_headRoom > _tail) {
\r
193 return _headRoom - _tail;
\r
194 } else if (_headRoom == _tail) {
\r
195 if (_isFull == true) {
\r
201 return _headRoom + _size - _tail;*/
\r
207 char* WindowedFifo::getName() const {
\r
212 * Test the implementation
\r
215 #include <iostream>
\r
219 void* producer(void *fifo)
\r
221 WindowedFifo* wfifo = (WindowedFifo*)fifo;
\r
222 for (int j = 0; j < LENGTH; j++) {
\r
223 //std::cout << "write " << i << " to Fifo. ";
\r
225 int write = wfifo->reserve((void**)&buf1, sizeof(int));
\r
227 if (write == sizeof(int)) {
\r
230 //std::cout << "used: " << std::setw(2) << wfifo->used()
\r
231 // << ", unused: " << std::setw(2) << wfifo->unused()
\r
232 // << ", size: " << std::setw(2) << wfifo->size()
\r
235 std::cout << "Not successful: " << write << std::endl;
\r
238 printf("producer returns.\n");
\r
242 void* consumer(void *fifo)
\r
244 WindowedFifo* wfifo = (WindowedFifo*)fifo;
\r
245 for (int j = 0; j < LENGTH; j++) {
\r
247 int read = wfifo->capture((void**)&buf3, sizeof(int));
\r
248 if (read == sizeof(int)) {
\r
249 std::cout << "read " << (unsigned)*buf3 << " from WindowedFifo ";
\r
250 std::cout << "used: " << std::setw(2) << wfifo->used()
\r
251 << ", unused: " << std::setw(2) << wfifo->unused()
\r
252 << ", size: " << std::setw(2) << wfifo->size()
\r
256 std::cout << "Read nothing from WindowedFifo." << std::endl;
\r
259 printf("consumer returns.\n");
\r
264 WindowedFifo *wfifo = new WindowedFifo("fifo", 12);
\r
268 wfifo->reserve((void**)&buf1, 8);
\r
272 wfifo->capture((void**)&buf2, 8);
\r
273 std::cout << "read " << *buf2 << " " << *(buf2 + 1) << std::endl;
\r
276 pthread_t *producer_thread = new pthread_t;
\r
277 pthread_t *consumer_thread = new pthread_t;
\r
279 pthread_attr_t attributes;
\r
280 pthread_attr_init(&attributes);
\r
281 pthread_attr_setstacksize(&attributes, 131072);
\r
283 if (pthread_create(consumer_thread, &attributes, consumer, wfifo)) {
\r
284 std::cout << "Error: Could not start consumer." << std::endl;
\r
285 std::cout << "Exit." << std::endl;
\r
288 pthread_attr_destroy(&attributes);
\r
290 pthread_attr_init(&attributes);
\r
291 pthread_attr_setstacksize(&attributes, 131072);
\r
292 if (pthread_create(producer_thread, &attributes, producer, wfifo)) {
\r
293 std::cout << "Error: Could not start producer." << std::endl;
\r
294 std::cout << "Exit." << std::endl;
\r
297 pthread_attr_destroy(&attributes);
\r
300 pthread_join(*consumer_thread, 0);
\r