GraphLab: Distributed Graph-Parallel API  2.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
iarchive.hpp
1 /*
2  * Copyright (c) 2009 Carnegie Mellon University.
3  * All rights reserved.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing,
12  * software distributed under the License is distributed on an "AS
13  * IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
14  * express or implied. See the License for the specific language
15  * governing permissions and limitations under the License.
16  *
17  * For more about this software visit:
18  *
19  * http://www.graphlab.ml.cmu.edu
20  *
21  */
22 
23 
24 #ifndef GRAPHLAB_SERIALIZE_HPP
25 #include <graphlab/serialization/serialize.hpp>
26 
27 #else
28 
29 
30 #ifndef GRAPHLAB_IARCHIVE_HPP
31 #define GRAPHLAB_IARCHIVE_HPP
32 
33 #include <iostream>
34 #include <graphlab/logger/assertions.hpp>
35 #include <graphlab/serialization/is_pod.hpp>
36 #include <graphlab/serialization/has_load.hpp>
37 namespace graphlab {
38 
39  /**
40  * \ingroup group_serialization
41  * \brief The serialization input archive object which, provided
42  * with a reference to an istream, will read from the istream,
43  * providing deserialization capabilities.
44  *
45  * Given a source of serialized bytes (written by an graphlab::oarchive),
46  * in the form of a standard input stream, you can construct an iarchive
47  * object by:
48  * \code
49  * // where strm is an istream object
50  * graphlab::iarchive iarc(strm);
51  * \endcode
52  *
53  * For instance, to deserialize from a file,
54  * \code
55  * std::ifstream fin("inputfile.bin");
56  * graphlab::iarchive iarc(fin);
57  * \endcode
58  *
59  * Once the iarc object is constructed, \ref sec_serializable
60  * objects can be read from it using the >> stream operator.
61  *
62  * \code
63  * iarc >> a >> b >> c;
64  * \endcode
65  *
66  * Alternatively, data can be directly read from the stream using
67  * the iarchive::read() and iarchive::read_char() functions.
68  *
69  * For more usage details, see \ref serialization
70  *
71  * The iarchive object should not be used once the associated stream
72  * object is closed or is destroyed.
73  *
74  * To use this class, include
75  * graphlab/serialization/serialization_includes.hpp
76  */
77  class iarchive {
78  public:
79  std::istream* in;
80  const char* buf;
81  size_t off;
82  size_t len;
83 
84  /// Directly reads a single character from the input stream
85  inline char read_char() {
86  char c;
87  if (buf) {
88  c = buf[off];
89  ++off;
90  } else {
91  in->get(c);
92  }
93  return c;
94  }
95 
96  /**
97  * Directly reads a sequence of "len" bytes from the
98  * input stream into the location pointed to by "c"
99  */
100  inline void read(char* c, size_t l) {
101  if (buf) {
102  memcpy(c, buf + off, l);
103  off += l;
104  } else {
105  in->read(c, l);
106  }
107  }
108 
109 
110  /// Returns true if the underlying stream is in a failure state
111  inline bool fail() {
112  return in == NULL ? off > len : in->fail();
113  }
114 
115  /**
116  * Constructs an iarchive object.
117  * Takes a reference to a generic std::istream object and associates
118  * the archive with it. Reads from the archive will read from the
119  * assiciated input stream.
120  */
121  inline iarchive(std::istream& instream)
122  : in(&instream), buf(NULL), off(0), len(0) { }
123 
124  inline iarchive(const char* buf, size_t len)
125  : in(NULL), buf(buf), off(0), len(len) { }
126 
127  ~iarchive() {}
128  };
129 
130 
131  /**
132  * \ingroup group_serialization
133  * \brief
134  * When this archive is used to deserialize an object,
135  * and the object does not support serialization,
136  * failure will only occur at runtime. Otherwise equivalent to
137  * graphlab::iarchive.
138  */
140  public:
141 
142  iarchive *iarc;
143  bool mine;
144 
145  /// Directly reads a single character from the input stream
146  inline char read_char() {
147  return iarc->read_char();
148  }
149 
150  /**
151  * Directly reads a sequence of "len" bytes from the
152  * input stream into the location pointed to by "c"
153  */
154  inline void read(char* c, size_t len) {
155  iarc->read(c, len);
156  }
157 
158  /// Returns true if the underlying stream is in a failure state
159  inline bool fail() {
160  return iarc->fail();
161  }
162 
163  /**
164  * Constructs an iarchive_soft_fail object.
165  * Takes a reference to a generic std::istream object and associates
166  * the archive with it. Reads from the archive will read from the
167  * assiciated input stream.
168  */
169  inline iarchive_soft_fail(std::istream &instream)
170  : iarc(new iarchive(instream)), mine(true) {}
171 
172  /**
173  * Constructs an iarchive_soft_fail object from an iarchive.
174  * Both will share the same input stream
175  */
177  : iarc(&iarc), mine(false) {}
178 
179  inline ~iarchive_soft_fail() { if (mine) delete iarc; }
180  };
181 
182 
183  namespace archive_detail {
184 
185  /// called by the regular archive The regular archive will do a hard fail
186  template <typename InArcType, typename T>
187  struct deserialize_hard_or_soft_fail {
188  inline static void exec(InArcType& iarc, T& t) {
189  t.load(iarc);
190  }
191  };
192 
193  /// called by the soft fail archive
194  template <typename T>
195  struct deserialize_hard_or_soft_fail<iarchive_soft_fail, T> {
196  inline static void exec(iarchive_soft_fail& iarc, T& t) {
197  load_or_fail(*(iarc.iarc), t);
198  }
199  };
200 
201 
202  /**
203  Implementation of the deserializer for different types. This is the
204  catch-all. If it gets here, it must be a non-POD and is a class. We
205  therefore call the .save function. Here we pick between the archive
206  types using serialize_hard_or_soft_fail
207  */
208  template <typename InArcType, typename T, bool IsPOD>
209  struct deserialize_impl {
210  inline static void exec(InArcType& iarc, T& t) {
211  deserialize_hard_or_soft_fail<InArcType, T>::exec(iarc, t);
212  }
213  };
214 
215  // catch if type is a POD
216  template <typename InArcType, typename T>
217  struct deserialize_impl<InArcType, T, true>{
218  inline static void exec(InArcType& iarc, T &t) {
219  iarc.read(reinterpret_cast<char*>(&t),
220  sizeof(T));
221  }
222  };
223 
224  } //namespace archive_detail
225 
226  /// \cond GRAPHLAB_INTERNAL
227 
228  /**
229  Allows Use of the "stream" syntax for serialization
230  */
231  template <typename T>
232  inline iarchive& operator>>(iarchive& iarc, T &t) {
233  archive_detail::deserialize_impl<iarchive,
234  T,
235  gl_is_pod<T>::value >::exec(iarc, t);
236  return iarc;
237  }
238 
239 
240 
241  /**
242  Allows Use of the "stream" syntax for serialization
243  */
244  template <typename T>
245  inline iarchive_soft_fail& operator>>(iarchive_soft_fail& iarc, T &t) {
246  archive_detail::deserialize_impl<iarchive_soft_fail,
247  T,
248  gl_is_pod<T>::value >::exec(iarc, t);
249  return iarc;
250  }
251 
252 
253  /**
254  deserializes an arbitrary pointer + length from an archive
255  */
256  inline iarchive& deserialize(iarchive& iarc,
257  void* str,
258  const size_t length) {
259  iarc.read(reinterpret_cast<char*>(str), (std::streamsize)length);
260  assert(!iarc.fail());
261  return iarc;
262  }
263 
264 
265 
266  /**
267  deserializes an arbitrary pointer + length from an archive
268  */
269  inline iarchive_soft_fail& deserialize(iarchive_soft_fail& iarc,
270  void* str,
271  const size_t length) {
272  iarc.read(reinterpret_cast<char*>(str), (std::streamsize)length);
273  assert(!iarc.fail());
274  return iarc;
275  }
276 
277  /// \endcond GRAPHLAB_INTERNAL
278 
279  /**
280  \ingroup group_serialization
281 
282  \brief Macro to make it easy to define out-of-place loads
283 
284  In the event that it is impractical to implement a save() and load()
285  function in the class one wnats to serialize, it is necessary to define
286  an "out of save" save and load.
287 
288  See \ref sec_serializable_out_of_place for an example
289 
290  \note important! this must be defined in the global namespace!
291  */
292 #define BEGIN_OUT_OF_PLACE_LOAD(arc, tname, tval) \
293  namespace graphlab{ namespace archive_detail { \
294  template <typename InArcType> \
295  struct deserialize_impl<InArcType, tname, false>{ \
296  static void exec(InArcType& arc, tname & tval) {
297 
298 #define END_OUT_OF_PLACE_LOAD() } }; } }
299 
300 
301 
302 
303 } // namespace graphlab
304 
305 
306 #endif
307 
308 #endif
309 
310 
311 
312 
313 
314 
315 
316