Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members   Related Pages  

Service_Repository.cpp

Go to the documentation of this file.
00001 #include "ace_pch.h"
00002 // Service_Repository.cpp
00003 // $Id: Service_Repository.cpp,v 1.1.1.4.2.1 2003/03/13 19:44:22 chad Exp $
00004 
00005 #include "ace/Service_Repository.h"
00006 #include "ace/Object_Manager.h"
00007 #include "ace/Log_Msg.h"
00008 
00009 #if !defined (__ACE_INLINE__)
00010 #include "ace/Service_Repository.i"
00011 #endif /* __ACE_INLINE__ */
00012 
00013 ACE_RCSID(ace, Service_Repository, "$Id: Service_Repository.cpp,v 1.1.1.4.2.1 2003/03/13 19:44:22 chad Exp $")
00014 
00015 ACE_ALLOC_HOOK_DEFINE(ACE_Service_Repository)
00016 
00017 // Process-wide Service Repository.
00018 ACE_Service_Repository *ACE_Service_Repository::svc_rep_ = 0;
00019 
00020 // Controls whether the Service_Repository is deleted when we shut
00021 // down (we can only delete it safely if we created it)!
00022 int ACE_Service_Repository::delete_svc_rep_ = 0;
00023 
00024 void
00025 ACE_Service_Repository::dump (void) const
00026 {
00027   ACE_TRACE ("ACE_Service_Repository::dump");
00028 }
00029 
00030 ACE_Service_Repository::ACE_Service_Repository (void)
00031   : service_vector_ (0),
00032     current_size_ (0),
00033     total_size_ (0)
00034 {
00035   ACE_TRACE ("ACE_Service_Repository::ACE_Service_Repository");
00036 }
00037 
00038 ACE_Service_Repository *
00039 ACE_Service_Repository::instance (int size /* = ACE_Service_Repository::DEFAULT_SIZE */)
00040 {
00041   ACE_TRACE ("ACE_Service_Repository::instance");
00042 
00043   if (ACE_Service_Repository::svc_rep_ == 0)
00044     {
00045       // Perform Double-Checked Locking Optimization.
00046       ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon,
00047                                 *ACE_Static_Object_Lock::instance (), 0));
00048       if (ACE_Service_Repository::svc_rep_ == 0)
00049         {
00050           if (ACE_Object_Manager::starting_up () ||
00051               !ACE_Object_Manager::shutting_down ())
00052             {
00053               ACE_NEW_RETURN (ACE_Service_Repository::svc_rep_,
00054                               ACE_Service_Repository (size),
00055                               0);
00056               ACE_Service_Repository::delete_svc_rep_ = 1;
00057             }
00058         }
00059     }
00060 
00061   return ACE_Service_Repository::svc_rep_;
00062 }
00063 
00064 ACE_Service_Repository *
00065 ACE_Service_Repository::instance (ACE_Service_Repository *s)
00066 {
00067   ACE_TRACE ("ACE_Service_Repository::instance");
00068   ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon,
00069                             *ACE_Static_Object_Lock::instance (), 0));
00070 
00071   ACE_Service_Repository *t = ACE_Service_Repository::svc_rep_;
00072   // We can't safely delete it since we don't know who created it!
00073   ACE_Service_Repository::delete_svc_rep_ = 0;
00074 
00075   ACE_Service_Repository::svc_rep_ = s;
00076   return t;
00077 }
00078 
00079 void
00080 ACE_Service_Repository::close_singleton (void)
00081 {
00082   ACE_TRACE ("ACE_Service_Repository::close_singleton");
00083 
00084   ACE_MT (ACE_GUARD (ACE_Recursive_Thread_Mutex, ace_mon,
00085                      *ACE_Static_Object_Lock::instance ()));
00086 
00087   if (ACE_Service_Repository::delete_svc_rep_)
00088     {
00089       delete ACE_Service_Repository::svc_rep_;
00090       ACE_Service_Repository::svc_rep_ = 0;
00091       ACE_Service_Repository::delete_svc_rep_ = 0;
00092     }
00093 }
00094 
00095 // Initialize the Repository to a clean slate.
00096 
00097 int
00098 ACE_Service_Repository::open (int size)
00099 {
00100   ACE_TRACE ("ACE_Service_Repository::open");
00101 
00102   ACE_Service_Type **temp;
00103 
00104   ACE_NEW_RETURN (temp,
00105                   ACE_Service_Type *[size],
00106                   -1);
00107 
00108   this->service_vector_ = ACE_const_cast (const ACE_Service_Type **,
00109                                           temp);
00110   this->total_size_ = size;
00111   return 0;
00112 }
00113 
00114 ACE_Service_Repository::ACE_Service_Repository (int size)
00115   : current_size_ (0)
00116 {
00117   ACE_TRACE ("ACE_Service_Repository::ACE_Service_Repository");
00118 
00119   if (this->open (size) == -1)
00120     ACE_ERROR ((LM_ERROR,
00121                 ACE_LIB_TEXT ("%p\n"),
00122                 ACE_LIB_TEXT ("ACE_Service_Repository")));
00123 }
00124 
00125 // Finalize (call <fini> and possibly delete) all the services.
00126 
00127 int
00128 ACE_Service_Repository::fini (void)
00129 {
00130   ACE_TRACE ("ACE_Service_Repository::fini");
00131   ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
00132   int retval = 0;
00133 
00134   if (this->service_vector_ != 0)
00135     {
00136       // <fini> the services in reverse order.  Note that if services
00137       // were removed from the middle of the repository the order
00138       // won't necessarily be maintained since the <remove> method
00139       // performs compaction.  However, the common case is not to
00140       // remove services, so typically they are deleted in reverse
00141       // order.
00142 
00143       for (int i = this->current_size_ - 1; i >= 0; i--)
00144         {
00145           if (ACE::debug ())
00146             ACE_DEBUG ((LM_DEBUG,
00147                         ACE_LIB_TEXT ("finalizing %s\n"),
00148                         this->service_vector_[i]->name ()));
00149           ACE_Service_Type *s =
00150             ACE_const_cast (ACE_Service_Type *,
00151                             this->service_vector_[i]);
00152           // Collect errors.
00153           retval += s->fini ();
00154         }
00155     }
00156 
00157   return (retval == 0) ? 0 : -1;
00158 }
00159 
00160 // Close down all the services.
00161 
00162 int
00163 ACE_Service_Repository::close (void)
00164 {
00165   ACE_TRACE ("ACE_Service_Repository::close");
00166   ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
00167 
00168   if (this->service_vector_ != 0)
00169     {
00170       // Delete services in reverse order.  Note that if services were
00171       // removed from the middle of the repository the order won't
00172       // necessarily be maintained since the <remove> method performs
00173       // compaction.  However, the common case is not to remove
00174       // services, so typically they are deleted in reverse order.
00175 
00176       for (int i = this->current_size_ - 1; i >= 0; i--)
00177         {
00178           ACE_Service_Type *s = ACE_const_cast (ACE_Service_Type *,
00179                                                 this->service_vector_[i]);
00180           --this->current_size_;
00181           delete s;
00182         }
00183 
00184       delete [] this->service_vector_;
00185       this->service_vector_ = 0;
00186       this->current_size_ = 0;
00187     }
00188 
00189   return 0;
00190 }
00191 
00192 ACE_Service_Repository::~ACE_Service_Repository (void)
00193 {
00194   ACE_TRACE ("ACE_Service_Repository::~ACE_Service_Repository");
00195   this->close ();
00196 }
00197 
00198 // Locate an entry with <name> in the table.  If <ignore_suspended> is
00199 // set then only consider services marked as resumed.  If the caller
00200 // wants the located entry, pass back a pointer to the located entry
00201 // via <srp>.  If <name> is not found -1 is returned.  If <name> is
00202 // found, but it is suspended and the caller wants to ignore suspended
00203 // services a -2 is returned.  Must be called with locks held.
00204 
00205 int
00206 ACE_Service_Repository::find_i (const ACE_TCHAR name[],
00207                                 const ACE_Service_Type **srp,
00208                                 int ignore_suspended)
00209 {
00210   ACE_TRACE ("ACE_Service_Repository::find_i");
00211   int i;
00212 
00213   for (i = 0; i < this->current_size_; i++)
00214     if (ACE_OS::strcmp (name,
00215                         this->service_vector_[i]->name ()) == 0)
00216       break;
00217 
00218   if (i < this->current_size_)
00219     {
00220       if (this->service_vector_[i]->fini_called ())
00221         {
00222           if (srp != 0)
00223             *srp = 0;
00224           return -1;
00225         }
00226 
00227       if (srp != 0)
00228         *srp = this->service_vector_[i];
00229       if (ignore_suspended
00230           && this->service_vector_[i]->active () == 0)
00231         return -2;
00232       return i;
00233     }
00234   else
00235     return -1;
00236 }
00237 
00238 int
00239 ACE_Service_Repository::find (const ACE_TCHAR name[],
00240                               const ACE_Service_Type **srp,
00241                               int ignore_suspended)
00242 {
00243   ACE_TRACE ("ACE_Service_Repository::find");
00244   ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
00245 
00246   return this->find_i (name, srp, ignore_suspended);
00247 }
00248 
00249 
00250 // Insert the ACE_Service_Type SR into the repository.  Note that
00251 // services may be inserted either resumed or suspended.
00252 
00253 int
00254 ACE_Service_Repository::insert (const ACE_Service_Type *sr)
00255 {
00256   ACE_TRACE ("ACE_Service_Repository::insert");
00257   ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
00258   int i;
00259 
00260   // Check to see if this is a duplicate.
00261   for (i = 0; i < this->current_size_; i++)
00262     if (ACE_OS::strcmp (sr->name (),
00263                         this->service_vector_[i]->name ()) == 0)
00264       break;
00265 
00266   // Replacing an existing entry
00267   if (i < this->current_size_)
00268     {
00269       // Check for self-assignment...
00270       if (sr == this->service_vector_[i])
00271         return 0;
00272       ACE_Service_Type *s = ACE_const_cast (ACE_Service_Type *,
00273                                             this->service_vector_[i]);
00274       delete s;
00275       this->service_vector_[i] = sr;
00276       return 0;
00277     }
00278   // Adding a new entry.
00279   else if (i < this->total_size_)
00280     {
00281       this->service_vector_[i] = sr;
00282       this->current_size_++;
00283       return 0;
00284     }
00285 
00286   return -1;
00287 }
00288 
00289 // Re-resume a service that was previously suspended.
00290 
00291 int
00292 ACE_Service_Repository::resume (const ACE_TCHAR name[],
00293                                 const ACE_Service_Type **srp)
00294 {
00295   ACE_TRACE ("ACE_Service_Repository::resume");
00296   ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
00297 
00298   int i = this->find_i (name, srp, 0);
00299 
00300   if (i == -1)
00301     return -1;
00302 
00303   return this->service_vector_[i]->resume ();
00304 }
00305 
00306 // Suspend a service so that it will not be considered active under
00307 // most circumstances by other portions of the ACE_Service_Repository.
00308 
00309 int
00310 ACE_Service_Repository::suspend (const ACE_TCHAR name[],
00311                                  const ACE_Service_Type **srp)
00312 {
00313   ACE_TRACE ("ACE_Service_Repository::suspend");
00314   ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
00315   int i = this->find_i (name, srp, 0);
00316 
00317   if (i == -1)
00318     return -1;
00319 
00320   return this->service_vector_[i]->suspend ();
00321 }
00322 
00323 // Completely remove a <name> entry from the Repository and
00324 // dynamically unlink it if it was originally dynamically linked.
00325 // Since the order of services in the Respository does not matter, we
00326 // simply overwrite the entry being deleted with the final entry in
00327 // the array and decrement the <current_size> by 1.
00328 
00329 int
00330 ACE_Service_Repository::remove (const ACE_TCHAR name[])
00331 {
00332   ACE_TRACE ("ACE_Service_Repository::remove");
00333   ACE_Service_Type *s = 0;
00334   {
00335     ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
00336     int i = this->find_i (name, 0, 0);
00337 
00338     if (i == -1)
00339       return -1;
00340 
00341     s = ACE_const_cast (ACE_Service_Type *,
00342                         this->service_vector_[i]);
00343     --this->current_size_;
00344 
00345     if (this->current_size_ >= 1)
00346       this->service_vector_[i]
00347         = this->service_vector_[this->current_size_];
00348   }
00349   delete s;
00350   return 0;
00351 }
00352 
00353 ACE_ALLOC_HOOK_DEFINE(ACE_Service_Repository_Iterator)
00354 
00355 void
00356 ACE_Service_Repository_Iterator::dump (void) const
00357 {
00358   ACE_TRACE ("ACE_Service_Repository_Iterator::dump");
00359 }
00360 
00361 // Initializes the iterator and skips over any suspended entries at
00362 // the beginning of the table, if necessary.  Note, you must not
00363 // perform destructive operations on elements during this iteration...
00364 
00365 ACE_Service_Repository_Iterator::ACE_Service_Repository_Iterator
00366   (ACE_Service_Repository &sr,
00367    int ignr_suspended)
00368   : svc_rep_ (sr),
00369     next_ (-1),
00370     ignore_suspended_ (ignr_suspended)
00371 {
00372   this->advance ();
00373 }
00374 
00375 // Obtains a pointer to the next valid service in the table.  If there
00376 // are no more entries, returns 0, else 1.
00377 
00378 int
00379 ACE_Service_Repository_Iterator::next (const ACE_Service_Type *&sr)
00380 {
00381   ACE_TRACE ("ACE_Service_Repository_Iterator::next");
00382   if (this->next_ < this->svc_rep_.current_size_)
00383     {
00384       sr = this->svc_rep_.service_vector_[this->next_];
00385       return 1;
00386     }
00387   else
00388     return 0;
00389 }
00390 
00391 int
00392 ACE_Service_Repository_Iterator::done (void) const
00393 {
00394   ACE_TRACE ("ACE_Service_Repository_Iterator::done");
00395 
00396   return this->next_ >= this->svc_rep_.current_size_;
00397 }
00398 
00399 // Advance the iterator by the proper amount.  If we are ignoring
00400 // suspended entries and the current entry is suspended, then we must
00401 // skip over this entry.  Otherwise, we must advance the NEXT index to
00402 // reference the next valid service entry.
00403 
00404 int
00405 ACE_Service_Repository_Iterator::advance (void)
00406 {
00407   ACE_TRACE ("ACE_Service_Repository_Iterator::advance");
00408 
00409   for (++this->next_;
00410        this->next_ < this->svc_rep_.current_size_
00411        && this->ignore_suspended_
00412        && this->svc_rep_.service_vector_[this->next_]->active () == 0;
00413        this->next_++)
00414     continue;
00415 
00416   return this->next_ < this->svc_rep_.current_size_;
00417 }

Generated on Mon Jun 16 11:21:12 2003 for ACE by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002