00001 /***************************** License ********************************** 00002 00003 Copyright (C) 2008 by Communicative Machines 00004 http://www.cmlabs.com All rights reserved. 00005 00006 This library is free software; you can redistribute it and/or 00007 modify it under the terms of the GNU Lesser General Public 00008 License as published by the Free Software Foundation; either 00009 version 2.1 of the License, or (at your option) any later version. 00010 00011 This library is distributed in the hope that it will be useful, 00012 but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 Lesser General Public License for more details. 00015 00016 You should have received a copy of the GNU Lesser General Public 00017 License along with this library; if not, write to the Free Software 00018 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00019 00020 ************************************************************************/ 00021 #include "BinaryBuffer.h" 00022 00023 namespace cmlabs { 00024 00025 // BinaryBuffer.cpp: implementation of the BinaryBuffer class. 00026 // 00027 ////////////////////////////////////////////////////////////////////// 00028 00029 00030 ////////////////////////////////////////////////////////////////////// 00031 // Construction/Destruction 00032 ////////////////////////////////////////////////////////////////////// 00033 00034 BinaryBuffer::BinaryBuffer(long size) { 00035 first = last = current = NULL; 00036 count = 0; 00037 buffersize = size; 00038 inUseTable = new ObjectCollection(); 00039 } 00040 00041 BinaryBuffer::~BinaryBuffer() { 00042 deleteAll(); 00043 delete(inUseTable); 00044 } 00045 00046 00047 00048 00049 bool BinaryBuffer::addEntry(JTime stamp, JString source, JString datatype, Object* obj) { 00050 00051 BinaryBufferEntry* entry; 00052 00053 if (count <= buffersize) { 00054 entry = new BinaryBufferEntry; 00055 00056 entry->prev = current; 00057 if (current != NULL) 00058 current->next = entry; 00059 last = entry; 00060 if (count == buffersize) { 00061 entry->next = first; 00062 first->prev = entry; 00063 } 00064 else 00065 entry->next = NULL; 00066 00067 if (first == NULL) 00068 first = last = entry; 00069 00070 } 00071 else { 00072 checkInUseTable(); 00073 00074 entry = (BinaryBufferEntry*) current->next; 00075 // If entry is in use 00076 if (entry->inUseBy.getCount() > 0) { 00077 // save entry in inUseTable 00078 inUseTable->add(entry); 00079 // create new entry 00080 BinaryBufferEntry* newentry = new BinaryBufferEntry; 00081 // and put it into structure 00082 newentry->next = entry->next; 00083 newentry->prev = entry->prev; 00084 // now we can let go of entry 00085 entry = (BinaryBufferEntry*) newentry->prev; 00086 entry->next = newentry; 00087 entry = (BinaryBufferEntry*) newentry->next; 00088 entry->prev = newentry; 00089 // and let go of newentry 00090 entry = newentry; 00091 } 00092 else { 00093 if (entry->object != NULL) 00094 delete(entry->object); 00095 } 00096 } 00097 00098 entry->count = count; 00099 entry->timestamp = stamp; 00100 entry->source = source; 00101 entry->datatype = datatype; 00102 entry->object = obj; 00103 entry->inUseBy.removeAll(); 00104 00105 current = entry; 00106 00107 count++; 00108 00109 return true; 00110 } 00111 00112 00113 BinaryBufferEntry* BinaryBuffer::getLastEntry() { 00114 BinaryBufferEntry* entry; 00115 if (mutex.EnterMutex(1000)) { 00116 entry = current; 00117 mutex.LeaveMutex(); 00118 return entry; 00119 } 00120 else 00121 return NULL; 00122 } 00123 00124 BinaryBufferEntry* BinaryBuffer::waitForNextEntryAfter(JTime t, long ms) { 00125 00126 JTime start; 00127 BinaryBufferEntry* entry = getNextEntryAfter(t); 00128 00129 if (entry != NULL) 00130 return entry; 00131 00132 // We are not ready, wait for the next one 00133 00134 // Tag the current one 00135 entry = current; 00136 00137 // and look for when it changes... 00138 while (entry == current) { 00139 if (JTime() - start > ms) break; 00140 wait(20); 00141 } 00142 00143 // Either we timed out or there is new data 00144 return getNextEntryAfter(t); 00145 } 00146 00147 BinaryBufferEntry* BinaryBuffer::getNextEntryAfter(JTime t) { 00148 00149 BinaryBufferEntry* entry = NULL; 00150 00151 if (first == NULL) 00152 return NULL; 00153 00154 if (current->timestamp > t) { 00155 // We have one newer than t, find it 00156 entry = (BinaryBufferEntry*) current->prev; 00157 while ((entry != NULL) && (entry->timestamp > t)) { 00158 entry = (BinaryBufferEntry*) entry->prev; 00159 } 00160 00161 // Now entry is either NULL (none found, return first) 00162 if (entry == NULL) return first; 00163 00164 // or entry is the one just before t and we want the next 00165 entry = (BinaryBufferEntry*) entry->next; 00166 } 00167 return entry; 00168 } 00169 00170 00171 bool BinaryBuffer::reset() { 00172 deleteAll(); 00173 first = last = current = NULL; 00174 count = 0; 00175 return true; 00176 } 00177 00178 bool BinaryBuffer::deleteAll() { 00179 if (first == NULL) 00180 return true; 00181 00182 if ((last == NULL) || (current == NULL)) 00183 return false; 00184 00185 BinaryBufferEntry* entry = first; 00186 while (first != NULL) { 00187 entry = (BinaryBufferEntry*) first->next; 00188 delete(first); 00189 // if we just deleted the last one... 00190 if (first == last) 00191 break; 00192 // else continue deleting... 00193 first = entry; 00194 } 00195 00196 return true; 00197 } 00198 00199 00200 00201 00202 00203 // ********************************************************* 00204 // Printing 00205 // ********************************************************* 00206 00207 JString BinaryBuffer::print() { 00208 return printLast(); 00209 } 00210 00211 JString BinaryBuffer::printLast() { 00212 return print(current); 00213 } 00214 00215 JString BinaryBuffer::print(BinaryBufferEntry* entry) { 00216 if (entry == NULL) return "No entries in buffer..."; 00217 00218 JString str; 00219 if (mutex.EnterMutex(1000)) { 00220 str += JString(current->count) + ": "; 00221 str += current->timestamp.printTime() + " "; 00222 str += current->source + " "; 00223 str += current->datatype; 00224 mutex.LeaveMutex(); 00225 return str; 00226 } 00227 else 00228 return ""; 00229 } 00230 00231 00232 // ********************************************************* 00233 // Housekeeping 00234 // ********************************************************* 00235 00236 bool BinaryBuffer::checkInUseTable() { 00237 00238 BinaryBufferEntry* entry; 00239 00240 int c = inUseTable->getCount(); 00241 00242 if (c == 0) return true; 00243 00244 for (int n=0; n<c; n++) { 00245 entry = (BinaryBufferEntry*) inUseTable->get(n); 00246 if (entry != NULL) { 00247 if (entry->inUseBy.getCount() == 0) { 00248 // delete(entry); 00249 inUseTable->remove(n); 00250 n--; 00251 } 00252 } 00253 } 00254 00255 return true; 00256 } 00257 00258 00259 00260 00261 00262 } // namespace cmlabs