//------------------------------------------------------------------------------ // Copyright (c) 2011-2017 by European Organization for Nuclear Research (CERN) // Author: Krzysztof Jamrog , // Michal Simon //------------------------------------------------------------------------------ // This file is part of the XRootD software suite. // // XRootD is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // XRootD is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with XRootD. If not, see . // // In applying this licence, CERN does not waive the privileges and immunities // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. //------------------------------------------------------------------------------ #ifndef SRC_XRDCL_XRDCLFWD_HH_ #define SRC_XRDCL_XRDCLFWD_HH_ #include #include namespace XrdCl { //---------------------------------------------------------------------------- //! Helper class for storing forwarded values //! Allocates memory respectively aligned for T but constructs the object //! only on assignment. //! //! @arg T : type of the value //---------------------------------------------------------------------------- template struct FwdStorage { //-------------------------------------------------------------------------- //! Default constructor //-------------------------------------------------------------------------- FwdStorage() : ptr( nullptr ) { } //-------------------------------------------------------------------------- //! Constructor from T. //! @param value : value for forwarding //-------------------------------------------------------------------------- FwdStorage( const T &value ) : ptr( new( &storage.memory ) T( value ) ) { } //-------------------------------------------------------------------------- //! Assignment operator from T //! @param value : value for forwarding //-------------------------------------------------------------------------- FwdStorage& operator=( const T &value ) { ptr = new( &storage.memory ) T( value ); return *this; } //-------------------------------------------------------------------------- //! Move constructor from T. //! @param value : value for forwarding //-------------------------------------------------------------------------- FwdStorage( T && value ) : ptr( new( &storage.memory ) T( std::move( value ) ) ) { } //-------------------------------------------------------------------------- //! Move assignment operator from T //! @param value : value for forwarding //-------------------------------------------------------------------------- FwdStorage& operator=( T && value ) { ptr = new( &storage.memory ) T( std::move( value ) ); return *this; } //-------------------------------------------------------------------------- //! Destructor //-------------------------------------------------------------------------- ~FwdStorage() { if( ptr ) ptr->~T(); } //-------------------------------------------------------------------------- //! Memory for the value //-------------------------------------------------------------------------- union Memory { //------------------------------------------------------------------------ //! Make sure the default constructor of T won't be called //------------------------------------------------------------------------ Memory() { } //------------------------------------------------------------------------ //! Make sure the destrutor of T won't be called //------------------------------------------------------------------------ ~Memory() { } //------------------------------------------------------------------------ //! The memory for storing forwarded value //------------------------------------------------------------------------ T memory; }; //-------------------------------------------------------------------------- //! The memory for storying forwarded value //-------------------------------------------------------------------------- Memory storage; //-------------------------------------------------------------------------- //! Pointer to the forwarded value //-------------------------------------------------------------------------- T *ptr; }; //---------------------------------------------------------------------------- //! A helper class for forwarding arguments between operations. //! In practice it's a wrapper around std::shared_ptr using FwdStorage as //! underlying memory. //! //! @arg T : type of forwarded value //---------------------------------------------------------------------------- template struct Fwd : protected std::shared_ptr> { //------------------------------------------------------------------------ //! Default constructor. //! //! Allocates memory for the underlying value object without callying //! its constructor. //------------------------------------------------------------------------ Fwd() : std::shared_ptr>( std::make_shared>() ) { } //------------------------------------------------------------------------ //! Copy constructor. //------------------------------------------------------------------------ Fwd( const Fwd &fwd ) : std::shared_ptr>( fwd ) { } //------------------------------------------------------------------------ //! Move constructor. //------------------------------------------------------------------------ Fwd( Fwd && fwd ) : std::shared_ptr>( std::move( fwd ) ) { } //------------------------------------------------------------------------ //! Initialize from shared_ptr //------------------------------------------------------------------------ Fwd( std::shared_ptr> && ptr ) : std::shared_ptr>( std::move( ptr ) ) { } //------------------------------------------------------------------------ //! Constructor from value //------------------------------------------------------------------------ explicit Fwd( const T &value ) { *this->get() = value; } //------------------------------------------------------------------------ //! Move construct from value //------------------------------------------------------------------------ explicit Fwd( T &&value ) { *this->get() = std::move( value ); } //------------------------------------------------------------------------ //! Assignment operator. //! //! @param value : forwarded value //! @throws : std::logic_error //------------------------------------------------------------------------ Fwd& operator=( const T &value ) { *this->get() = value; return *this; } //------------------------------------------------------------------------ //! Move assignment operator. //! //! @param value : forwarded value //! @throws : std::logic_error //------------------------------------------------------------------------ Fwd& operator=( T && value ) { *this->get() = std::move( value ); return *this; } //------------------------------------------------------------------------ //! Dereferencing operator. Note if Fwd has not been assigned with //! a value this will trigger an exception //! //! @return : reference to the underlying value //! @throws : std::logic_error //------------------------------------------------------------------------ T& operator*() const { if( !bool( this->get()->ptr ) ) throw std::logic_error( "XrdCl::Fwd contains no value!" ); return *this->get()->ptr; } //------------------------------------------------------------------------ //! Dereferencing member operator. Note if Fwd has not been assigned with //! a value this will trigger an exception //! //! @return : pointer to the underlying value //! @throws : std::logic_error //------------------------------------------------------------------------ T* operator->() const { if( !bool( this->get()->ptr ) ) throw std::logic_error( "XrdCl::Fwd contains no value!" ); return this->get()->ptr; } //------------------------------------------------------------------------ //! Check if it contains a valid value //------------------------------------------------------------------------ bool Valid() const { return bool( this->get()->ptr ); } }; //-------------------------------------------------------------------------- // Utility function for creating forwardable objects //-------------------------------------------------------------------------- template inline std::shared_ptr> make_fwd( Args&&... args ) { return std::make_shared>( std::forward( args )... ); } } #endif /* SRC_XRDCL_XRDCLFWD_HH_ */