00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00036 #ifdef HAVE_UNISTD_H
00037 #include <unistd.h>
00038 #endif
00039 #ifdef HAVE_TIME_H
00040 #include <time.h>
00041 #endif
00042
00043 #include <iostream>
00044
00045
00046 #include <algorithm>
00047 #include <functional>
00048
00049 #include "casobject.h"
00050 #include "casgarbage.h"
00051
00063 extern "C" void*
00064 CASGarbage_thread_wrapper ( void *object ) {
00065 CASGarbage *ptr = ( CASGarbage* ) object;
00066 return ptr->Trasher();
00067 }
00068
00069
00070
00071
00082 void
00083 CASGarbage::CreateTrasherThread() {
00084
00085 if ( trasher_thread_created == true ) {
00086 return;
00087 }
00088
00089
00090 int retval = pthread_attr_init ( &pattr );
00091 CheckRetVal ( retval, std::string ( "pthread_attr_init()" ) );
00092
00093 retval = pthread_create ( &tid, &pattr, CASGarbage_thread_wrapper, this );
00094 CheckRetVal ( retval, std::string ( "pthread_create()" ) );
00095
00096
00097 trasher_thread_created = true;
00098 }
00099
00106 void
00107 CASGarbage::TerminateTrasherThread() {
00108
00109 if ( trasher_thread_created == false ) {
00110 return;
00111 }
00112
00113
00114 time_to_die = true;
00115
00116
00117 int retval = pthread_cond_broadcast ( &cond_var );
00118 CheckRetVal ( retval, std::string ( "pthread_cond_broadcast()" ) );
00119
00120
00121 retval = pthread_join ( tid, NULL );
00122 CheckRetVal ( retval, std::string ( "pthread_join()" ) );
00123
00124
00125 retval = pthread_attr_destroy ( &pattr );
00126 CheckRetVal ( retval, std::string ( "pthread_attr_destroy()" ) );
00127
00128
00129 trasher_thread_created = false;
00130
00131 }
00132
00139 void
00140 CASGarbage::RemoveDuplicate() {
00141 if ( list.size() == 0 ) {
00142 return;
00143 }
00144
00145 std::sort ( list.begin(), list.end(), CASGarbageSort_Cmp() );
00146
00147 std::vector<CASObject*>::iterator ip =
00148 std::unique ( list.begin(), list.end() );
00149
00150 list.erase ( ip, list.end() );
00151 }
00152
00167 void
00168 CASGarbage::CheckRetVal ( int rv, std::string fname ) {
00169 switch ( rv ) {
00170 case 0:
00171 break;
00172 case ENOMEM:
00173
00174 throw ECASGarbageThread_ENOMEM ( fname );
00175 case EAGAIN:
00176 throw ECASGarbageThread_EAGAIN ( fname );
00177 case EINVAL:
00178 throw ECASGarbageThread_EINVAL ( fname );
00179 case ESRCH:
00180 throw ECASGarbageThread_ESRCH ( fname, tid );
00181 case EDEADLK:
00182 throw ECASGarbageThread_EDEADLK ( fname );
00183 default:
00184 throw ECASGarbageThread_UNKNOWN ( fname );
00185 }
00186 }
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00202 CASGarbage::CASGarbage() : min_casobjects ( 200 ),
00203 time_to_die ( false ),
00204 trasher_thread_created ( false ) {
00205 #ifdef SHOWCONSTRUCTOR
00206 std::cerr << "# CASGarbage::CASGarbage()" << std::endl;
00207 #endif
00208
00209 int retval = pthread_mutexattr_init ( &mutex_attr );
00210 CheckRetVal ( retval, std::string ( "pthread_mutexattr_init()" ) );
00211
00212
00213 retval = pthread_mutexattr_setpshared ( &mutex_attr, PTHREAD_PROCESS_PRIVATE );
00214 CheckRetVal ( retval, std::string ( "pthread_mutexattr_setpshared()" ) );
00215
00216
00217 retval = pthread_mutexattr_settype ( &mutex_attr, PTHREAD_MUTEX_ERRORCHECK );
00218 CheckRetVal ( retval, std::string ( "pthread_mutexattr_settype()" ) );
00219
00220
00221 retval = pthread_mutex_init ( &mutex, &mutex_attr );
00222 CheckRetVal ( retval, std::string ( "pthread_mutex_init()" ) );
00223
00224
00225 retval = pthread_cond_init ( &cond_var, NULL );
00226 CheckRetVal ( retval, std::string ( "pthread_cond_init()" ) );
00227 }
00228
00233 CASGarbage::~CASGarbage() {
00234 #ifdef SHOWCONSTRUCTOR
00235 std::cerr << "# CASGarbage::~CASGarbage()" << std::endl;
00236 #endif
00237
00238 TerminateTrasherThread();
00239
00240
00241
00242
00243 RemoveDuplicate();
00244 std::for_each ( list.begin(),
00245 list.end(),
00246 CASDestroyObject() );
00247
00248
00249 int retval = pthread_mutex_destroy ( &mutex );
00250 CheckRetVal ( retval, std::string ( "phtread_mutex_destroy()" ) );
00251
00252
00253 retval = pthread_mutexattr_destroy ( &mutex_attr );
00254 CheckRetVal ( retval, std::string ( "pthread_mutexattr_destroy()" ) );
00255
00256
00257 retval = pthread_cond_destroy ( &cond_var );
00258 CheckRetVal ( retval, std::string ( "pthread_cond_destroy()" ) );
00259
00260 }
00261
00267 CASGarbage::CASGarbage ( const CASGarbage &wdc ) : min_casobjects ( 0 ) {
00268 throw EDoesNotApply();
00269 }
00270
00271
00272
00273
00274
00275
00289 void*
00290 CASGarbage::Trasher() {
00291 int retval = pthread_mutex_lock ( &mutex );
00292 CheckRetVal ( retval, std::string ( "pthread_mutex_lock()" ) );
00293
00294 while ( time_to_die != true ) {
00295 if ( list.size() > min_casobjects ) {
00296 RemoveDuplicate();
00297
00298 std::for_each ( list.begin(),
00299 list.end(),
00300 CASDestroyObject() );
00301 list.clear();
00302 }
00303
00304 retval = pthread_cond_wait ( &cond_var, &mutex );
00305 CheckRetVal ( retval, std::string ( "pthread_cond_wait()" ) );
00306 }
00307
00308 retval = pthread_mutex_unlock ( &mutex );
00309 CheckRetVal ( retval, std::string ( "pthread_mutex_unlock()" ) );
00310
00311 pthread_exit ( 0 );
00312 return NULL;
00313 }
00314
00324 void
00325 CASGarbage::Put ( CASObject *o ) {
00326 checkptr ( o );
00327
00328 CreateTrasherThread();
00329
00330
00331 int retval = pthread_mutex_lock ( &mutex );
00332 CheckRetVal ( retval, std::string ( "pthread_mutex_lock()" ) );
00333
00334 list.push_back ( o );
00335
00336 retval = pthread_mutex_unlock ( &mutex );
00337 CheckRetVal ( retval, std::string ( "pthread_mutex_lock()" ) );
00338
00339 retval = pthread_cond_broadcast ( &cond_var );
00340 CheckRetVal ( retval, std::string ( "pthread_cond_broadcast()" ) );
00341 }
00342
00353 void
00354 CASGarbage::Put ( const std::vector<CASObject*> &v ) {
00355
00356 CreateTrasherThread();
00357
00358
00359 int retval = pthread_mutex_lock ( &mutex );
00360 CheckRetVal ( retval, std::string ( "pthread_mutex_lock()" ) );
00361
00362 std::vector<CASObject*>::const_iterator it = v.begin();
00363 while ( it != v.end() ) {
00364 list.push_back ( *it );
00365 it++;
00366 }
00367
00368 retval = pthread_mutex_unlock ( &mutex );
00369 CheckRetVal ( retval, std::string ( "pthread_mutex_lock()" ) );
00370
00371 retval = pthread_cond_broadcast ( &cond_var );
00372 CheckRetVal ( retval, std::string ( "pthread_cond_broadcast()" ) );
00373 }
00374
00385 void
00386 CASGarbage::Put ( const std::list<CASObject*> &l ) {
00387
00388 CreateTrasherThread();
00389
00390
00391 int retval = pthread_mutex_lock ( &mutex );
00392 CheckRetVal ( retval, std::string ( "pthread_mutex_lock()" ) );
00393
00394 std::list<CASObject*>::const_iterator it = l.begin();
00395 while ( it != l.end() ) {
00396 list.push_back ( *it );
00397 it++;
00398 }
00399
00400 retval = pthread_mutex_unlock ( &mutex );
00401 CheckRetVal ( retval, std::string ( "pthread_mutex_lock()" ) );
00402
00403 retval = pthread_cond_broadcast ( &cond_var );
00404 CheckRetVal ( retval, std::string ( "pthread_cond_broadcast()" ) );
00405 }
00406
00407
00408
00409
00410
00420 CASGarbage &
00421 CASGarbage::operator= ( const CASGarbage &wdc ) {
00422 throw EDoesNotApply();
00423 }
00424
00425