dol: initial dol commit
[jump.git] / dol / src / dol / visitor / PipeAndFilter / lib / Fifo.cpp
1 #include "Fifo.h"\r
2 \r
3 /**\r
4  *\r
5  */\r
6 Fifo::Fifo(char* name, unsigned size = 18) {\r
7     //std::cout << "Create Fifo." << std::endl;\r
8     //except at the beginning, _head and _tail must never overlap,\r
9     //otherwise one does not know whether the buffer is full or\r
10     //empty. to have nevertheless a buffer with the given capacity,\r
11     //a buffer with one more element is allocated.\r
12     _size = size + 1;\r
13     _buffer = new char[_size];\r
14     _head = 0;\r
15     _tail = 0;\r
16     _name = new char[strlen(name) + 1];\r
17     strcpy(_name, name);\r
18     _mutex = new Mutex();\r
19     _readCondition = new Condition(_mutex);\r
20     _writeCondition = new Condition(_mutex);\r
21 }\r
22 \r
23 /**\r
24  *\r
25  */\r
26 Fifo::~Fifo() {\r
27     //std::cout << "Delete Fifo." << std::endl;\r
28     if (_buffer) {\r
29         delete _buffer;\r
30     }\r
31     if (_name) {\r
32         delete _name;\r
33     }\r
34     if (_readCondition) {\r
35         delete _readCondition;\r
36     }\r
37     if (_writeCondition) {\r
38         delete _writeCondition;\r
39     }\r
40     if (_mutex) {\r
41         delete _mutex;\r
42     }\r
43 \r
44     _buffer = 0;\r
45     _head = 0;\r
46     _tail = 0;\r
47     _name = 0;\r
48     _readCondition = 0;\r
49     _writeCondition = 0;\r
50     _mutex = 0;\r
51     //std::cout << "Deleted Fifo." << std::endl;\r
52 }\r
53 \r
54 /**\r
55  *\r
56  */\r
57 unsigned Fifo::read(void *destination, unsigned len) {\r
58     char* buffer = (char*)destination;\r
59     unsigned read = 0;\r
60     //std::cout << "Try to read " << len << " bytes from Fifo " << _name << "." << std::endl;\r
61 \r
62     while (read < len) {\r
63         _mutex->lock();\r
64         while (used() == 0) {\r
65             _writeCondition->wait();\r
66         }\r
67         _mutex->unlock();\r
68 \r
69         if ((len - read) < used()) {\r
70             while (read < len) {\r
71                 _mutex->lock();\r
72                 unsigned tocopy = (len - read + _tail >= _size) ? _size - _tail : len - read;\r
73                 memcpy(buffer, _buffer + _tail, tocopy);\r
74                 _tail = (_tail + tocopy) % _size;\r
75                 read += tocopy;\r
76                 buffer += tocopy;\r
77                 _mutex->unlock();\r
78             }\r
79             _readCondition->notify();\r
80         } else {\r
81             _mutex->lock();\r
82             *buffer++ = *(_buffer + _tail % _size);\r
83             _tail = (_tail + 1) % _size;\r
84             read++;\r
85             _mutex->unlock();\r
86             _readCondition->notify();\r
87         }\r
88     }\r
89 \r
90     //std::cout << "Read " << read << " bytes from Fifo " << _name << "." << std::endl;\r
91     return read;\r
92 }\r
93 \r
94 /**\r
95  *\r
96  */\r
97 unsigned Fifo::write(const void *source, unsigned len) {\r
98     char* buffer = (char*)source;\r
99     unsigned write = 0;\r
100     //std::cout << "Try to write " << len << " bytes to Fifo " << _name << std::endl;\r
101 \r
102     while (write < len) {\r
103         _mutex->lock();\r
104         while (unused() == 0) {\r
105             _readCondition->wait();\r
106         }\r
107         _mutex->unlock();\r
108 \r
109         if ((len - write) < unused()) {\r
110             while (write < len) {\r
111                 unsigned tocopy = (len - write + _head >= _size) ? _size - _head : len - write;\r
112                 _mutex->lock();\r
113                 memcpy(_buffer + _head, buffer, tocopy);\r
114                 _head = (_head + tocopy) % _size;\r
115                 write += tocopy;\r
116                 buffer += tocopy;\r
117                 _mutex->unlock();\r
118             }\r
119             _writeCondition->notify();\r
120         } else {\r
121             _mutex->lock();\r
122             *(_buffer + (unsigned)(_head) % _size) = *buffer++;\r
123             _head = (_head + 1) % _size;\r
124             write++;\r
125             _mutex->unlock();\r
126             _writeCondition->notify();\r
127         }\r
128     }\r
129     //std::cout << "Wrote " << write << " bytes to Fifo " << _name << "." << std::endl;\r
130     return write;\r
131 }\r
132 \r
133 /**\r
134  *\r
135  */\r
136 unsigned Fifo::size() const {\r
137     return (_size - 1);\r
138 }\r
139 \r
140 /**\r
141  *\r
142  */\r
143 unsigned Fifo::unused() const {\r
144     return (_size - 1) - used();\r
145 }\r
146 \r
147 /**\r
148  *\r
149  */\r
150 unsigned Fifo::used() const {\r
151     if (_head >= _tail) {\r
152         return _head - _tail;\r
153     }\r
154     return _head + _size - _tail;\r
155 }\r
156 \r
157 /**\r
158  *\r
159  */\r
160 char* Fifo::getName() const {\r
161     return _name;\r
162 }\r
163 \r
164 /**\r
165  * Test the implementation\r
166  */\r
167 /*\r
168 #include <iostream>\r
169 void* producer(void *fifo)\r
170 {\r
171     const char *str =\r
172         "Visit www.systemc.org and see what SystemC can do for you today!\n";\r
173 \r
174     while (*str) {\r
175         //printf("%c", *str);\r
176         ((Fifo*)fifo)->write((void*)str++, 4);\r
177     }\r
178     printf("\nproducer returns.\n");\r
179     return 0;\r
180 }\r
181 \r
182 void* consumer(void *fifo)\r
183 {\r
184     char c;\r
185     while (c != '\n') {\r
186         ((Fifo*)fifo)->read(&c, 4);\r
187         std::cout << c << std::flush;\r
188 \r
189         if (((Fifo*)fifo)->used() == 1)\r
190             std::cout << "<1>" << std::flush;\r
191         if (((Fifo*)fifo)->used() == 9)\r
192             std::cout << "<9>" << std::flush;\r
193     }\r
194     printf("\nconsumer returns.\n");\r
195     return 0;\r
196 }\r
197 \r
198 \r
199 int main() {\r
200     Fifo *fifo = new Fifo("fifo", 3);\r
201     pthread_t *producer_thread = new pthread_t;\r
202     pthread_t *consumer_thread = new pthread_t;\r
203 \r
204     pthread_attr_t attributes;\r
205     pthread_attr_init(&attributes);\r
206     pthread_attr_setstacksize(&attributes, 131072);\r
207 \r
208     if (pthread_create(consumer_thread, &attributes, consumer, fifo)) {\r
209         std::cout << "Error: Could not start consumer." << std::endl;\r
210         std::cout << "Exit." << std::endl;\r
211         exit(1);\r
212     }\r
213     pthread_attr_destroy(&attributes);\r
214 \r
215     pthread_attr_init(&attributes);\r
216     pthread_attr_setstacksize(&attributes, 131072);\r
217     if (pthread_create(producer_thread, &attributes, producer, fifo)) {\r
218         std::cout << "Error: Could not start producer." << std::endl;\r
219         std::cout << "Exit." << std::endl;\r
220         exit(1);\r
221     }\r
222     pthread_attr_destroy(&attributes);\r
223 \r
224 \r
225     pthread_join(*consumer_thread, 0);\r
226     delete fifo;\r
227     return 0;\r
228 }\r
229 */\r