dol: initial dol commit
[jump.git] / dol / src / dol / visitor / PipeAndFilter / lib / Fifo.cpp
diff --git a/dol/src/dol/visitor/PipeAndFilter/lib/Fifo.cpp b/dol/src/dol/visitor/PipeAndFilter/lib/Fifo.cpp
new file mode 100644 (file)
index 0000000..a88fd98
--- /dev/null
@@ -0,0 +1,229 @@
+#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