mirror of
https://github.com/boostorg/serialization.git
synced 2026-02-01 08:52:08 +00:00
Support serialization in DLLS
Make thread-safe fix portable binary archives [SVN r43691]
This commit is contained in:
@@ -16,13 +16,15 @@
|
||||
#include <cassert>
|
||||
|
||||
// STL
|
||||
#include <set>
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
|
||||
// BOOST
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#define BOOST_SERIALIZATION_SOURCE
|
||||
#include <boost/serialization/singleton.hpp>
|
||||
|
||||
#define BOOST_SERIALIZATION_SOURCE
|
||||
#include <boost/serialization/extended_type_info.hpp>
|
||||
#include <boost/serialization/void_cast.hpp>
|
||||
@@ -31,300 +33,242 @@ namespace boost {
|
||||
namespace serialization {
|
||||
namespace void_cast_detail {
|
||||
|
||||
#if 0
|
||||
// registry of casting objects
|
||||
struct void_caster_compare
|
||||
{
|
||||
bool
|
||||
operator()(
|
||||
shared_ptr<const void_caster> lhs,
|
||||
shared_ptr<const void_caster> rhs ) const
|
||||
{
|
||||
if( lhs.get()->m_derived_type < rhs.get()->m_derived_type )
|
||||
const void_caster * lhs,
|
||||
const void_caster * rhs
|
||||
) const {
|
||||
if( lhs->m_derived < rhs->m_derived )
|
||||
return true;
|
||||
|
||||
if( rhs.get()->m_derived_type < lhs.get()->m_derived_type)
|
||||
return false;
|
||||
|
||||
if( lhs.get()->m_base_type < rhs.get()->m_base_type )
|
||||
if( lhs->m_base < rhs->m_base )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
struct null_deleter
|
||||
{
|
||||
void operator()(void const *) const
|
||||
{}
|
||||
};
|
||||
typedef std::set<const void_caster *, void_caster_compare> set_type;
|
||||
#endif
|
||||
|
||||
// it turns out that at least one compiler (msvc 6.0) doesn't guarentee
|
||||
// to destroy static objects in exactly the reverse sequence that they
|
||||
// are constructed. To guarentee this, use a singleton pattern
|
||||
class void_caster_registry
|
||||
{
|
||||
typedef shared_ptr<const void_caster> value_type;
|
||||
typedef std::set<value_type, void_caster_compare> set_type;
|
||||
set_type m_set;
|
||||
static void_caster_registry * m_self;
|
||||
static void_caster_registry *
|
||||
self(){
|
||||
if(NULL == m_self){
|
||||
static void_caster_registry instance;
|
||||
m_self = & instance;
|
||||
}
|
||||
return m_self;
|
||||
}
|
||||
void_caster_registry(){}
|
||||
public:
|
||||
~void_caster_registry(){
|
||||
m_self = 0;
|
||||
}
|
||||
typedef set_type::iterator iterator;
|
||||
typedef set_type::const_iterator const_iterator;
|
||||
static iterator
|
||||
begin() {
|
||||
return self()->m_set.begin();
|
||||
}
|
||||
static iterator
|
||||
end() {
|
||||
return self()->m_set.end();
|
||||
}
|
||||
static const_iterator
|
||||
find(void_caster * vcp){
|
||||
return self()->m_set.find(value_type(vcp, null_deleter()));
|
||||
}
|
||||
static std::pair<iterator, bool>
|
||||
insert(const value_type & vcp){
|
||||
return self()->m_set.insert(vcp);
|
||||
}
|
||||
static bool
|
||||
empty(){
|
||||
if(NULL == m_self)
|
||||
return true;
|
||||
return m_self->m_set.empty();
|
||||
}
|
||||
static void
|
||||
purge(const extended_type_info * eti);
|
||||
};
|
||||
typedef std::vector<const void_caster *> set_type;
|
||||
|
||||
void_caster_registry * void_caster_registry::m_self = NULL;
|
||||
typedef boost::serialization::singleton<set_type> void_caster_registry;
|
||||
|
||||
void
|
||||
void_caster_registry::purge(const extended_type_info * eti){
|
||||
if(NULL == m_self)
|
||||
return;
|
||||
if(! empty()){
|
||||
iterator i = m_self->m_set.begin();
|
||||
while(i != m_self->m_set.end()){
|
||||
// note that the erase might invalidate i so save it here
|
||||
iterator j = i++;
|
||||
if((*j)->includes(eti))
|
||||
m_self->m_set.erase(j);
|
||||
}
|
||||
}
|
||||
inline bool
|
||||
void_caster::operator==(void_caster const & rhs) const{
|
||||
if(m_derived != rhs.m_derived)
|
||||
return false;
|
||||
if(m_base != rhs.m_base)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
// implementation of void caster base class
|
||||
BOOST_SERIALIZATION_DECL(BOOST_PP_EMPTY())
|
||||
void_caster::void_caster(
|
||||
extended_type_info const & derived_type_,
|
||||
extended_type_info const & base_type_
|
||||
extended_type_info const & derived,
|
||||
extended_type_info const & base
|
||||
) :
|
||||
m_derived_type( derived_type_),
|
||||
m_base_type(base_type_)
|
||||
m_derived(derived),
|
||||
m_base(base)
|
||||
{}
|
||||
|
||||
BOOST_SERIALIZATION_DECL(BOOST_PP_EMPTY())
|
||||
void_caster::~void_caster(){}
|
||||
|
||||
bool
|
||||
void_caster::includes(const extended_type_info * eti) const {
|
||||
return & m_derived_type == eti || & m_base_type == eti;
|
||||
BOOST_SERIALIZATION_DECL(void)
|
||||
void_caster::static_register() const {
|
||||
void_caster_registry::get_mutable_instance().push_back(this);
|
||||
// to do - add new void_caster_derived entries
|
||||
// which can be generated by adding this new primitive
|
||||
/*
|
||||
while(){
|
||||
if(!extend_down(this)
|
||||
&& !extend_up(this))
|
||||
break;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
void BOOST_SERIALIZATION_DECL(BOOST_PP_EMPTY())
|
||||
void_caster::static_register(const void_caster * vcp)
|
||||
{
|
||||
void_caster_registry::insert(shared_ptr<const void_caster>(vcp, null_deleter()));
|
||||
BOOST_SERIALIZATION_DECL(void)
|
||||
void_caster::static_unregister() const {
|
||||
void_cast_detail::set_type & st
|
||||
= void_caster_registry::get_mutable_instance();
|
||||
void_cast_detail::set_type::iterator it;
|
||||
it = std::find(st.begin(), st.end(), this);
|
||||
assert(st.end() != it);
|
||||
st.erase(it);
|
||||
// to do - remove all void_caster_derived entries
|
||||
// which depend upon this primitive
|
||||
/*
|
||||
while(){
|
||||
if(!truncate_down(this)
|
||||
&& !truncate_up(this))
|
||||
break;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
#if 0
|
||||
// implementation of shortcut void caster
|
||||
class void_caster_derived : public void_caster
|
||||
{
|
||||
std::ptrdiff_t difference;
|
||||
virtual void const*
|
||||
upcast( void const* t ) const{
|
||||
return static_cast<const char*> ( t ) + difference;
|
||||
virtual void const *
|
||||
upcast(void const * const t) const{
|
||||
return static_cast<const char *> ( t ) + difference;
|
||||
}
|
||||
virtual void const*
|
||||
downcast( void const* t ) const{
|
||||
return static_cast<const char*> ( t ) - difference;
|
||||
virtual void const *
|
||||
downcast(void const * const t) const{
|
||||
return static_cast<const char *> ( t ) - difference;
|
||||
}
|
||||
public:
|
||||
void_caster_derived(
|
||||
extended_type_info const& derived_type_,
|
||||
extended_type_info const& base_type_,
|
||||
std::ptrdiff_t difference_
|
||||
extended_type_info const & derived,
|
||||
extended_type_info const & base,
|
||||
std::ptrdiff_t difference
|
||||
) :
|
||||
void_caster(derived_type_, base_type_),
|
||||
difference( difference_ )
|
||||
{}
|
||||
void_caster(derived, base),
|
||||
difference( difference )
|
||||
{
|
||||
this->static_register();
|
||||
}
|
||||
~void_caster_derived(){
|
||||
this->static_unregister();
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
// just used as a search key
|
||||
class void_caster_argument : public void_caster
|
||||
{
|
||||
virtual void const*
|
||||
upcast( void const* t ) const {
|
||||
virtual void const *
|
||||
upcast(void const * const t) const {
|
||||
assert(false);
|
||||
return NULL;
|
||||
}
|
||||
virtual void const*
|
||||
downcast( void const* t ) const {
|
||||
virtual void const *
|
||||
downcast( void const * const t) const {
|
||||
assert(false);
|
||||
return NULL;
|
||||
}
|
||||
public:
|
||||
void_caster_argument(
|
||||
extended_type_info const& derived_type_,
|
||||
extended_type_info const& base_type_
|
||||
extended_type_info const & derived,
|
||||
extended_type_info const & base
|
||||
) :
|
||||
void_caster(derived_type_, base_type_)
|
||||
void_caster(derived, base)
|
||||
{}
|
||||
~void_caster_argument(){};
|
||||
};
|
||||
|
||||
struct match {
|
||||
void_cast_detail::void_caster_argument const * const m_ca;
|
||||
|
||||
match(void_cast_detail::void_caster_argument const * const ca) :
|
||||
m_ca(ca)
|
||||
{}
|
||||
bool operator()(const void_cast_detail::void_caster * vc){
|
||||
return * vc == * m_ca;
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace void_cast_detail
|
||||
|
||||
void BOOST_SERIALIZATION_DECL(BOOST_PP_EMPTY())
|
||||
unregister_void_casts(extended_type_info *eti)
|
||||
{
|
||||
void_cast_detail::void_caster_registry::purge(eti);
|
||||
}
|
||||
|
||||
// Given a void *, assume that it really points to an instance of one type
|
||||
// and alter it so that it would point to an instance of a related type.
|
||||
// Return the altered pointer. If there exists no sequence of casts that
|
||||
// can transform from_type to to_type, return a NULL.
|
||||
|
||||
BOOST_SERIALIZATION_DECL(void const *)
|
||||
BOOST_SERIALIZATION_DECL(void const *)
|
||||
void_upcast(
|
||||
extended_type_info const & derived_type,
|
||||
extended_type_info const & base_type,
|
||||
void const * const t,
|
||||
bool top
|
||||
extended_type_info const & derived,
|
||||
extended_type_info const & base,
|
||||
void const * const t
|
||||
){
|
||||
// same types - trivial case
|
||||
if (derived_type == base_type)
|
||||
if (derived == base)
|
||||
return t;
|
||||
|
||||
// check to see if base/derived pair is found in the registry
|
||||
void_cast_detail::void_caster_argument ca(derived_type, base_type );
|
||||
void_cast_detail::void_caster_registry::const_iterator it;
|
||||
it = void_cast_detail::void_caster_registry::find( &ca );
|
||||
|
||||
const void * t_new = NULL;
|
||||
|
||||
// check to see if base/derived pair is found in the registry
|
||||
const void_cast_detail::set_type & s
|
||||
= void_cast_detail::void_caster_registry::get_const_instance();
|
||||
void_cast_detail::set_type::const_iterator it;
|
||||
void_cast_detail::void_caster_argument ca(derived, base);
|
||||
|
||||
it = std::find_if(
|
||||
s.begin(),
|
||||
s.end(),
|
||||
void_cast_detail::match(& ca)
|
||||
);
|
||||
|
||||
// if so
|
||||
if (it != void_cast_detail::void_caster_registry::end())
|
||||
if (s.end() != it)
|
||||
// we're done
|
||||
return (*it)->upcast(t);
|
||||
|
||||
// try to find a chain that gives us what we want
|
||||
for(
|
||||
it = void_cast_detail::void_caster_registry::begin();
|
||||
it != void_cast_detail::void_caster_registry::end();
|
||||
++it
|
||||
){
|
||||
for(it = s.begin(); it != s.end(); ++it){
|
||||
// if the current candidate doesn't cast to the desired target type
|
||||
if ((*it)->m_base_type == base_type){
|
||||
if((*it)->m_base == base){
|
||||
// if the current candidate casts from the desired source type
|
||||
if ((*it)->m_derived_type == derived_type){
|
||||
if ((*it)->m_derived == derived){
|
||||
// we have a base/derived match - we're done
|
||||
// cast to the intermediate type
|
||||
t_new = (*it)->upcast(t);
|
||||
break;
|
||||
}
|
||||
t_new = void_upcast(derived_type, (*it)->m_derived_type, t, false);
|
||||
if (NULL != t_new){
|
||||
t_new = (*it)->upcast(t_new);
|
||||
assert(NULL != t_new);
|
||||
if(top){
|
||||
// register the this pair so we will have to go through
|
||||
// keep this expensive search process more than once.
|
||||
void_cast_detail::void_caster * vcp =
|
||||
new void_cast_detail::void_caster_derived(
|
||||
derived_type,
|
||||
base_type,
|
||||
static_cast<const char*>(t_new) - static_cast<const char*>(t)
|
||||
);
|
||||
void_cast_detail::void_caster_registry::insert(
|
||||
shared_ptr<const void_cast_detail::void_caster>(vcp)
|
||||
);
|
||||
}
|
||||
break;
|
||||
return (*it)->upcast(t);
|
||||
}
|
||||
const void * t_new;
|
||||
t_new = void_upcast(derived, (*it)->m_derived, t);
|
||||
if(NULL != t_new)
|
||||
return (*it)->upcast(t_new);
|
||||
}
|
||||
}
|
||||
return t_new;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BOOST_SERIALIZATION_DECL(void const *)
|
||||
BOOST_SERIALIZATION_DECL(void const *)
|
||||
void_downcast(
|
||||
const extended_type_info & derived_type,
|
||||
const extended_type_info & base_type,
|
||||
const void * const t,
|
||||
bool top
|
||||
extended_type_info const & derived,
|
||||
extended_type_info const & base,
|
||||
void const * const t
|
||||
){
|
||||
// same types - trivial case
|
||||
if (derived_type == base_type)
|
||||
if (derived == base)
|
||||
return t;
|
||||
|
||||
// check to see if base/derived pair is found in the registry
|
||||
void_cast_detail::void_caster_argument ca(derived_type, base_type );
|
||||
void_cast_detail::void_caster_registry::const_iterator it;
|
||||
it = void_cast_detail::void_caster_registry::find( &ca );
|
||||
|
||||
// if so
|
||||
if (it != void_cast_detail::void_caster_registry::end())
|
||||
// we're done
|
||||
return (*it)->downcast(t);
|
||||
|
||||
const void * t_new = NULL;
|
||||
// check to see if base/derived pair is found in the registry
|
||||
const void_cast_detail::set_type & s
|
||||
= void_cast_detail::void_caster_registry::get_const_instance();
|
||||
void_cast_detail::set_type::const_iterator it;
|
||||
void_cast_detail::void_caster_argument ca(derived, base);
|
||||
|
||||
it = std::find_if(
|
||||
s.begin(),
|
||||
s.end(),
|
||||
void_cast_detail::match(& ca)
|
||||
);
|
||||
|
||||
// if so
|
||||
if (s.end() != it)
|
||||
// we're done
|
||||
return(*it)->downcast(t);
|
||||
|
||||
// try to find a chain that gives us what we want
|
||||
for(
|
||||
it = void_cast_detail::void_caster_registry::begin();
|
||||
it != void_cast_detail::void_caster_registry::end();
|
||||
++it
|
||||
){
|
||||
// if the current candidate doesn't casts from the desired target type
|
||||
if ((*it)->m_derived_type == derived_type){
|
||||
// if the current candidate casts to the desired source type
|
||||
if ((*it)->m_base_type == base_type){
|
||||
for(it = s.begin(); it != s.end(); ++it){
|
||||
// if the current candidate doesn't cast to the desired target type
|
||||
if ((*it)->m_derived == derived){
|
||||
// if the current candidate casts from the desired source type
|
||||
if ((*it)->m_base == base){
|
||||
// we have a base/derived match - we're done
|
||||
// cast to the intermediate type
|
||||
t_new = (*it)->downcast(t);
|
||||
break;
|
||||
}
|
||||
t_new = void_downcast((*it)->m_base_type, base_type, t, false);
|
||||
if (NULL != t_new){
|
||||
t_new = (*it)->downcast(t_new);
|
||||
assert(NULL != t_new);
|
||||
if(top){
|
||||
// register the this pair so we will have to go through
|
||||
// keep this expensive search process more than once.
|
||||
void_cast_detail::void_caster * vcp =
|
||||
new void_cast_detail::void_caster_derived(
|
||||
derived_type,
|
||||
base_type,
|
||||
static_cast<const char*>(t) - static_cast<const char*>(t_new)
|
||||
);
|
||||
void_cast_detail::void_caster_registry::insert(
|
||||
shared_ptr<const void_cast_detail::void_caster>(vcp)
|
||||
);
|
||||
}
|
||||
break;
|
||||
return (*it)->downcast(t);
|
||||
}
|
||||
const void * t_new;
|
||||
t_new = void_downcast((*it)->m_base, base, t);
|
||||
if(NULL != t_new)
|
||||
return (*it)->downcast(t_new);
|
||||
}
|
||||
}
|
||||
return t_new;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
} // namespace serialization
|
||||
|
||||
Reference in New Issue
Block a user