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

Transport_Cache_Manager.cpp

Go to the documentation of this file.
00001 #include "tao_pch.h"
00002 #include "tao/Transport_Cache_Manager.h"
00003 #include "tao/Transport.h"
00004 #include "tao/debug.h"
00005 #include "tao/ORB_Core.h"
00006 #include "tao/Resource_Factory.h"
00007 #include "tao/Connection_Purging_Strategy.h"
00008 #include "tao/Condition.h"
00009 #include "ace/Synch_T.h"
00010 #include "ace/Containers_T.h"
00011 #include "ace/Handle_Set.h"
00012 
00013 #if !defined (__ACE_INLINE__)
00014 # include "tao/Transport_Cache_Manager.inl"
00015 #endif /* __ACE_INLINE__ */
00016 
00017 
00018 ACE_RCSID (TAO,
00019            Transport_Cache_Manager,
00020            "$Id: Transport_Cache_Manager.cpp,v 1.1.1.2.2.2 2003/04/21 19:10:25 chad Exp $")
00021 
00022 
00023 TAO_Transport_Cache_Manager::TAO_Transport_Cache_Manager (TAO_ORB_Core &orb_core)
00024   : percent_ (orb_core.resource_factory ()->purge_percentage ()),
00025     purging_strategy_ (orb_core.resource_factory ()->create_purging_strategy ()),
00026     cache_map_ (ACE_static_cast (size_t, ACE::max_handles ())),
00027     condition_ (0),
00028     cache_lock_ (0),
00029     muxed_number_ (orb_core.resource_factory ()->max_muxed_connections ()),
00030     no_waiting_threads_ (0),
00031     last_entry_returned_ (0)
00032 {
00033   if (orb_core.resource_factory ()->locked_transport_cache ())
00034     {
00035       ACE_NEW (this->condition_,
00036                TAO_Condition <TAO_SYNCH_MUTEX>);
00037 
00038       ACE_NEW (this->cache_lock_,
00039                ACE_Lock_Adapter <TAO_SYNCH_MUTEX> (*this->condition_->mutex ()));
00040     }
00041   else
00042     {
00043       /// If the cache is not going to be locked then dont create a
00044       /// condition variable. Make the <muxed_number_> to 0, else a
00045       /// single thread could get into waiting mode
00046       this->muxed_number_ = 0;
00047       ACE_NEW (this->cache_lock_,
00048                ACE_Lock_Adapter<ACE_SYNCH_NULL_MUTEX>);
00049     }
00050 }
00051 
00052 TAO_Transport_Cache_Manager::~TAO_Transport_Cache_Manager (void)
00053 {
00054   // Wakeup all the waiting threads threads before we shutdown stuff
00055   if (this->no_waiting_threads_)
00056     this->condition_->broadcast ();
00057 
00058   // Delete the lock that we have
00059   if (this->cache_lock_)
00060     {
00061       delete this->cache_lock_;
00062       this->cache_lock_ = 0;
00063     }
00064 
00065   // Delete the purging strategy
00066   if (this->purging_strategy_)
00067     {
00068       delete this->purging_strategy_;
00069       this->purging_strategy_ = 0;
00070     }
00071 
00072   // Delete the condition variable
00073   if (this->condition_)
00074     {
00075       delete this->condition_;
00076       this->condition_ = 0;
00077     }
00078 }
00079 
00080 
00081 int
00082 TAO_Transport_Cache_Manager::bind_i (TAO_Cache_ExtId &ext_id,
00083                                      TAO_Cache_IntId &int_id)
00084 {
00085   if (TAO_debug_level > 0)
00086     {
00087       ACE_DEBUG ((LM_DEBUG,
00088                   "TAO (%P|%t) - Transport_Cache_Manager::bind_i, "
00089                   "0x%x -> 0x%x Transport[%d]\n",
00090                   ext_id.property (),
00091                   int_id.transport (),
00092                   int_id.transport ()->id ()));
00093     }
00094 
00095   // Get the entry too
00096   HASH_MAP_ENTRY *entry = 0;
00097 
00098   // Update the purging strategy information while we
00099   // are holding our lock
00100   this->purging_strategy_->update_item (int_id.transport ());
00101 
00102 
00103 
00104   int retval = this->cache_map_.bind (ext_id,
00105                                       int_id,
00106                                       entry);
00107   if (retval == 0)
00108     {
00109       // The entry has been added to cache succesfully
00110       // Add the cache_map_entry to the transport
00111       int_id.transport ()->cache_map_entry (entry);
00112     }
00113   else if (retval == 1)
00114     {
00115       if (TAO_debug_level > 4 && retval != 0)
00116         {
00117           ACE_DEBUG ((LM_DEBUG,
00118                       "TAO (%P|%t) - Transport_Cache_Manager::bind_i, "
00119                       "unable to bind in the first attempt. "
00120                       "Trying with a new index\n"));
00121         }
00122 
00123 
00124       // There was an entry like this before, so let us do some
00125       // minor adjustments and rebind
00126       retval = this->get_last_index_bind (ext_id,
00127                                           int_id,
00128                                           entry);
00129       if (retval == 0)
00130         {
00131           int_id.transport ()->cache_map_entry (entry);
00132         }
00133     }
00134 
00135   if (TAO_debug_level > 5 && retval != 0)
00136     {
00137       ACE_ERROR ((LM_ERROR,
00138                   "TAO (%P|%t) - Transport_Cache_Manager::bind_i, "
00139                   "unable to bind\n"));
00140     }
00141   else if (TAO_debug_level > 3)
00142     {
00143       ACE_DEBUG ((LM_DEBUG,
00144                   "TAO (%P|%t) - Transport_Cache_Manager::bind_i, "
00145                   " size is [%d] \n",
00146                   this->current_size ()));
00147     }
00148 
00149   return retval;
00150 }
00151 
00152 int
00153 TAO_Transport_Cache_Manager::find_transport (
00154     TAO_Transport_Descriptor_Interface *prop,
00155     TAO_Transport *&transport)
00156 {
00157   if (prop == 0)
00158     {
00159       transport = 0;
00160       return -1;
00161     }
00162 
00163   // Compose the ExternId
00164   TAO_Cache_ExtId ext_id (prop);
00165   TAO_Cache_IntId int_id;
00166 
00167   int retval = this->find (ext_id,
00168                            int_id);
00169   if (retval == 0)
00170     {
00171       transport = int_id.relinquish_transport ();
00172     }
00173 
00174   return retval;
00175 }
00176 
00177 int
00178 TAO_Transport_Cache_Manager::find (const TAO_Cache_ExtId &key,
00179                                     TAO_Cache_IntId &value)
00180 {
00181   ACE_MT (ACE_GUARD_RETURN  (ACE_Lock,
00182                              guard,
00183                              *this->cache_lock_,
00184                              -1));
00185 
00186   int status =  this->find_i (key,
00187                               value);
00188 
00189   if (status == 0)
00190     {
00191       // Update the purging strategy information while we
00192       // are holding our lock
00193       this->purging_strategy_->update_item (value.transport ());
00194     }
00195 
00196   return status;
00197 }
00198 
00199 
00200 
00201 int
00202 TAO_Transport_Cache_Manager::find_i (const TAO_Cache_ExtId &key,
00203                                      TAO_Cache_IntId &value)
00204 {
00205   HASH_MAP_ENTRY *entry = 0;
00206 
00207   // Get the entry from the Hash Map
00208   int retval = 0;
00209 
00210   // Make a temporary object. It does not do a copy.
00211   TAO_Cache_ExtId tmp_key (key.property ());
00212 
00213   while (retval == 0)
00214     {
00215       // Wait for a connection..
00216       this->wait_for_connection (tmp_key);
00217 
00218       // Look for an entry in the map
00219       retval = this->cache_map_.find (tmp_key,
00220                                       entry);
00221 
00222       // We have an entry in the map, check whether it is idle.
00223       if (entry)
00224         {
00225           CORBA::Boolean idle =
00226             this->is_entry_idle (entry);
00227 
00228           if (idle)
00229             {
00230               // Successfully found a TAO_Transport.
00231 
00232               // NOTE: This assignment operator indirectly incurs two
00233               //       lock operations since it duplicates and releases
00234               //       TAO_Transport objects.
00235               value = entry->int_id_;
00236 
00237               entry->int_id_.recycle_state (ACE_RECYCLABLE_BUSY);
00238 
00239               if (TAO_debug_level > 4)
00240                 {
00241                   ACE_DEBUG ((LM_DEBUG,
00242                               "TAO (%P|%t) - Transport_Cache_Manager::find_i, "
00243                               "index in find <%d> (Transport[%d])\n",
00244                               entry->ext_id_.index (),
00245                               value.transport ()->id ()
00246                               ));
00247                 }
00248               return 0;
00249             }
00250         }
00251 
00252       // Bump the index up
00253       tmp_key.incr_index ();
00254     }
00255 
00256   // If we are here then it is an error
00257   if (TAO_debug_level > 4 && retval != 0)
00258     {
00259       ACE_ERROR ((LM_ERROR,
00260                   "TAO (%P|%t) - Transport_Cache_Manager::find_i, "
00261                   "unable to locate a free connection\n"));
00262     }
00263 
00264   return retval;
00265 }
00266 
00267 int
00268 TAO_Transport_Cache_Manager::make_idle_i (HASH_MAP_ENTRY *&entry)
00269 {
00270   if (entry == 0)
00271     return -1;
00272 
00273   // First get the entry again (if at all things had changed in the
00274   // cache map in the mean time)
00275 
00276   // @todo: Is this required? Looks like a legacy one..
00277 
00278   HASH_MAP_ENTRY *new_entry = 0;
00279   int retval = this->cache_map_.find (entry->ext_id_,
00280                                       new_entry);
00281   if (retval == 0)
00282     {
00283 
00284       new_entry->int_id_.
00285         recycle_state (ACE_RECYCLABLE_IDLE_AND_PURGABLE);
00286 
00287       entry = new_entry;
00288 
00289       // Does any one need waking?
00290       if (this->no_waiting_threads_)
00291         {
00292           // We returned this entry to the map
00293           this->last_entry_returned_ = &new_entry->ext_id_;
00294 
00295           // Wake up a thread
00296           this->condition_->signal ();
00297         }
00298     }
00299   else if (TAO_debug_level > 0 && retval != 0)
00300     {
00301       ACE_ERROR ((LM_ERROR,
00302                   "TAO (%P|%t) - Transport_Cache_Manager::make_idle_i, "
00303                   "unable to locate the entry to make it idle\n"));
00304     }
00305 
00306   return retval;
00307 }
00308 
00309 
00310 int
00311 TAO_Transport_Cache_Manager::update_entry (HASH_MAP_ENTRY *&entry)
00312 {
00313   if(entry == 0)
00314     return -1;
00315 
00316   ACE_MT (ACE_GUARD_RETURN (ACE_Lock,
00317                             guard,
00318                             *this->cache_lock_, -1));
00319 
00320   if (entry == 0)
00321     return -1;
00322 
00323   TAO_Connection_Purging_Strategy *st =
00324     this->purging_strategy_;
00325 
00326   (void) st->update_item (entry->int_id_.transport ());
00327 
00328   return 0;
00329 }
00330 
00331 int
00332 TAO_Transport_Cache_Manager::close_i (ACE_Handle_Set &reactor_registered,
00333                                       TAO_EventHandlerSet &unregistered)
00334 {
00335   HASH_MAP_ITER end_iter =
00336     this->cache_map_.end ();
00337 
00338   for (HASH_MAP_ITER iter = this->cache_map_.begin ();
00339        iter != end_iter;
00340        ++iter)
00341     {
00342       // First we look through whether we have an entry that has already
00343       // been closed.
00344 
00345       if ((*iter).int_id_.recycle_state () != ACE_RECYCLABLE_CLOSED)
00346         {
00347           // Get the transport to fill its associated connection's handle in
00348           // the handle sets.
00349           (*iter).int_id_.transport ()->provide_handle (reactor_registered,
00350                                                         unregistered);
00351           // Inform the transport that has a reference to the entry in the
00352           // map that we are *gone* now. So, the transport should not use
00353           // the reference to the entry that he has, to acces us *at any
00354           // time*.
00355           (*iter).int_id_.transport ()->cache_map_entry (0);
00356         }
00357      }
00358 
00359   // Unbind all the entries in the map
00360   this->cache_map_.unbind_all ();
00361 
00362   return 0;
00363 }
00364 
00365 int
00366 TAO_Transport_Cache_Manager::purge_entry_i (HASH_MAP_ENTRY *&entry)
00367 {
00368   if (entry == 0)
00369     return 0;
00370 
00371   // Remove the entry from the Map
00372  int retval = this->cache_map_.unbind (entry);
00373 
00374   // Set the entry pointer to zero
00375   entry = 0;
00376 
00377   return retval;
00378 }
00379 
00380 void
00381 TAO_Transport_Cache_Manager::mark_invalid_i (HASH_MAP_ENTRY *&entry)
00382 {
00383   if (entry == 0)
00384     return;
00385 
00386   // Mark the entry as not usable
00387   entry->int_id_.recycle_state (ACE_RECYCLABLE_PURGABLE_BUT_NOT_IDLE);
00388 }
00389 
00390 
00391 
00392 int
00393 TAO_Transport_Cache_Manager::get_last_index_bind (TAO_Cache_ExtId &key,
00394                                                   TAO_Cache_IntId &val,
00395                                                   HASH_MAP_ENTRY *&entry)
00396 {
00397   CORBA::ULong ctr = entry->ext_id_.index ();
00398 
00399   int retval = 0;
00400 
00401   while (retval == 0)
00402     {
00403       // Set the index
00404       key.index (++ctr);
00405 
00406       // Check to see if an element exists in the Map. If it exists we
00407       // loop, else we drop out of the loop
00408       retval =
00409         this->cache_map_.find (key);
00410     }
00411 
00412   // Now do a bind again with the new index
00413   return  this->cache_map_.bind (key,
00414                                  val,
00415                                  entry);
00416 }
00417 
00418 
00419 int
00420 TAO_Transport_Cache_Manager::is_entry_idle (HASH_MAP_ENTRY *&entry)
00421 {
00422   if (TAO_debug_level)
00423     {
00424       ACE_DEBUG ((LM_DEBUG,
00425                   "TAO (%P|%t) - Transport_Cache_Manager::is_entry_idle_i, "
00426                   "state is [%d]\n",
00427                   entry->int_id_.recycle_state ()));
00428     }
00429   if (entry->int_id_.recycle_state () == ACE_RECYCLABLE_IDLE_AND_PURGABLE ||
00430       entry->int_id_.recycle_state () == ACE_RECYCLABLE_IDLE_BUT_NOT_PURGABLE)
00431     return 1;
00432 
00433   return 0;
00434 }
00435 
00436 
00437 #if !defined (ACE_LACKS_QSORT)
00438 int
00439 TAO_Transport_Cache_Manager::cpscmp(const void* a, const void* b)
00440 {
00441   const HASH_MAP_ENTRY** left  = (const HASH_MAP_ENTRY**)a;
00442   const HASH_MAP_ENTRY** right = (const HASH_MAP_ENTRY**)b;
00443 
00444   if ((*left)->int_id_.transport ()->purging_order () <
00445       (*right)->int_id_.transport ()->purging_order ())
00446     return -1;
00447 
00448   if ((*left)->int_id_.transport ()->purging_order () >
00449       (*right)->int_id_.transport ()->purging_order ())
00450     return 1;
00451 
00452   return 0;
00453 }
00454 #endif /* ACE_LACKS_QSORT */
00455 
00456 int
00457 TAO_Transport_Cache_Manager::purge (void)
00458 {
00459   ACE_Unbounded_Stack<TAO_Transport*> transports_to_be_closed;
00460 
00461   {
00462     ACE_MT (ACE_GUARD_RETURN (ACE_Lock, ace_mon, *this->cache_lock_, 0));
00463 
00464     DESCRIPTOR_SET sorted_set = 0;
00465     int sorted_size = this->fill_set_i (sorted_set);
00466 
00467     // Only call close_entries () if sorted_set != 0.  It takes control of
00468     // sorted_set and cleans up any allocated memory.  If sorted_set == 0,
00469     // then there is nothing to de-allocate.
00470     if (sorted_set != 0)
00471       {
00472         // BEGIN FORMER close_entries
00473         // Calculate the number of entries to purge
00474         const int amount = (sorted_size * this->percent_) / 100;
00475 
00476         if (TAO_debug_level > 0)
00477           {
00478             ACE_DEBUG ((LM_DEBUG,
00479                         ACE_TEXT ("TAO (%P|%t) - Transport_Cache_Manager::purge, ")
00480                         ACE_TEXT ("purging %d of %d cache entries\n"),
00481                         amount,
00482                         sorted_size));
00483           }
00484 
00485         int count = 0;
00486         for(int i = 0; count < amount && i < sorted_size; i++)
00487           {
00488             if (this->is_entry_idle(sorted_set[i]))
00489               {
00490                 sorted_set[i]->int_id_.recycle_state (ACE_RECYCLABLE_BUSY);
00491 
00492                 TAO_Transport* transport = sorted_set[i]->int_id_.transport ();
00493                 if (transports_to_be_closed.push (TAO_Transport::_duplicate(transport)) != 0)
00494                   {
00495                     ACE_DEBUG ((LM_INFO,
00496                                 ACE_TEXT ("TAO (%P|%t) - ")
00497                                 ACE_TEXT ("Unable to push transport %lu on the to-be-closed stack, so it will leak\n"),
00498                                 transport));
00499                   }
00500 
00501                 if (TAO_debug_level > 0)
00502                   {
00503                     ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("TAO (%P|%t) - ")
00504                                           ACE_TEXT ("Idle transport found in ")
00505                                           ACE_TEXT ("cache: [%d] \n"),
00506                                           transport->id ()));
00507                   }
00508 
00509                 // We need to save the cache_map_entry before we
00510                 // set it to zero, so we can call purge_entry_i()
00511                 // after we call close_connection_no_purge ().
00512                 HASH_MAP_ENTRY* entry = transport->cache_map_entry ();
00513 
00514                 // This is a bit ugly, but we must do this to
00515                 // avoid taking and giving locks inside this loop.
00516                 transport->cache_map_entry (0);
00517                 this->purge_entry_i (entry);
00518 
00519                 // Count this as a successful purged entry
00520                 count++;
00521               }
00522           }
00523 
00524       delete [] sorted_set;
00525       sorted_set = 0;
00526       // END FORMER close_entries
00527     }
00528   }
00529 
00530   // Now, without the lock held, lets go through and close all the transports.
00531   TAO_Transport *transport = 0;
00532   while (! transports_to_be_closed.is_empty ())
00533     {
00534       if (transports_to_be_closed.pop (transport) == 0)
00535         {
00536           if (transport)
00537             transport->close_connection_no_purge ();
00538           TAO_Transport::release (transport);
00539         }
00540     }
00541 
00542   return 0;
00543 }
00544 
00545 
00546 void
00547 TAO_Transport_Cache_Manager::sort_set (DESCRIPTOR_SET& entries,
00548                                        int current_size)
00549 {
00550 #if defined (ACE_LACKS_QSORT)
00551   // Use insertion sort if we don't have qsort
00552   for(int i = 1; i < current_size; i++)
00553     {
00554       if (entries[i]->int_id_.transport ()->purging_order () <
00555                     entries[i - 1]->int_id_.transport ()->purging_order ())
00556         {
00557           HASH_MAP_ENTRY* entry = entries[i];
00558           for(int j = i; j > 0 &&
00559               entries[j - 1]->int_id_.transport ()->purging_order () >
00560               entry->int_id_.transport ()->purging_order (); j--)
00561             {
00562               HASH_MAP_ENTRY* holder = entries[j];
00563               entries[j] = entries[j - 1];
00564               entries[j - 1] = holder;
00565             }
00566         }
00567     }
00568 #else
00569   ACE_OS::qsort (entries, current_size,
00570                  sizeof (HASH_MAP_ENTRY*), (ACE_COMPARE_FUNC)cpscmp);
00571 #endif /* ACE_LACKS_QSORT */
00572 }
00573 
00574 
00575 int
00576 TAO_Transport_Cache_Manager::fill_set_i (DESCRIPTOR_SET& sorted_set)
00577 {
00578   int current_size = 0;
00579   int cache_maximum = this->purging_strategy_->cache_maximum ();
00580 
00581   // set sorted_set to 0.  This signifies nothing to purge.
00582   sorted_set = 0;
00583 
00584   // Do we need to worry about cache purging?
00585   if (cache_maximum >= 0)
00586     {
00587       current_size = ACE_static_cast(int, this->cache_map_.current_size ());
00588 
00589       if (TAO_debug_level > 0)
00590         {
00591           ACE_DEBUG ((LM_DEBUG,
00592                       "TAO (%P|%t) - Transport_Cache_Manager::fill_set_i, "
00593                       "current_size = %d, cache_maximum = %d\n",
00594                       current_size, cache_maximum));
00595         }
00596 
00597       if (current_size >= cache_maximum)
00598         {
00599           ACE_NEW_RETURN (sorted_set, HASH_MAP_ENTRY*[current_size], 0);
00600 
00601           HASH_MAP_ITER iter = this->cache_map_.begin ();
00602           for (int i = 0; i < current_size; i++)
00603             {
00604               sorted_set[i] = &(*iter);
00605               iter++;
00606             }
00607           this->sort_set (sorted_set, current_size);
00608         }
00609     }
00610 
00611   return current_size;
00612 }
00613 
00614 
00615 int
00616 TAO_Transport_Cache_Manager::wait_for_connection (TAO_Cache_ExtId &extid)
00617 {
00618   if (this->muxed_number_ &&
00619       this->muxed_number_ == extid.index ())
00620     {
00621       // If we have a limit on the number of muxed connections for
00622       // a particular endpoint just wait to get the connection
00623       ++this->no_waiting_threads_;
00624 
00625       if (TAO_debug_level > 2)
00626         {
00627           ACE_DEBUG ((LM_DEBUG,
00628                       "TAO (%P|%t) - Transport_Cache_Manager::wait_for_connection, "
00629                       "entering wait loop\n"));
00630         }
00631 
00632       int ready_togo = 0;
00633 
00634       while (ready_togo == 0)
00635         {
00636           this->condition_->wait ();
00637 
00638           // Check whether we are waiting for this connection
00639           ready_togo = this->is_wakeup_useful (extid);
00640         }
00641 
00642       if (TAO_debug_level > 2)
00643         {
00644           ACE_DEBUG ((LM_DEBUG,
00645                       "TAO (%P|%t) - Transport_Cache_Manager::wait_for_connection, "
00646                       "left wait loop\n"));
00647         }
00648 
00649       // We are not waiting anymore
00650       --this->no_waiting_threads_;
00651     }
00652 
00653   return 0;
00654 }
00655 
00656 int
00657 TAO_Transport_Cache_Manager::is_wakeup_useful (TAO_Cache_ExtId &extid)
00658 {
00659   // Get the underlying property that we are looking for
00660   TAO_Transport_Descriptor_Interface *prop = extid.property ();
00661 
00662   // Just check the underlying property for equivalence. If the last
00663   // connection that was returned  had the same property just return
00664   // 1.
00665   if (this->last_entry_returned_ &&
00666       prop->is_equivalent (this->last_entry_returned_->property ()))
00667     {
00668       // Set the index to be right so that we can pick teh connection
00669       // right away..
00670       extid.index (this->last_entry_returned_->index ());
00671 
00672       // There is no more use for it ...
00673       this->last_entry_returned_ = 0;
00674 
00675       return 1;
00676     }
00677 
00678   // If there  is an entry that was returned and if there are more
00679   // threads just wake up the peer to check for the returned
00680   // connection.
00681   if (this->last_entry_returned_ &&
00682       this->no_waiting_threads_ > 1)
00683     {
00684       this->condition_->signal ();
00685     }
00686 
00687   return 0;
00688 }
00689 
00690 #if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION)
00691 
00692   // Instantiations for the Hash Map
00693 template class ACE_Equal_To<TAO_Cache_ExtId>;
00694 template class ACE_Hash<TAO_Cache_ExtId>;
00695 template class ACE_Hash_Map_Entry<TAO_Cache_ExtId, TAO_Cache_IntId>;
00696 template class ACE_Hash_Map_Manager_Ex<TAO_Cache_ExtId, TAO_Cache_IntId, ACE_Hash<TAO_Cache_ExtId>, ACE_Equal_To<TAO_Cache_ExtId>, ACE_Null_Mutex>;
00697 template class ACE_Hash_Map_Iterator_Base_Ex<TAO_Cache_ExtId, TAO_Cache_IntId, ACE_Hash<TAO_Cache_ExtId>, ACE_Equal_To<TAO_Cache_ExtId>, ACE_Null_Mutex>;
00698 template class ACE_Hash_Map_Iterator_Ex<TAO_Cache_ExtId, TAO_Cache_IntId, ACE_Hash<TAO_Cache_ExtId>, ACE_Equal_To<TAO_Cache_ExtId>, ACE_Null_Mutex>;
00699 template class ACE_Hash_Map_Reverse_Iterator_Ex<TAO_Cache_ExtId, TAO_Cache_IntId, ACE_Hash<TAO_Cache_ExtId>, ACE_Equal_To<TAO_Cache_ExtId>, ACE_Null_Mutex>;
00700 template class ACE_Unbounded_Set<ACE_Event_Handler*>;
00701 template class ACE_Unbounded_Set_Iterator<ACE_Event_Handler*>;
00702 template class ACE_Node<ACE_Event_Handler*>;
00703 template class ACE_Unbounded_Stack<TAO_Transport*>;
00704 template class ACE_Node <TAO_Transport *>;
00705 
00706 template class TAO_Condition<ACE_SYNCH_MUTEX>;
00707 #elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA)
00708 
00709   // Instantiations for the Hash Map
00710 #pragma instantiate ACE_Equal_To<TAO_Cache_ExtId>
00711 #pragma instantiate ACE_Hash<TAO_Cache_ExtId>
00712 #pragma instantiate ACE_Hash_Map_Entry<TAO_Cache_ExtId, TAO_Cache_IntId>
00713 #pragma instantiate ACE_Hash_Map_Manager_Ex<TAO_Cache_ExtId, TAO_Cache_IntId, ACE_Hash<TAO_Cache_ExtId>, ACE_Equal_To<TAO_Cache_ExtId>, ACE_Null_Mutex>
00714 #pragma instantiate ACE_Hash_Map_Iterator_Base_Ex<TAO_Cache_ExtId, TAO_Cache_IntId, ACE_Hash<TAO_Cache_ExtId>, ACE_Equal_To<TAO_Cache_ExtId>, ACE_Null_Mutex>
00715 #pragma instantiate ACE_Hash_Map_Iterator_Ex<TAO_Cache_ExtId, TAO_Cache_IntId, ACE_Hash<TAO_Cache_ExtId>, ACE_Equal_To<TAO_Cache_ExtId>, ACE_Null_Mutex>
00716 #pragma instantiate ACE_Hash_Map_Reverse_Iterator_Ex<TAO_Cache_ExtId, TAO_Cache_IntId, ACE_Hash<TAO_Cache_ExtId>, ACE_Equal_To<TAO_Cache_ExtId>, ACE_Null_Mutex>
00717 #pragma instantiate ACE_Unbounded_Set<ACE_Event_Handler*>
00718 #pragma instantiate ACE_Unbounded_Set_Iterator<ACE_Event_Handler*>
00719 #pragma instantiate ACE_Node<ACE_Event_Handler*>
00720 #pragma instantiate ACE_Unbounded_Stack<TAO_Transport*>
00721 #pragma instantiate ACE_Node <TAO_Transport *>
00722 
00723 #pragma instantiate TAO_Condition<ACE_SYNCH_MUTEX>
00724 #endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */

Generated on Mon Jun 16 13:50:06 2003 for TAO by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002