vbl_io_smart_ptr.hxx
Go to the documentation of this file.
1 // This is core/vbl/io/vbl_io_smart_ptr.hxx
2 #ifndef vbl_io_smart_ptr_hxx_
3 #define vbl_io_smart_ptr_hxx_
4 //:
5 // \file
6 // \brief Serialised binary IO functions for vbl_smart_ptr<T>
7 // \author Ian Scott (Manchester)
8 // \date 26-Mar-2001
9 
10 #include <cstdlib>
11 #include <iostream>
12 #include "vbl_io_smart_ptr.h"
13 #include <vsl/vsl_binary_io.h>
14 #include <vbl/vbl_smart_ptr.h>
15 #ifdef _MSC_VER
16 # include <vcl_msvc_warnings.h>
17 #endif
18 
19 //=========================================================================
20 //: Binary save self to stream.
21 template<class T>
22 void vsl_b_write(vsl_b_ostream & os, const vbl_smart_ptr<T> &p)
23 {
24  // write version number
25  constexpr short io_version_no = 2;
26  vsl_b_write(os, io_version_no);
27  vsl_b_write(os, p.is_protected());
28 
29  if (p.ptr() == nullptr) // Deal with Null pointers first.
30  {
31  vsl_b_write(os, true);
32  vsl_b_write(os, 0ul); // Use 0 to indicate a null pointer.
33  // True serialisation IDs are always 1 or more.
34  return;
35  }
36 
37  // Get a serial_number for object being pointed to
38  unsigned long id = os.get_serial_number(p.ptr());
39  // Find out if this is the first time the object being pointed to is
40  // being saved
41  if (id == 0)
42  {
43  // <rant> IMS
44  // It is not clear how to deal fully satisfactorily with unprotected
45  // smart_ptrs. For example is we save and reload them without any error
46  // checks we could restore the object with a reference count of 0.
47  // To be honest, I think the idea of an unprotected smart_ptr is
48  // not so smart. Either it is a smart pointer, in which case it should
49  // be protected, or it is unprotected in which case you should use a
50  // ordinary pointer. Cycles in the pointer network, are best dealt with
51  // by avoiding them. You have to be aware they are happening to unprotect
52  // the pointer anyway.
53  // </rant>
54  if (!p.is_protected())
55  {
56  std::cerr << "vsl_b_write(vsl_b_ostream & os, const vbl_smart_ptr<T>&):"
57  << " You cannot\nsave unprotected smart pointers before saving"
58  << " a protected smart pointer\nto the same object. Either do"
59  << " not save unprotected smart pointers, or\nbe very careful"
60  << " about the order.\n";
61  std::abort();
62  }
63 
64  id = os.add_serialisation_record(p.ptr());
65 
66  // Say that this is the first time
67  // that this object is being saved.
68  // This isn't really necessary but
69  // it is useful as an error check
70  vsl_b_write(os, true);
71  vsl_b_write(os, id); // Save the serial number
72 // If you get an error in the next line, it could be because your type T
73 // has no vsl_b_write(vsl_b_ostream &,const T*) defined on it.
74 // See the documentation in the .h file to see how to add it.
75  vsl_b_write(os, p.ptr()); // Only save the actual object if it
76  //hasn't been saved before to this stream
77  }
78  else
79  {
80  // Say that this is not the first time
81  // that this object is being saved.
82  // This isn't really necessary but
83  // it is useful as an error check
84 
85  vsl_b_write(os, false);
86  vsl_b_write(os, id); // Save the serial number
87  }
88 }
89 
90 //=====================================================================
91 //: Binary load self from stream.
92 template<class T>
93 void vsl_b_read(vsl_b_istream &is, vbl_smart_ptr<T> &p)
94 {
95  if (!is) return;
96 
97  short ver;
98  vsl_b_read(is, ver);
99  switch (ver)
100  {
101  case 1:
102  case 2:
103  {
104  bool is_protected; // true if the smart_ptr is to be
105  //responsible for the object
106  vsl_b_read(is, is_protected);
107 
108  bool first_time; // true if the object is about to be loaded
109  vsl_b_read(is, first_time);
110 
111  if (first_time && !is_protected) // This should have been
112  { //checked during saving
113  std::cerr << "I/O ERROR: vsl_b_read(vsl_b_istream&, vbl_smart_ptr<T>&)\n"
114  << " De-serialisation failure of non-protected smart_ptr\n";
115  is.is().clear(std::ios::badbit); // Set an unrecoverable IO error on stream
116  return;
117  }
118  unsigned long id; // Unique serial number indentifying object
119  vsl_b_read(is, id);
120 
121  if (id == 0) // Deal with Null pointers first.
122  {
123  p = nullptr;
124  return;
125  }
126 
127  T * pointer = static_cast<T *>( is.get_serialisation_pointer(id));
128  if (first_time != (pointer == nullptr))
129  {
130  // This checks that the saving stream and reading stream
131  // both agree on whether or not this is the first time they
132  // have seen this object.
133  std::cerr << "I/O ERROR: vsl_b_read(vsl_b_istream&, vbl_smart_ptr<T>&)\n"
134  << " De-serialisation failure\n";
135  is.is().clear(std::ios::badbit); // Set an unrecoverable IO error on stream
136  return;
137  }
138 
139  if (pointer == nullptr)
140  {
141  // If you get an error in the next line, it could be because your type T
142  // has no vsl_b_read(vsl_b_istream&,T*&) defined on it.
143  // See the documentation in the .h file to see how to add it.
144  vsl_b_read(is, pointer);
145  is.add_serialisation_record(id, pointer);
146  }
147 
148  p = pointer; // This operator method will set the internal
149  //pointer in vbl_smart_ptr.
150  if (!is_protected)
151  p.unprotect();
152 
153  break;
154  }
155  default:
156  std::cerr << "I/O ERROR: vsl_b_read(vsl_b_istream&, vbl_smart_ptr<T>&)\n"
157  << " Unknown version number "<< ver << '\n';
158  is.is().clear(std::ios::badbit); // Set an unrecoverable IO error on stream
159  return;
160  }
161 }
162 
163 //=====================================================================
164 //: Output a human readable summary to the stream
165 template<class T>
166 void vsl_print_summary(std::ostream & os,const vbl_smart_ptr<T> & p)
167 {
168  if (p.is_protected())
169  os <<"Unprotected ";
170  os << "Smart ptr to ";
171  if (p.ptr())
172  {
173  // If you get an error in the next line, it could be because your type T
174  // has no vsl_print_summary(vsl_b_ostream &, const T*) defined on it.
175  // See the documentation in the .h file to see how to add it.
176  vsl_print_summary(os, p.ptr());
177  }
178  else
179  os << "NULL";
180 }
181 
182 
183 #undef VBL_IO_SMART_PTR_INSTANTIATE
184 #define VBL_IO_SMART_PTR_INSTANTIATE(T) \
185 template void vsl_print_summary(std::ostream &, const vbl_smart_ptr<T > &); \
186 template void vsl_b_read(vsl_b_istream &, vbl_smart_ptr<T > &); \
187 template void vsl_b_write(vsl_b_ostream &, const vbl_smart_ptr<T > &)
188 
189 #endif // vbl_io_smart_ptr_hxx_
Serialised binary IO functions for vbl_smart_ptr<T>
bool is_protected() const
Is this smart pointer responsible for the object being pointed to.
void unprotect()
Used for breaking circular references (see above).
A templated smart pointer class.
Definition: vbl_fwd.h:18
void vsl_print_summary(std::ostream &os, const vbl_smart_ptr< T > &p)
Output a human readable summary to the stream.
Contains a templated smart pointer class.
void vsl_b_write(vsl_b_ostream &os, const vbl_smart_ptr< T > &p)
Binary save self to stream.
void vsl_b_read(vsl_b_istream &is, vbl_smart_ptr< T > &p)
Binary load self from stream.
T * ptr() const
These methods all return the raw/dumb pointer.