From df2aaaf1e8285565ab0b878ba888cf1527f31b90 Mon Sep 17 00:00:00 2001 From: Eric Friedman Date: Wed, 7 Aug 2002 03:03:25 +0000 Subject: [PATCH] Initial release. [SVN r361] --- include/boost/utility/safe_assign.hpp | 80 ++++++++++++++++++++ include/boost/utility/safe_swap.hpp | 101 ++++++++++++++++++++++++++ 2 files changed, 181 insertions(+) create mode 100644 include/boost/utility/safe_assign.hpp create mode 100644 include/boost/utility/safe_swap.hpp diff --git a/include/boost/utility/safe_assign.hpp b/include/boost/utility/safe_assign.hpp new file mode 100644 index 0000000..3e0c574 --- /dev/null +++ b/include/boost/utility/safe_assign.hpp @@ -0,0 +1,80 @@ +//----------------------------------------------------------------------------- +// boost utility/safe_assign.hpp header file +// See http://www.boost.org for updates, documentation, and revision history. +//----------------------------------------------------------------------------- +// +// Copyright (c) 2002 +// Eric Friedman +// +// Permission to use, copy, modify, distribute and sell this software +// and its documentation for any purpose is hereby granted without fee, +// provided that the above copyright notice appears in all copies and +// that both the copyright notice and this permission notice appear in +// supporting documentation. No representations are made about the +// suitability of this software for any purpose. It is provided "as is" +// without express or implied warranty. + +#ifndef BOOST_UTILITY_SAFE_ASSIGN_HPP +#define BOOST_UTILITY_SAFE_ASSIGN_HPP + +#include "boost/utility/addressof.hpp" +#include "boost/type_traits/alignment_of.hpp" + +// The following are new/in-progress headers or fixes to existing headers: +#include "boost/aligned_storage.hpp" + +namespace boost { + +// safe_assign +// Generic assignment w/ strong exception-safety guarantee. +// +// Rationale: +// safe_assign is more efficient than safe_swap for assignment. +// +// !WARNING! +// safe_assign CANNOT be safely used in the general case if the +// destination argument's data members may be accessed +// concurrently. +template +Destination& safe_assign(Destination& dest, const Source& src) +{ + typedef aligned_storage< + sizeof(Destination) + , alignment_of::value + > aligned_storage_t; + + // Cache (for convienence) the addresses of lhs and rhs using addressof: + Destination* address = boost::addressof(dest); + + // Now backup dest... + aligned_storage_t backup; + backup.memcpy_in(address); + + try + { + // ...and attempt to overwrite dest with a (possible converted) copy of src: + new(address) Destination(src); + } + catch (...) + { + // In case of failure, restore dest using backup, and rethrow: + backup.memcpy_out(address); + throw; + } + + // Since the copy succeeded, copy dest's new value off to the side, + // and (temporarily) restore dest's old value using backup: + aligned_storage_t new_value; + new_value.memcpy_in(address); + + // Now destroy dest (which currently contains its _old_ value)... + dest.~Destination(); + + // ...and finally copy in its new (assigned) value: + new_value.memcpy_out(address); + return dest; +} + +} // namespace boost + +#endif // BOOST_UTILITY_SAFE_ASSIGN_HPP diff --git a/include/boost/utility/safe_swap.hpp b/include/boost/utility/safe_swap.hpp new file mode 100644 index 0000000..2a41bf2 --- /dev/null +++ b/include/boost/utility/safe_swap.hpp @@ -0,0 +1,101 @@ +//----------------------------------------------------------------------------- +// boost utility/safe_swap.hpp header file +// See http://www.boost.org for updates, documentation, and revision history. +//----------------------------------------------------------------------------- +// +// Copyright (c) 2002 +// Eric Friedman +// +// Permission to use, copy, modify, distribute and sell this software +// and its documentation for any purpose is hereby granted without fee, +// provided that the above copyright notice appears in all copies and +// that both the copyright notice and this permission notice appear in +// supporting documentation. No representations are made about the +// suitability of this software for any purpose. It is provided "as is" +// without express or implied warranty. + +#ifndef BOOST_UTILITY_SAFE_SWAP_HPP +#define BOOST_UTILITY_SAFE_SWAP_HPP + +#include "boost/utility/addressof.hpp" +#include "boost/type_traits/alignment_of.hpp" + +// The following are new/in-progress headers or fixes to existing headers: +#include "boost/aligned_storage.hpp" + +namespace boost { + +// safe_swap +// Generic swap w/ strong exception-safety guarantee. +// +// !WARNING! +// safe_swap CANNOT be safely used in the general case if either +// argument's data members may be accessed concurrently. +template +void safe_swap(T& lhs, T& rhs) +{ + typedef aligned_storage< + sizeof(T) + , alignment_of::value + > aligned_storage_t; + + // Cache (for convienence) the addresses of lhs and rhs using addressof: + T* lhs_address = boost::addressof(lhs); + T* rhs_address = boost::addressof(rhs); + + // Now backup lhs... + aligned_storage_t lhs_backup; + lhs_backup.memcpy_in(lhs_address); + + try + { + // ...and attempt to overwrite lhs with a copy of rhs: + new(lhs_address) T(rhs); + } + catch (...) + { + // In event of error, restore lhs using backup, and rethrow: + lhs_backup.memcpy_out(lhs_address); + throw; + } + + // Since the copy succeeded, copy lhs's new value off to the side, + // and (temporarily) restore lhs's old value using backup: + aligned_storage_t lhs_new; + lhs_new.memcpy_in(lhs_address); + lhs_backup.memcpy_out(lhs_address); + + // Now backup rhs... + aligned_storage_t rhs_backup; + rhs_backup.memcpy_in(rhs_address); + + try + { + // ...and attempt to overwrite rhs with a copy of lhs: + new(rhs_address) T(lhs); + } + catch (...) + { + // In event of error, restore rhs using backup, and rethrow: + rhs_backup.memcpy_out(rhs_address); + throw; + } + + // Since the copy succeeded, copy rhs's new value off to the side, + // and (temporarily) restore rhs's old value using backup: + aligned_storage_t rhs_new; + rhs_new.memcpy_in(rhs_address); + rhs_backup.memcpy_out(rhs_address); + + // Now destroy lhs and rhs (which currently contain their _old_ values)... + lhs.~T(); + rhs.~T(); + + // ...and finally copy in their new (swapped) values: + lhs_new.memcpy_out(lhs_address); + rhs_new.memcpy_out(rhs_address); +} + +} // namespace boost + +#endif // BOOST_UTILITY_SAFE_SWAP_HPP