NVList.cpp

Go to the documentation of this file.
00001 // $Id: NVList.cpp 78631 2007-06-28 13:49:10Z johnnyw $
00002 
00003 
00004 // Implementation of Named Value List and NamedValue classes
00005 
00006 #include "tao/AnyTypeCode/NVList.h"
00007 #include "tao/AnyTypeCode/BoundsC.h"
00008 #include "tao/AnyTypeCode/TypeCode.h"
00009 #include "tao/AnyTypeCode/Marshal.h"
00010 #include "tao/AnyTypeCode/Any_Impl.h"
00011 
00012 #include "tao/CORBA_String.h"
00013 #include "tao/CDR.h"
00014 #include "tao/debug.h"
00015 #include "tao/SystemException.h"
00016 
00017 #include "ace/Auto_Ptr.h"
00018 #include "ace/Log_Msg.h"
00019 #include "ace/CORBA_macros.h"
00020 
00021 #if !defined (__ACE_INLINE__)
00022 # include "tao/AnyTypeCode/NVList.inl"
00023 #endif /* ! __ACE_INLINE__ */
00024 
00025 ACE_RCSID (AnyTypeCode,
00026            NVList,
00027            "$Id: NVList.cpp 78631 2007-06-28 13:49:10Z johnnyw $")
00028 
00029 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
00030 
00031 // Reference counting for DII Request object
00032 
00033 CORBA::ULong
00034 CORBA::NamedValue::_incr_refcnt (void)
00035 {
00036   return ++this->refcount_;
00037 }
00038 
00039 CORBA::ULong
00040 CORBA::NamedValue::_decr_refcnt (void)
00041 {
00042   CORBA::ULong const new_count = --this->refcount_;
00043 
00044   if (new_count == 0)
00045     delete this;
00046 
00047   return new_count;
00048 }
00049 
00050 CORBA::NamedValue::~NamedValue (void)
00051 {
00052   if (this->name_)
00053     {
00054       CORBA::string_free (this->name_);
00055       this->name_ = 0;
00056     }
00057   // the any will be destroyed by itself
00058 }
00059 
00060 // ****************************************************************
00061 
00062 CORBA::ULong
00063 CORBA::NVList::_incr_refcnt (void)
00064 {
00065   return ++this->refcount_;
00066 }
00067 
00068 CORBA::ULong
00069 CORBA::NVList::_decr_refcnt (void)
00070 {
00071   const CORBA::ULong new_count = --this->refcount_;
00072 
00073   if (new_count == 0)
00074     delete this;
00075 
00076   return new_count;
00077 }
00078 
00079 CORBA::NVList::~NVList (void)
00080 {
00081   // initialize an iterator and delete each NamedValue
00082   ACE_Unbounded_Queue_Iterator<CORBA::NamedValue_ptr> iter (this->values_);
00083 
00084   for (iter.first (); !iter.done (); iter.advance ())
00085     {
00086       CORBA::NamedValue_ptr *nv = 0;
00087       (void) iter.next (nv);
00088       delete *nv;
00089     }
00090 
00091   this->max_ = 0;
00092 
00093   // Remove the CDR stream if it is present.
00094   delete this->incoming_;
00095 }
00096 
00097 // add an element and just initialize its flags
00098 CORBA::NamedValue_ptr
00099 CORBA::NVList::add (CORBA::Flags flags)
00100 {
00101   // call the helper to allocate a NamedValue element (if necessary)
00102   return this->add_element (flags);
00103 }
00104 
00105 // add an element and just initialize its flags and name
00106 CORBA::NamedValue_ptr
00107 CORBA::NVList::add_item (const char *name, CORBA::Flags flags)
00108 {
00109   // call the helper to allocate a NamedValue element
00110   CORBA::NamedValue_ptr nv = this->add_element (flags);
00111 
00112   if (nv)
00113     {
00114       // now initialize the fields
00115       nv->name_ = CORBA::string_dup (name);
00116       return nv;
00117     }
00118   else
00119     {
00120       return 0;
00121     }
00122 }
00123 
00124 // add a value. If necessary, increment the list
00125 CORBA::NamedValue_ptr
00126 CORBA::NVList::add_value (const char *name,
00127                           const CORBA::Any &value,
00128                           CORBA::Flags flags)
00129 {
00130   // Call the helper to allocate a NamedValue element.
00131   CORBA::NamedValue_ptr nv = this->add_element (flags);
00132 
00133   if (nv)
00134     {
00135       nv->name_ = CORBA::string_dup (name);
00136 
00137       // With the original Any implementation, we had alternate
00138       // paths for the assignment based on the IN_COPY_VALUE flag.
00139       // Now that the Any's contained Any_Impl is refcounted, the
00140       // distinction between the ORB "copying" or "borrowing" the
00141       // memory is irrelevant. The IN_COPY_VALUE flag was not
00142       // checked anywhere else in the ORB anyway.
00143       nv->any_ = value;
00144       return nv;
00145     }
00146   else
00147     {
00148       return 0;
00149     }
00150 }
00151 
00152 // add an element and just initialize its flags and name
00153 CORBA::NamedValue_ptr
00154 CORBA::NVList::add_item_consume (char *name, CORBA::Flags flags)
00155 {
00156 
00157   // call the helper to allocate a NamedValue element
00158   CORBA::NamedValue_ptr nv = this->add_element (flags);
00159 
00160   if (nv)
00161     {
00162       // now initialize the fields
00163 
00164       // consume the name
00165       nv->name_ = name;
00166       return nv;
00167     }
00168   else
00169     {
00170       return 0;
00171     }
00172 }
00173 
00174 // add a value. If necessary, increment the list
00175 CORBA::NamedValue_ptr
00176 CORBA::NVList::add_value_consume (char * name,
00177                                   CORBA::Any * value,
00178                                   CORBA::Flags flags)
00179 {
00180   // call the helper to allocate a NamedValue element
00181   CORBA::NamedValue_ptr nv = this->add_element (flags);
00182 
00183   if (nv)
00184     {
00185       // now initialize the fields
00186 
00187       // consume name
00188       nv->name_ = name;
00189 
00190       // consume the value @@ (ASG) have we? we may need to destroy
00191       // the in parameter
00192       nv->any_ = *value;
00193       return nv;
00194     }
00195   else
00196     {
00197       return 0;
00198     }
00199 }
00200 
00201 //CORBA::Status
00202 void
00203 CORBA::NVList::remove (CORBA::ULong /* n */)
00204 {
00205   // not implemented
00206   // @@ (ASG) - TODO
00207 }
00208 
00209 // Helper method
00210 CORBA::NamedValue_ptr
00211 CORBA::NVList::add_element (CORBA::Flags flags)
00212 {
00213   this->evaluate ();
00214 
00215   if (ACE_BIT_DISABLED (flags,
00216                         CORBA::ARG_IN | CORBA::ARG_OUT | CORBA::ARG_INOUT))
00217     {
00218       throw ::CORBA::BAD_PARAM ();
00219     }
00220 
00221   CORBA::NamedValue_ptr nv;
00222 
00223   // allocate a new NamedValue
00224   ACE_NEW_THROW_EX (nv,
00225                     CORBA::NamedValue,
00226                     CORBA::NO_MEMORY ());
00227 
00228   // set the flags and enqueue in the queue
00229   nv->flags_ = flags;
00230 
00231   if (this->values_.enqueue_tail (nv) == -1)
00232     {
00233       delete nv;
00234       return 0;
00235     }
00236 
00237   this->max_++;
00238   return nv; // success
00239 }
00240 
00241 // return the item at location n
00242 CORBA::NamedValue_ptr
00243 CORBA::NVList::item (CORBA::ULong n)
00244 {
00245   this->evaluate ();
00246 
00247   if (n >= this->max_)
00248     {
00249       throw ::CORBA::Bounds ();
00250     }
00251 
00252   CORBA::NamedValue_ptr *nv = 0;
00253 
00254   this->values_.get (nv, n);
00255   return *nv;
00256 }
00257 
00258 void
00259 CORBA::NVList::_tao_incoming_cdr (TAO_InputCDR &cdr,
00260                                   int flag,
00261                                   bool &lazy_evaluation)
00262 {
00263   // If the list is empty then using lazy evaluation is the only
00264   // choice.
00265   // @@ There are other cases where we can use lazy evaluation, for
00266   //    example if the list is not empty but the anys own all their
00267   //    objects.
00268   if (lazy_evaluation == false && this->max_ == 0)
00269     {
00270       lazy_evaluation = true;
00271     }
00272 
00273   if (lazy_evaluation == false)
00274     {
00275       this->_tao_decode (cdr, flag);
00276       return;
00277     }
00278 
00279   ACE_GUARD (TAO_SYNCH_MUTEX, ace_mon, this->lock_);
00280 
00281   if (this->incoming_ != 0)
00282     {
00283       delete this->incoming_;
00284       this->incoming_ = 0;
00285     }
00286 
00287   ACE_NEW (this->incoming_, TAO_InputCDR (cdr));
00288   this->incoming_flag_ = flag;
00289 }
00290 
00291 void
00292 CORBA::NVList::_tao_encode (TAO_OutputCDR &cdr, int flag)
00293 {
00294   ACE_GUARD (TAO_SYNCH_MUTEX,
00295              ace_mon,
00296              this->lock_);
00297 
00298   if (this->incoming_ != 0)
00299     {
00300       if (this->max_ == 0)
00301         {
00302           // The list is empty aggresively reduce copies and just send
00303           // the CDR stream, we assume that
00304           // TAO_Server_Request::init_reply
00305           // has inserted appropiated padding already to make this
00306           // operation correct
00307           cdr.write_octet_array_mb (this->incoming_->start ());
00308           return;
00309         }
00310 
00311       // Then unmarshal each "in" and "inout" parameter.
00312       ACE_Unbounded_Queue_Iterator<CORBA::NamedValue_ptr> i (this->values_);
00313 
00314       for (i.first (); !i.done (); i.advance ())
00315         {
00316           CORBA::NamedValue_ptr *item = 0;
00317           (void) i.next (item);
00318 
00319           CORBA::NamedValue_ptr nv = *item;
00320 
00321           if (ACE_BIT_DISABLED (nv->flags (), flag))
00322             {
00323               continue;
00324             }
00325 
00326           if (TAO_debug_level > 3)
00327             {
00328               const char* arg = nv->name ();
00329 
00330               if (arg == 0)
00331                 {
00332                   arg = "(nil)";
00333                 }
00334 
00335               ACE_DEBUG ((LM_DEBUG,
00336                           ACE_TEXT ("NVList::_tao_encode - parameter <%s>\n"),
00337                           ACE_TEXT_CHAR_TO_TCHAR (arg)));
00338             }
00339           CORBA::TypeCode_ptr tc = nv->value ()->_tao_get_typecode ();
00340           (void) TAO_Marshal_Object::perform_append (tc,
00341                                                      this->incoming_,
00342                                                      &cdr);
00343         }
00344 
00345       delete this->incoming_;
00346       this->incoming_ = 0;
00347       return;
00348     }
00349 
00350   // The list is already evaluated, we cannot optimize the copies, go
00351   // ahead with the slow way to do things.
00352 
00353   // Then marshal each "in" and "inout" parameter.
00354   ACE_Unbounded_Queue_Iterator<CORBA::NamedValue_ptr> i (this->values_);
00355 
00356   for (i.first (); !i.done (); i.advance ())
00357     {
00358       CORBA::NamedValue_ptr *item = 0;
00359       (void) i.next (item);
00360 
00361       CORBA::NamedValue_ptr nv = *item;
00362 
00363       if (ACE_BIT_DISABLED (nv->flags (), flag))
00364         {
00365           continue;
00366         }
00367 
00368       nv->value ()->impl ()->marshal_value (cdr);
00369     }
00370 }
00371 
00372 void
00373 CORBA::NVList::_tao_decode (TAO_InputCDR &incoming, int flag)
00374 {
00375   if (TAO_debug_level > 3)
00376     {
00377       ACE_DEBUG ((LM_DEBUG,
00378                   ACE_TEXT ("TAO (%P|%t) : NVList::_tao_decode\n")));
00379     }
00380 
00381   // Then unmarshal each "in" and "inout" parameter.
00382   ACE_Unbounded_Queue_Iterator<CORBA::NamedValue_ptr> i (this->values_);
00383 
00384   for (i.first (); !i.done (); i.advance ())
00385     {
00386       CORBA::NamedValue_ptr *item = 0;
00387       (void) i.next (item);
00388 
00389       CORBA::NamedValue_ptr nv = *item;
00390 
00391       // check if it is an in or inout parameter
00392       // @@ this is where we assume that the NVList is coming from
00393       //    a Server-side request, we could probably handle both
00394       //    cases with a flag, but there is no clear need for that.
00395       if (ACE_BIT_DISABLED (nv->flags (), flag))
00396         {
00397           continue;
00398         }
00399 
00400       if (TAO_debug_level > 3)
00401         {
00402           ACE_DEBUG ((LM_DEBUG,
00403                       ACE_TEXT ("TAO (%P|%t) : NVList::_tao_decode - %s\n"),
00404                       ACE_TEXT_CHAR_TO_TCHAR (nv->name ()? nv->name () : "(no name given)" )));
00405         }
00406 
00407       CORBA::Any_ptr any = nv->value ();
00408       any->impl ()->_tao_decode (incoming
00409                                 );
00410     }
00411 }
00412 
00413 ptrdiff_t
00414 CORBA::NVList::_tao_target_alignment (void)
00415 {
00416   ACE_GUARD_RETURN (TAO_SYNCH_MUTEX,
00417                     ace_mon,
00418                     this->lock_,
00419                     ACE_CDR::MAX_ALIGNMENT);
00420 
00421   if (this->incoming_ == 0)
00422     {
00423       return ACE_CDR::MAX_ALIGNMENT;
00424     }
00425 
00426   const char* rd = this->incoming_->start ()->rd_ptr ();
00427   ptrdiff_t t = ptrdiff_t (rd) % ACE_CDR::MAX_ALIGNMENT;
00428 
00429   if (t < 0)
00430     {
00431       t += ACE_CDR::MAX_ALIGNMENT;
00432     }
00433 
00434   return t;
00435 }
00436 
00437 void
00438 CORBA::NVList::evaluate (void)
00439 {
00440   ACE_GUARD (TAO_SYNCH_MUTEX, ace_mon, this->lock_);
00441 
00442   if (this->incoming_ == 0)
00443     {
00444       return;
00445     }
00446 
00447   auto_ptr<TAO_InputCDR> incoming (this->incoming_);
00448   this->incoming_ = 0;
00449 
00450   this->_tao_decode (*(incoming.get ()),
00451                      this->incoming_flag_
00452                     );
00453 }
00454 
00455 CORBA::Boolean
00456 CORBA::NVList::_lazy_has_arguments (void) const
00457 {
00458   if (this->incoming_ != 0)
00459     {
00460       return this->incoming_->length () <= 1 ? false : true;
00461     }
00462   else
00463     {
00464       return this->count () <= 1 ? false : true;
00465     }
00466 }
00467 
00468 TAO_END_VERSIONED_NAMESPACE_DECL

Generated on Sun Jan 27 13:21:06 2008 for TAO_AnyTypeCode by doxygen 1.3.6