1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-01-26 03:52:01 +02:00

Fixed handling cyclic pointers in serializer.

This commit is contained in:
Michał W. Urbańczyk 2010-05-15 02:26:49 +00:00
parent 26d0483465
commit 88fab9c669
2 changed files with 30 additions and 35 deletions

View File

@ -124,15 +124,12 @@ connerror1:
//delete socket;
throw std::string("Can't establish connection :(");
}
CConnection::CConnection(
boost::asio::basic_stream_socket<boost::asio::ip::tcp , boost::asio::stream_socket_service<boost::asio::ip::tcp> > * Socket,
std::string Name )
:socket(Socket),io_service(&Socket->io_service()), name(Name)//, send(this), rec(this)
CConnection::CConnection(TSocket * Socket, std::string Name )
:socket(Socket),io_service(&Socket->io_service()), name(Name)//, send(this), rec(this)
{
init();
}
CConnection::CConnection(boost::asio::basic_socket_acceptor<boost::asio::ip::tcp,boost::asio::socket_acceptor_service<boost::asio::ip::tcp> > * acceptor,
boost::asio::io_service *Io_service, std::string Name)
CConnection::CConnection(TAcceptor * acceptor, boost::asio::io_service *Io_service, std::string Name)
: name(Name)//, send(this), rec(this)
{
boost::system::error_code error = asio::error::host_not_found;

View File

@ -223,12 +223,7 @@ struct SerializationLevel
static const int value = SerializationLevel::type::value;
};
class DLL_EXPORT CSerializerBase
{
public:
};
class DLL_EXPORT CSaverBase : public virtual CSerializerBase
class DLL_EXPORT CSaverBase
{
};
@ -434,20 +429,20 @@ public:
class DLL_EXPORT CLoaderBase : public virtual CSerializerBase
class DLL_EXPORT CLoaderBase
{};
class CBasicPointerLoader
{
public:
virtual void loadPtr(CLoaderBase &ar, void *data) const =0; //data is pointer to the ACTUAL POINTER
virtual void loadPtr(CLoaderBase &ar, void *data, ui32 pid) const =0; //data is pointer to the ACTUAL POINTER
virtual ~CBasicPointerLoader(){}
};
template <typename Serializer, typename T> class CPointerLoader : public CBasicPointerLoader
{
public:
void loadPtr(CLoaderBase &ar, void *data) const //data is pointer to the ACTUAL POINTER
void loadPtr(CLoaderBase &ar, void *data, ui32 pid) const //data is pointer to the ACTUAL POINTER
{
Serializer &s = static_cast<Serializer&>(ar);
T *&ptr = *static_cast<T**>(data);
@ -455,7 +450,7 @@ public:
//create new object under pointer
typedef typename boost::remove_pointer<T>::type npT;
ptr = new npT;
s.ptrAllocated(ptr, pid);
//T is most derived known type, it's time to call actual serialize
ptr->serialize(s,version);
}
@ -569,11 +564,10 @@ public:
}
ui32 pid = -1; //pointer id (or maybe rather pointee id)
std::map<ui32, void*>::iterator i = loadedPointers.end();
if(smartPointerSerialization)
{
*this >> pid; //get the id
i = loadedPointers.find(pid); //lookup
std::map<ui32, void*>::iterator i = loadedPointers.find(pid); //lookup
if(i != loadedPointers.end())
{
@ -586,29 +580,34 @@ public:
//get type id
ui16 tid;
*this >> tid;
This()->loadPointerHlp(tid, data);
if(smartPointerSerialization && i == loadedPointers.end())
loadedPointers[pid] = (void*)data; //add loaded pointer to our lookup map; cast is to avoid errors with const T* pt
This()->loadPointerHlp(tid, data, pid);
}
//that part of ptr deserialization was extracted to allow customization of its behavior in derived classes
template <typename T>
void loadPointerHlp( ui16 tid, T & data )
void loadPointerHlp( ui16 tid, T & data, ui32 pid )
{
if(!tid)
{
typedef typename boost::remove_pointer<T>::type npT;
typedef typename boost::remove_const<npT>::type ncpT;
data = new ncpT;
ptrAllocated(data, pid);
*this >> *data;
}
else
{
loaders[tid]->loadPtr(*this,&data);
loaders[tid]->loadPtr(*this,&data, pid);
}
}
template <typename T>
void ptrAllocated(const T *ptr, ui32 pid)
{
if(smartPointerSerialization && pid != -1)
loadedPointers[pid] = (void*)ptr; //add loaded pointer to our lookup map; cast is to avoid errors with const T* pt
}
template <typename T>
void loadSerializable(std::vector<T> &data)
{
@ -706,6 +705,9 @@ public:
void openNextFile(const std::string &fname, bool requireLatest);
};
typedef boost::asio::basic_stream_socket < boost::asio::ip::tcp , boost::asio::stream_socket_service<boost::asio::ip::tcp> > TSocket;
typedef boost::asio::basic_socket_acceptor<boost::asio::ip::tcp, boost::asio::socket_acceptor_service<boost::asio::ip::tcp> > TAcceptor;
class DLL_EXPORT CConnection
:public CISer<CConnection>, public COSer<CConnection>
{
@ -715,21 +717,17 @@ class DLL_EXPORT CConnection
void init();
public:
boost::mutex *rmx, *wmx; // read/write mutexes
boost::asio::basic_stream_socket < boost::asio::ip::tcp , boost::asio::stream_socket_service<boost::asio::ip::tcp> > * socket;
TSocket * socket;
bool logging;
bool connected;
bool myEndianess, contactEndianess; //true if little endian, if ednianess is different we'll have to revert recieved multi-byte vars
boost::asio::io_service *io_service;
std::string name; //who uses this connection
CConnection
(std::string host, std::string port, std::string Name);
CConnection
(boost::asio::basic_socket_acceptor<boost::asio::ip::tcp, boost::asio::socket_acceptor_service<boost::asio::ip::tcp> > * acceptor,
boost::asio::io_service *Io_service, std::string Name);
CConnection
(boost::asio::basic_stream_socket < boost::asio::ip::tcp , boost::asio::stream_socket_service<boost::asio::ip::tcp> > * Socket,
std::string Name); //use immediately after accepting connection into socket
CConnection(std::string host, std::string port, std::string Name);
CConnection(TAcceptor * acceptor, boost::asio::io_service *Io_service, std::string Name);
CConnection(TSocket * Socket, std::string Name); //use immediately after accepting connection into socket
int write(const void * data, unsigned size);
int read(void * data, unsigned size);
void close();
@ -766,7 +764,7 @@ public:
{
static void invoke(CConnection &s, T &data, ui16 tid)
{
s.CISer<CConnection>::loadPointerHlp(tid, data);
s.CISer<CConnection>::loadPointerHlp(tid, data, -1);
}
};
template<typename T>
@ -799,7 +797,7 @@ public:
//"overload" loading pointer procedure
template <typename T>
void loadPointerHlp( ui16 tid, T & data )
void loadPointerHlp( ui16 tid, T & data, ui32 pid )
{
typedef typename
//if