|
Fast Research Interface Library
Manual and Documentation
|
00001 // ---------------------- Doxygen info ---------------------- 00051 // ---------------------------------------------------------- 00052 // For a convenient reading of this file's source code, 00053 // please use a tab width of four characters. 00054 // ---------------------------------------------------------- 00055 00056 00057 #include <Console.h> 00058 #include <stdio.h> 00059 #include <stdarg.h> 00060 #include <string.h> 00061 #include <pthread.h> 00062 #include <OSAbstraction.h> 00063 00064 00065 #ifdef WIN32// \ToDo Make this clean through the OSAbstraction 00066 #include <Windows.h> 00067 #endif 00068 00069 00070 00071 // **************************************************************** 00072 // Constructor 00073 // 00074 Console::Console( const unsigned int &Priority 00075 , const FILE *FileHandler) 00076 { 00077 struct sched_param ThreadSchedulingParams; 00078 00079 pthread_attr_t ThreadAttributes; 00080 00081 TermintateThread = false; 00082 ThreadCreated = false; 00083 ConsoleThreadReadyToRun = false; 00084 00085 pthread_mutex_init (&(this->Mutex) , NULL); 00086 pthread_cond_init (&(this->CondVar) , NULL); 00087 00088 ThreadSchedulingParams.sched_priority = Priority; 00089 00090 pthread_attr_init (&ThreadAttributes ) ; 00091 pthread_attr_setschedpolicy (&ThreadAttributes , SCHED_FIFO ) ; 00092 pthread_attr_setinheritsched(&ThreadAttributes , PTHREAD_EXPLICIT_SCHED ) ; 00093 pthread_attr_setschedparam (&ThreadAttributes , &ThreadSchedulingParams ) ; 00094 00095 pthread_create( &ConsoleThread 00096 , &ThreadAttributes 00097 , &ConsoleThreadMain 00098 , this); 00099 00100 pthread_mutex_lock(&(this->Mutex)); 00101 00102 while (!ThreadCreated) 00103 { 00104 pthread_cond_wait (&(this->CondVar), &(this->Mutex)); 00105 } 00106 00107 pthread_mutex_unlock(&(this->Mutex)); 00108 00109 memset(this->Buffer, 0x0, 2 00110 * CONSOLE_NUMBER_OF_BUFFER_ENTRIES 00111 * CONSOLE_BUFFER_ENTRY_SIZE 00112 * sizeof(char)); 00113 00114 00115 00116 this->BufferNumber = false; 00117 00118 this->NumberOfMessages[0] = 0; 00119 this->NumberOfMessages[1] = 0; 00120 00121 00122 this->Handler = (FILE*)FileHandler; 00123 00124 pthread_mutex_lock(&(this->Mutex)); 00125 this->ConsoleThreadReadyToRun = true; 00126 pthread_mutex_unlock(&(this->Mutex)); 00127 00128 pthread_cond_signal(&(this->CondVar)); 00129 } 00130 00131 00132 // **************************************************************** 00133 // Destructor 00134 // 00135 Console::~Console(void) 00136 { 00137 pthread_mutex_lock(&(this->Mutex)); 00138 this->TermintateThread = true; 00139 pthread_mutex_unlock(&(this->Mutex)); 00140 pthread_cond_signal(&(this->CondVar)); 00141 pthread_join(this->ConsoleThread, NULL); 00142 } 00143 00144 00145 // **************************************************************** 00146 // printf() 00147 // 00148 int Console::printf(const char* Format,...) 00149 { 00150 int Result; 00151 00152 va_list ListOfArguments; 00153 00154 va_start(ListOfArguments, Format); 00155 00156 00157 pthread_mutex_lock(&(this->Mutex)); 00158 if (this->NumberOfMessages[this->BufferNumber] >= CONSOLE_NUMBER_OF_BUFFER_ENTRIES) 00159 { 00160 sprintf(this->Buffer[this->BufferNumber][this->NumberOfMessages[this->BufferNumber] - 1], "Console::printf(): Buffer is full, skipping output!\n"); 00161 Result = strlen(this->Buffer[this->BufferNumber][this->NumberOfMessages[this->BufferNumber] - 1]); 00162 pthread_mutex_unlock(&(this->Mutex)); 00163 return(Result); 00164 } 00165 00166 (this->NumberOfMessages[this->BufferNumber])++; 00167 Result = vsnprintf(this->Buffer[this->BufferNumber][NumberOfMessages[this->BufferNumber] - 1], CONSOLE_BUFFER_ENTRY_SIZE - 1, Format, ListOfArguments); 00168 pthread_mutex_unlock(&(this->Mutex)); 00169 pthread_cond_signal(&(this->CondVar)); 00170 00171 va_end(ListOfArguments); 00172 return(Result); 00173 } 00174 00175 00176 00177 00178 00179 // **************************************************************** 00180 // ConsoleThreadMain() 00181 // 00182 00183 void* Console::ConsoleThreadMain(void* ObjectPointer) 00184 { 00185 unsigned int i = 0; 00186 00187 Console* ThisObjectPtr = (Console*)ObjectPointer; 00188 00189 #ifdef WIN32 00190 // \ToDo Make this clean through the OSAbstraction 00191 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_LOWEST); 00192 #endif 00193 00194 pthread_mutex_lock(&(ThisObjectPtr->Mutex)); 00195 ThisObjectPtr->ThreadCreated = true; 00196 pthread_mutex_unlock(&(ThisObjectPtr->Mutex)); 00197 00198 pthread_cond_signal(&(ThisObjectPtr->CondVar)); 00199 00200 pthread_mutex_lock(&(ThisObjectPtr->Mutex)); 00201 00202 while (!ThisObjectPtr->ConsoleThreadReadyToRun) 00203 { 00204 pthread_cond_wait (&(ThisObjectPtr->CondVar), &(ThisObjectPtr->Mutex)); 00205 } 00206 00207 pthread_mutex_unlock(&(ThisObjectPtr->Mutex)); 00208 00209 for(;;) 00210 { 00211 pthread_mutex_lock(&(ThisObjectPtr->Mutex)); 00212 if (ThisObjectPtr->NumberOfMessages[!(ThisObjectPtr->BufferNumber)] == 0) 00213 { 00214 if (ThisObjectPtr->TermintateThread) 00215 { 00216 pthread_mutex_unlock(&(ThisObjectPtr->Mutex)); 00217 break; 00218 } 00219 pthread_cond_wait (&(ThisObjectPtr->CondVar), &(ThisObjectPtr->Mutex)); 00220 00221 // keep the maximum amount of CPU time for this thread at a minimum while the mutex is locked 00222 ThisObjectPtr->BufferNumber = !ThisObjectPtr->BufferNumber; 00223 00224 pthread_mutex_unlock(&(ThisObjectPtr->Mutex)); 00225 } 00226 else 00227 { 00228 pthread_mutex_unlock(&(ThisObjectPtr->Mutex)); 00229 } 00230 00231 for(i = 0; i < ThisObjectPtr->NumberOfMessages[!(ThisObjectPtr->BufferNumber)]; i++) 00232 { 00233 fprintf(ThisObjectPtr->Handler, "%s", ThisObjectPtr->Buffer[!(ThisObjectPtr->BufferNumber)][i]); 00234 } 00235 00236 ThisObjectPtr->flush(); 00237 ThisObjectPtr->NumberOfMessages[!(ThisObjectPtr->BufferNumber)] = 0; 00238 } 00239 00240 for(i = 0; i < ThisObjectPtr->NumberOfMessages[ThisObjectPtr->BufferNumber]; i++) 00241 { 00242 fprintf(ThisObjectPtr->Handler, "%s", ThisObjectPtr->Buffer[ThisObjectPtr->BufferNumber][i]); 00243 } 00244 00245 ThisObjectPtr->flush(); 00246 00247 pthread_exit(NULL); 00248 00249 return (NULL); 00250 } 00251 00252 00253 00254 // **************************************************************** 00255 // flush() 00256 // 00257 void Console::flush(void) const 00258 { 00259 fflush(this->Handler); 00260 return; 00261 } 00262 00263 00264 // **************************************************************** 00265 // GetFileHandler() 00266 // 00267 FILE* Console::GetFileHandler(void) const 00268 { 00269 return(this->Handler); 00270 }