casgarbage.cc

Go to the documentation of this file.
00001 //
00002 //  Copyright (c) 2006 by Rafael Ostertag
00003 //
00004 //  This program is free software; you can redistribute it and/or modify
00005 //  it under the terms of the GNU General Public License as published by
00006 //  the Free Software Foundation; either version 2 of the License, or
00007 //  (at your option) any later version.
00008 //
00009 //  This program is distributed in the hope that it will be useful,
00010 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 //  GNU General Public License for more details.
00013 //
00014 //  You should have received a copy of the GNU General Public License
00015 //  along with this program; if not, write to the Free Software
00016 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00017 //
00018 //
00019 // $Id: casgarbage.cc,v 1.11 2006/12/31 00:48:15 rafi Exp $
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 // Private methods
00070 // ----------------------------------------------------------------------------
00071 
00082 void
00083 CASGarbage::CreateTrasherThread() {
00084     // Make sure the thread has not been created already.
00085     if ( trasher_thread_created == true ) {
00086         return;
00087     }
00088 
00089     // Initialize the thread attribute
00090     int retval = pthread_attr_init ( &pattr );
00091     CheckRetVal ( retval, std::string ( "pthread_attr_init()" ) );
00092     // Creates the thread
00093     retval = pthread_create ( &tid, &pattr, CASGarbage_thread_wrapper, this );
00094     CheckRetVal ( retval, std::string ( "pthread_create()" ) );
00095 
00096     // Indicate the creation of the thread.
00097     trasher_thread_created = true;
00098 }
00099 
00106 void
00107 CASGarbage::TerminateTrasherThread() {
00108     // Make sure a thread has been created
00109     if ( trasher_thread_created == false ) {
00110         return;
00111     }
00112 
00113     // Signal the thread the end of his life
00114     time_to_die = true;
00115 
00116     // Signal the trasher thread
00117     int retval = pthread_cond_broadcast ( &cond_var );
00118     CheckRetVal ( retval, std::string ( "pthread_cond_broadcast()" ) );
00119 
00120     // Wait for the thread to complete and exit
00121     retval = pthread_join ( tid, NULL );
00122     CheckRetVal ( retval, std::string ( "pthread_join()" ) );
00123 
00124     // Destroy Thread Attribute
00125     retval = pthread_attr_destroy ( &pattr );
00126     CheckRetVal ( retval, std::string ( "pthread_attr_destroy()" ) );
00127 
00128     // Indicate
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         // This could get complicated, because there is no memory
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 // Protected methods
00192 // ----------------------------------------------------------------------------
00193 // ----------------------------------------------------------------------------
00194 
00195 
00196 // Constructors & Destructor
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     // Initialize the Mutex Attribute
00209     int retval = pthread_mutexattr_init ( &mutex_attr );
00210     CheckRetVal ( retval, std::string ( "pthread_mutexattr_init()" ) );
00211 
00212     // Set the Mutex sharing
00213     retval = pthread_mutexattr_setpshared ( &mutex_attr, PTHREAD_PROCESS_PRIVATE );
00214     CheckRetVal ( retval, std::string ( "pthread_mutexattr_setpshared()" ) );
00215 
00216     // Set the Mutex type
00217     retval = pthread_mutexattr_settype ( &mutex_attr, PTHREAD_MUTEX_ERRORCHECK );
00218     CheckRetVal ( retval, std::string ( "pthread_mutexattr_settype()" ) );
00219 
00220     // Create the Mutex
00221     retval = pthread_mutex_init ( &mutex, &mutex_attr );
00222     CheckRetVal ( retval, std::string ( "pthread_mutex_init()" ) );
00223 
00224     // Create the conditional variable.
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     // Clean up for the last time. The trasher thread might left
00241     // objects undestroyed since the threshold for cleaning up was not
00242     // reached.
00243     RemoveDuplicate();
00244     std::for_each ( list.begin(),
00245                     list.end(),
00246                     CASDestroyObject() );
00247 
00248     // Destroy Mutex
00249     int retval = pthread_mutex_destroy ( &mutex );
00250     CheckRetVal ( retval, std::string ( "phtread_mutex_destroy()" ) );
00251 
00252     // Destroy Mutex Attribute
00253     retval = pthread_mutexattr_destroy ( &mutex_attr );
00254     CheckRetVal ( retval, std::string ( "pthread_mutexattr_destroy()" ) );
00255 
00256     // Destroy conditional variable
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 // Public Methods
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     // Acquire the mutex
00331     int retval = pthread_mutex_lock ( &mutex );
00332     CheckRetVal ( retval, std::string ( "pthread_mutex_lock()" ) );
00333     // Push the value on the list
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     // Acquire the mutex
00359     int retval = pthread_mutex_lock ( &mutex );
00360     CheckRetVal ( retval, std::string ( "pthread_mutex_lock()" ) );
00361     // Push the values on the list
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     // Acquire the mutex
00391     int retval = pthread_mutex_lock ( &mutex );
00392     CheckRetVal ( retval, std::string ( "pthread_mutex_lock()" ) );
00393     // Push the values on the list
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 // Operators
00410 // ----------------------------------------------------------------------------
00420 CASGarbage &
00421 CASGarbage::operator= ( const CASGarbage &wdc ) {
00422     throw EDoesNotApply();
00423 }
00424 // ----------------------------------------------------------------------------
00425 

Generated on Sun Dec 31 01:57:27 2006 for ECAS by  doxygen 1.4.7