source: Sophya/trunk/ArchTOIPipe/Kernel/toisegment.cc@ 1686

Last change on this file since 1686 was 1686, checked in by aubourg, 24 years ago

* empty log message *

File size: 5.3 KB
Line 
1#include "toisegment.h"
2
3/*******************************/
4/******* BufferSegment *********/
5/*******************************/
6
7TOISegmented::BufferSegment::BufferSegment(int sz) {
8 status = NEW;
9 bufferSize = sz;
10 sn0 = -1;
11
12 refcount = 0;
13
14 data = new double[sz];
15 flags = new uint_8[sz];
16
17 pthread_mutex_init(&refcount_mutex, NULL);
18}
19
20TOISegmented::BufferSegment::~BufferSegment() {
21 if (refcount > 0) {
22 throw(ForbiddenError("TOISegment : delete Buffer with refcount>0"));
23 }
24 delete[] data;
25 delete[] flags;
26 pthread_mutex_destroy(&refcount_mutex);
27}
28
29void TOISegmented::BufferSegment::putData(int sn, double d, uint_8 f) {
30 if (status == NEW) {
31 status = WRITE;
32 sn0 = sn;
33 }
34 if (status == COMMITTED) {
35 throw(ForbiddenError("TOISegment : putData in committed buffer"));
36 }
37 checkInRange(sn);
38 data[sn-sn0] = d;
39 flags[sn-sn0] = f;
40}
41
42void TOISegmented::BufferSegment::incRefCount() {
43 pthread_mutex_lock(&refcount_mutex);
44 refcount++;
45 pthread_mutex_unlock(&refcount_mutex);
46}
47
48void TOISegmented::BufferSegment::decRefCount() {
49 pthread_mutex_lock(&refcount_mutex);
50 int nrc = --refcount;
51 pthread_mutex_unlock(&refcount_mutex);
52 if (nrc<0)
53 throw(ForbiddenError("TOISegment : buffer refcount < 0"));
54}
55
56int TOISegmented::BufferSegment::getRefCount() {
57 pthread_mutex_lock(&refcount_mutex);
58 int rc = refcount;
59 pthread_mutex_unlock(&refcount_mutex);
60 return rc;
61}
62
63
64/*******************************/
65/********** BufferView *********/
66/*******************************/
67
68TOISegmented::BufferView::BufferView(MasterView* m) {
69 master = m;
70 sn0 = -1;
71 segmentSize = m->segmentSize;
72 pthread_mutex_init(&mutex, NULL);
73 pthread_cond_init(&condv, NULL);
74}
75
76TOISegmented::BufferView::~BufferView() {
77 pthread_mutex_destroy(&mutex);
78 pthread_cond_destroy(&condv);
79}
80
81double TOISegmented::BufferView::getData(int sn) { /* Single-thread */
82 ensure(sn);
83 int seg = (sn-sn0)/segmentSize;
84 return segments[seg]->getData(sn);
85}
86
87uint_8 TOISegmented::BufferView::getFlag(int sn) { /* Single-thread */
88 ensure(sn);
89 int seg = (sn-sn0)/segmentSize;
90 return segments[seg]->getFlag(sn);
91}
92
93void TOISegmented::BufferView::ensure(int sn) { /* Single-thread */
94 if (sn < sn0) {
95 throw RangeCheckError("requested sample before first");
96 }
97
98 if (sn >= sn0 + segmentSize*segments.size()) {
99 cout << "BufferView : read fault for " << sn << endl;
100 sync();
101 while (sn >= sn0 + segmentSize*segments.size()) {
102 wait();
103 cout << "BufferView : waiting for " << sn << endl;
104 sync();
105 }
106 cout << "BufferView : resuming for " << sn << endl;
107 }
108}
109
110void TOISegmented::BufferView::sync() { /* Single-thread */
111 master->updateView(this); // update me !
112}
113
114void TOISegmented::BufferView::wait() { /* From reader thread */
115 pthread_mutex_lock(&mutex);
116 master->addToWaitList(this); // needing wake-up call
117 pthread_cond_wait(&condv, &mutex);
118 pthread_mutex_unlock(&mutex);
119}
120
121void TOISegmented::BufferView::signal() { /* From masterview, writer thread */
122 pthread_mutex_lock(&mutex);
123 pthread_cond_signal(&condv); // only one thread can be sleeping
124 master->removeFromWaitList(this);
125 pthread_mutex_unlock(&mutex);
126}
127
128
129/*******************************/
130/********** MasterView *********/
131/*******************************/
132
133TOISegmented::MasterView::MasterView(int bufsz, int maxseg) {
134 currentSegment = NULL;
135 maxSegments = maxseg;
136 segmentSize = bufsz;
137 sn0 = -1;
138
139 pthread_mutex_init(&views_mutex, NULL);
140 pthread_mutex_init(&write_mutex, NULL);
141 pthread_cond_init(&condv, NULL);
142 pthread_key_create(&buffer_key, BufferDestroy);
143
144 waitStatus = NO_WAIT;
145}
146
147TOISegmented::MasterView::~MasterView() {
148 pthread_mutex_destroy(&views_mutex);
149 pthread_mutex_destroy(&write_mutex);
150 pthread_cond_destroy(&condv);
151 pthread_key_delete(buffer_key);
152
153 // There should not be any BufferView left... Check ?
154
155 // decrement count for segments ?
156}
157
158void TOISegmented::MasterView::putData(int sn, double data, uint_8 flags) {
159 // can fit in current segment ?
160 if (!(currentSegment != NULL &&
161 sn >= currentSegment->sn0 &&
162 sn < currentSegment->sn0 + currentSegment->bufferSize)) {
163 nextSegment();
164 }
165 currentSegment->putData(sn, data, flags);
166}
167
168double TOISegmented::MasterView::getData(int sn) {
169 return getView()->getData(sn);
170}
171
172uint_8 TOISegmented::MasterView::getFlag(int sn) {
173 return getView()->getFlag(sn);
174}
175
176void TOISegmented::MasterView::addToWaitList(BufferView* bv) { /* reader thread */
177 // A view needs to wait for new data.
178
179 // There is a possible deadlock if no view can free old segments
180 // and we are waiting for write.
181
182 // we need to record "wont need before" for each view, and
183 // signal deadlock if any view that needs first segment data is sleeping
184 // while we are asleep
185
186 pthread_mutex_lock(&views_mutex);
187 waitingBuffers.insert(bv);
188 pthread_mutex_unlock(&views_mutex);
189 checkDeadLock();
190}
191
192void TOISegmented::MasterView::removeFromWaitList(BufferView* bv) { /* reader thread */
193 pthread_mutex_lock(&views_mutex);
194 waitingBuffers.erase(bv);
195 pthread_mutex_unlock(&views_mutex);
196}
197
198TOISegmented::BufferView* TOISegmented::MasterView::getView() { /* reader thread */
199 BufferView* bv = (BufferView*) pthread_getspecific(buffer_key);
200 if (bv == NULL) {
201 bv = createView();
202 pthread_setspecific(buffer_key, bv);
203 }
204 return bv;
205}
Note: See TracBrowser for help on using the repository browser.