+#include "Fifo.h"\r
+\r
+/**\r
+ *\r
+ */\r
+Fifo::Fifo(char* name, unsigned size = 18) {\r
+ //std::cout << "Create Fifo." << std::endl;\r
+ //except at the beginning, _head and _tail must never overlap,\r
+ //otherwise one does not know whether the buffer is full or\r
+ //empty. to have nevertheless a buffer with the given capacity,\r
+ //a buffer with one more element is allocated.\r
+ _size = size + 1;\r
+ _buffer = new char[_size];\r
+ _head = 0;\r
+ _tail = 0;\r
+ _name = new char[strlen(name) + 1];\r
+ strcpy(_name, name);\r
+ _mutex = new Mutex();\r
+ _readCondition = new Condition(_mutex);\r
+ _writeCondition = new Condition(_mutex);\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+Fifo::~Fifo() {\r
+ //std::cout << "Delete Fifo." << std::endl;\r
+ if (_buffer) {\r
+ delete _buffer;\r
+ }\r
+ if (_name) {\r
+ delete _name;\r
+ }\r
+ if (_readCondition) {\r
+ delete _readCondition;\r
+ }\r
+ if (_writeCondition) {\r
+ delete _writeCondition;\r
+ }\r
+ if (_mutex) {\r
+ delete _mutex;\r
+ }\r
+\r
+ _buffer = 0;\r
+ _head = 0;\r
+ _tail = 0;\r
+ _name = 0;\r
+ _readCondition = 0;\r
+ _writeCondition = 0;\r
+ _mutex = 0;\r
+ //std::cout << "Deleted Fifo." << std::endl;\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+unsigned Fifo::read(void *destination, unsigned len) {\r
+ char* buffer = (char*)destination;\r
+ unsigned read = 0;\r
+ //std::cout << "Try to read " << len << " bytes from Fifo " << _name << "." << std::endl;\r
+\r
+ while (read < len) {\r
+ _mutex->lock();\r
+ while (used() == 0) {\r
+ _writeCondition->wait();\r
+ }\r
+ _mutex->unlock();\r
+\r
+ if ((len - read) < used()) {\r
+ while (read < len) {\r
+ _mutex->lock();\r
+ unsigned tocopy = (len - read + _tail >= _size) ? _size - _tail : len - read;\r
+ memcpy(buffer, _buffer + _tail, tocopy);\r
+ _tail = (_tail + tocopy) % _size;\r
+ read += tocopy;\r
+ buffer += tocopy;\r
+ _mutex->unlock();\r
+ }\r
+ _readCondition->notify();\r
+ } else {\r
+ _mutex->lock();\r
+ *buffer++ = *(_buffer + _tail % _size);\r
+ _tail = (_tail + 1) % _size;\r
+ read++;\r
+ _mutex->unlock();\r
+ _readCondition->notify();\r
+ }\r
+ }\r
+\r
+ //std::cout << "Read " << read << " bytes from Fifo " << _name << "." << std::endl;\r
+ return read;\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+unsigned Fifo::write(const void *source, unsigned len) {\r
+ char* buffer = (char*)source;\r
+ unsigned write = 0;\r
+ //std::cout << "Try to write " << len << " bytes to Fifo " << _name << std::endl;\r
+\r
+ while (write < len) {\r
+ _mutex->lock();\r
+ while (unused() == 0) {\r
+ _readCondition->wait();\r
+ }\r
+ _mutex->unlock();\r
+\r
+ if ((len - write) < unused()) {\r
+ while (write < len) {\r
+ unsigned tocopy = (len - write + _head >= _size) ? _size - _head : len - write;\r
+ _mutex->lock();\r
+ memcpy(_buffer + _head, buffer, tocopy);\r
+ _head = (_head + tocopy) % _size;\r
+ write += tocopy;\r
+ buffer += tocopy;\r
+ _mutex->unlock();\r
+ }\r
+ _writeCondition->notify();\r
+ } else {\r
+ _mutex->lock();\r
+ *(_buffer + (unsigned)(_head) % _size) = *buffer++;\r
+ _head = (_head + 1) % _size;\r
+ write++;\r
+ _mutex->unlock();\r
+ _writeCondition->notify();\r
+ }\r
+ }\r
+ //std::cout << "Wrote " << write << " bytes to Fifo " << _name << "." << std::endl;\r
+ return write;\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+unsigned Fifo::size() const {\r
+ return (_size - 1);\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+unsigned Fifo::unused() const {\r
+ return (_size - 1) - used();\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+unsigned Fifo::used() const {\r
+ if (_head >= _tail) {\r
+ return _head - _tail;\r
+ }\r
+ return _head + _size - _tail;\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+char* Fifo::getName() const {\r
+ return _name;\r
+}\r
+\r
+/**\r
+ * Test the implementation\r
+ */\r
+/*\r
+#include <iostream>\r
+void* producer(void *fifo)\r
+{\r
+ const char *str =\r
+ "Visit www.systemc.org and see what SystemC can do for you today!\n";\r
+\r
+ while (*str) {\r
+ //printf("%c", *str);\r
+ ((Fifo*)fifo)->write((void*)str++, 4);\r
+ }\r
+ printf("\nproducer returns.\n");\r
+ return 0;\r
+}\r
+\r
+void* consumer(void *fifo)\r
+{\r
+ char c;\r
+ while (c != '\n') {\r
+ ((Fifo*)fifo)->read(&c, 4);\r
+ std::cout << c << std::flush;\r
+\r
+ if (((Fifo*)fifo)->used() == 1)\r
+ std::cout << "<1>" << std::flush;\r
+ if (((Fifo*)fifo)->used() == 9)\r
+ std::cout << "<9>" << std::flush;\r
+ }\r
+ printf("\nconsumer returns.\n");\r
+ return 0;\r
+}\r
+\r
+\r
+int main() {\r
+ Fifo *fifo = new Fifo("fifo", 3);\r
+ pthread_t *producer_thread = new pthread_t;\r
+ pthread_t *consumer_thread = new pthread_t;\r
+\r
+ pthread_attr_t attributes;\r
+ pthread_attr_init(&attributes);\r
+ pthread_attr_setstacksize(&attributes, 131072);\r
+\r
+ if (pthread_create(consumer_thread, &attributes, consumer, fifo)) {\r
+ std::cout << "Error: Could not start consumer." << std::endl;\r
+ std::cout << "Exit." << std::endl;\r
+ exit(1);\r
+ }\r
+ pthread_attr_destroy(&attributes);\r
+\r
+ pthread_attr_init(&attributes);\r
+ pthread_attr_setstacksize(&attributes, 131072);\r
+ if (pthread_create(producer_thread, &attributes, producer, fifo)) {\r
+ std::cout << "Error: Could not start producer." << std::endl;\r
+ std::cout << "Exit." << std::endl;\r
+ exit(1);\r
+ }\r
+ pthread_attr_destroy(&attributes);\r
+\r
+\r
+ pthread_join(*consumer_thread, 0);\r
+ delete fifo;\r
+ return 0;\r
+}\r
+*/\r