mirror of
https://github.com/boostorg/utility.git
synced 2025-08-02 14:24:30 +02:00
Initial release.
[SVN r361]
This commit is contained in:
80
include/boost/utility/safe_assign.hpp
Normal file
80
include/boost/utility/safe_assign.hpp
Normal file
@@ -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 <typename Destination, typename Source>
|
||||
Destination& safe_assign(Destination& dest, const Source& src)
|
||||
{
|
||||
typedef aligned_storage<
|
||||
sizeof(Destination)
|
||||
, alignment_of<Destination>::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
|
101
include/boost/utility/safe_swap.hpp
Normal file
101
include/boost/utility/safe_swap.hpp
Normal file
@@ -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 <typename T>
|
||||
void safe_swap(T& lhs, T& rhs)
|
||||
{
|
||||
typedef aligned_storage<
|
||||
sizeof(T)
|
||||
, alignment_of<T>::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
|
Reference in New Issue
Block a user