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