Collage  1.5.0
High-performance C++ library for developing object-oriented distributed applications.
dataIStream.ipp
1 
2 /* Copyright (c) 2012-2016, Daniel Nachbaur <danielnachbaur@gmail.com>
3  * Stefan.Eilemann@epfl.ch
4  *
5  * This library is free software; you can redistribute it and/or modify it under
6  * the terms of the GNU Lesser General Public License version 2.1 as published
7  * by the Free Software Foundation.
8  *
9  * This library is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11  * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12  * details.
13  *
14  * You should have received a copy of the GNU Lesser General Public License
15  * along with this library; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17  */
18 
19 #include <co/object.h>
20 #include <co/objectVersion.h>
21 #include <servus/serializable.h> // used inline
22 
23 namespace co
24 {
28 template<> inline DataIStream& DataIStream::operator >> ( std::string& str )
29 {
30  uint64_t nElems = 0;
31  *this >> nElems;
32  const uint64_t maxElems = getRemainingBufferSize();
33  LBASSERTINFO( nElems <= maxElems,
34  nElems << " > " << maxElems );
35  if( nElems == 0 )
36  str.clear();
37  else if( nElems <= maxElems )
38  str.assign( static_cast< const char* >( getRemainingBuffer(nElems)),
39  size_t( nElems ));
40  else
41  str.assign(
42  static_cast< const char* >( getRemainingBuffer(maxElems)),
43  size_t( maxElems ));
44  return *this;
45 }
46 
48 template<> inline DataIStream& DataIStream::operator >> ( Object*& object )
49 {
50  ObjectVersion data;
51  *this >> data;
52  LBASSERT( object->getID() == data.identifier );
53  object->sync( data.version );
54  return *this;
55 }
56 
58 template< class T >
59 void DataIStream::_readSerializable( T& object, const boost::true_type& )
60 {
61  const size_t size = read< size_t >();
62  object.fromBinary( getRemainingBuffer( size ), size );
63 }
64 
66 template< class T >
67 void DataIStream::_readArray( Array< T > array, const boost::true_type& )
68 {
69  _read( array.data, array.getNumBytes( ));
70  _swap( array );
71 }
72 
74 template< class T >
75 void DataIStream::_readArray( Array< T > array, const boost::false_type& )
76 {
77  for( size_t i = 0; i < array.num; ++i )
78  *this >> array.data[ i ];
79 }
80 
81 template<> inline
82 void DataIStream::_readArray( Array< void > array, const boost::false_type& )
83 {
84  _read( array.data, array.getNumBytes( ));
85 }
86 
87 template< class T > inline DataIStream&
88 DataIStream::operator >> ( lunchbox::RefPtr< T >& ptr )
89 {
90  T* object = 0;
91  *this >> object;
92  ptr = object;
93  return *this;
94 }
95 
96 template< class T > inline DataIStream&
97 DataIStream::operator >> ( lunchbox::Buffer< T >& buffer )
98 {
99  uint64_t nElems = 0;
100  *this >> nElems;
101  LBASSERTINFO( nElems < LB_BIT48,
102  "Out-of-sync co::DataIStream: " << nElems << " elements?" );
103  buffer.resize( nElems );
104  return *this >> Array< T >( buffer.getData(), nElems );
105 }
106 
107 
108 template< class T > inline DataIStream&
109 DataIStream::operator >> ( std::vector< T >& value )
110 {
111  uint64_t nElems = 0;
112  *this >> nElems;
113  value.resize( nElems );
114  for( uint64_t i = 0; i < nElems; ++i )
115  *this >> value[i];
116  return *this;
117 }
118 
119 template< class K, class V > inline DataIStream&
120 DataIStream::operator >> ( std::map< K, V >& map )
121 {
122  map.clear();
123  uint64_t nElems = 0;
124  *this >> nElems;
125  for( uint64_t i = 0; i < nElems; ++i )
126  {
127  typename std::map< K, V >::key_type key;
128  typename std::map< K, V >::mapped_type value;
129  *this >> key >> value;
130  map.insert( std::make_pair( key, value ));
131  }
132  return *this;
133 }
134 
135 template< class T > inline DataIStream&
136 DataIStream::operator >> ( std::set< T >& value )
137 {
138  value.clear();
139  uint64_t nElems = 0;
140  *this >> nElems;
141  for( uint64_t i = 0; i < nElems; ++i )
142  {
143  T item;
144  *this >> item;
145  value.insert( item );
146  }
147  return *this;
148 }
149 
150 template< class K, class V > inline DataIStream&
151 DataIStream::operator >> ( stde::hash_map< K, V >& map )
152 {
153  map.clear();
154  uint64_t nElems = 0;
155  *this >> nElems;
156  for( uint64_t i = 0; i < nElems; ++i )
157  {
158  typename stde::hash_map< K, V >::key_type key;
159  typename stde::hash_map< K, V >::mapped_type value;
160  *this >> key >> value;
161  map.insert( std::make_pair( key, value ));
162  }
163  return *this;
164 }
165 
166 template< class T > inline DataIStream&
167 DataIStream::operator >> ( stde::hash_set< T >& value )
168 {
169  value.clear();
170  uint64_t nElems = 0;
171  *this >> nElems;
172  for( uint64_t i = 0; i < nElems; ++i )
173  {
174  T item;
175  *this >> item;
176  value.insert( item );
177  }
178  return *this;
179 }
180 
181 namespace
182 {
183 class ObjectFinder
184 {
185 public:
186  explicit ObjectFinder( const uint128_t& id ) : _id( id ) {}
187  bool operator()( co::Object* candidate )
188  { return candidate->getID() == _id; }
189 
190 private:
191  const uint128_t _id;
192 };
193 }
194 
195 template< typename O, typename C > inline void
196 DataIStream::deserializeChildren( O* object, const std::vector< C* >& old_,
197  std::vector< C* >& result )
198 {
199  ObjectVersions versions;
200  *this >> versions;
201  std::vector< C* > old = old_;
202 
203  // rebuild vector from serialized list
204  result.clear();
205  for( ObjectVersions::const_iterator i = versions.begin();
206  i != versions.end(); ++i )
207  {
208  const ObjectVersion& version = *i;
209 
210  if( version.identifier == uint128_t( ))
211  {
212  result.push_back( 0 );
213  continue;
214  }
215 
216  typename std::vector< C* >::iterator j =
217  lunchbox::find_if( old, ObjectFinder( version.identifier ));
218 
219  if( j == old.end( )) // previously unknown child
220  {
221  C* child = 0;
222  object->create( &child );
223  LocalNodePtr localNode = object->getLocalNode();
224  LBASSERT( child );
225  LBASSERT( !object->isMaster( ));
226 
227  LBCHECK( localNode->mapObject( child, version ));
228  result.push_back( child );
229  }
230  else
231  {
232  C* child = *j;
233  old.erase( j );
234  if( object->isMaster( ))
235  child->sync( VERSION_HEAD );
236  else
237  child->sync( version.version );
238 
239  result.push_back( child );
240  }
241  }
242 
243  while( !old.empty( )) // removed children
244  {
245  C* child = old.back();
246  old.pop_back();
247  if( !child )
248  continue;
249 
250  if( child->isAttached() && !child->isMaster( ))
251  {
252  LocalNodePtr localNode = object->getLocalNode();
253  localNode->unmapObject( child );
254  }
255  object->release( child );
256  }
257 }
261 template<> inline DataIStream&
262 DataIStream::operator >> ( std::vector< uint8_t >& value )
263 { return _readFlatVector( value );}
264 
266 template<> inline DataIStream&
267 DataIStream::operator >> ( std::vector< uint16_t >& value )
268 { return _readFlatVector( value ); }
269 
271 template<> inline DataIStream&
272 DataIStream::operator >> ( std::vector< int16_t >& value )
273 { return _readFlatVector( value ); }
274 
276 template<> inline DataIStream&
277 DataIStream::operator >> ( std::vector< uint32_t >& value )
278 { return _readFlatVector( value ); }
279 
281 template<> inline DataIStream&
282 DataIStream::operator >> ( std::vector< int32_t >& value )
283 { return _readFlatVector( value ); }
284 
286 template<> inline DataIStream&
287 DataIStream::operator >> ( std::vector< uint64_t>& value )
288 { return _readFlatVector( value ); }
289 
291 template<> inline DataIStream&
292 DataIStream::operator >> ( std::vector< int64_t >& value )
293 { return _readFlatVector( value ); }
294 
296 template<> inline DataIStream&
297 DataIStream::operator >> ( std::vector< float >& value )
298 { return _readFlatVector( value ); }
299 
301 template<> inline DataIStream&
302 DataIStream::operator >> ( std::vector< double >& value )
303 { return _readFlatVector( value ); }
304 
306 template<> inline DataIStream&
307 DataIStream::operator >> ( std::vector< ObjectVersion >& value )
308 { return _readFlatVector( value ); }
310 }
CO_API const uint128_t & getID() const
A distributed object.
Definition: object.h:45
lunchbox::RefPtr< LocalNode > LocalNodePtr
A reference pointer for LocalNode pointers.
Definition: types.h:89
A helper struct bundling an object identifier and version.
Definition: objectVersion.h:47
uint128_t identifier
the object identifier
Definition: objectVersion.h:95
Object-oriented network library.
Definition: barrier.h:27
CO_API const void * getRemainingBuffer(const uint64_t size)
DataIStream & operator>>(T &value)
Read a plain data item.
Definition: dataIStream.h:63
uint128_t version
the object version
Definition: objectVersion.h:96
CO_API uint64_t getRemainingBufferSize()
A std::istream-like input data stream for binary data.
Definition: dataIStream.h:41