GraphLab: Distributed Graph-Parallel API  2.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
blob.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_BLOB_HPP
25 #define GRAPHLAB_BLOB_HPP
26 
27 #include <cstring>
28 #include <cstdlib>
29 #include <cassert>
30 
31 #include <graphlab/serialization/iarchive.hpp>
32 #include <graphlab/serialization/oarchive.hpp>
33 #include <graphlab/serialization/vector.hpp>
34 #include <graphlab/serialization/map.hpp>
35 
36 namespace graphlab {
37  /**
38  * blob is the general representation of a "block" of information.
39  *. 'data' must be exactly 'length' bytes and must be entirely
40  * self contained. It must not hold references to other memory
41  * regions. That is to say, I should be able read off exactly
42  * 'length' bytes from 'data', and send it across a network/write it
43  * to a disk/etc, and the information should still be consistent
44  * The blob is self-managed and will free and delete the underlying memory
45  * when it goes out of scope.
46  */
47  class blob {
48  size_t size_; /// number of bytes of the 'data' field
49  void* data_; /// user information
50  public:
51 
52  /** Create an empty blob */
53  blob() : size_(0), data_(NULL) { }
54 
55  /** Create simple blob of a certain size (with allocation)*/
56  blob(size_t new_size) :
57  size_(0), data_(NULL) {
58  resize(new_size);
59  } // end of basic blob constructor
60 
61  /** Makes a copy of the ptr provided */
62  blob(size_t osize, void* odata) : size_(0), data_(NULL) {
63  if (osize > 0) { copy(osize, odata); }
64  } // end of basic blob constructor
65 
66  /** Copy constructor */
67  blob(const blob &b) : size_(0), data_(NULL) {
68  if (b.size_ != 0 && b.data_ != NULL) {
69  copy(b);
70  }
71  }
72 
73  ~blob() { clear(); }
74 
75  /** Smart Casting */
76  template<typename T>
77  T& as() {
78  assert(data_ != NULL);
79  assert(sizeof(T) <= size_);
80  return *reinterpret_cast<T*>(data_);
81  }
82 
83  /** Smart Casting */
84  template<typename T>
85  const T& as() const {
86  assert(data_ != NULL);
87  assert(sizeof(T) <= size_);
88  return *reinterpret_cast<T*>(data_);
89  }
90 
91  /** Smart Casting */
92  template<typename T>
93  T* as_ptr() {
94  assert(data_ != NULL);
95  assert(sizeof(T) <= size_);
96  return reinterpret_cast<T*>(data_);
97  }
98 
99  /** Smart Casting */
100  template<typename T>
101  const T* as_ptr() const {
102  assert(data_ != NULL);
103  assert(sizeof(T) <= size_);
104  return reinterpret_cast<const T*>(data_);
105  }
106 
107  /** Get the size of the blob */
108  size_t size() const { return size_; }
109 
110  /** Get the size of the blob */
111  void* data() { return data_; }
112 
113  /** Get the size of the blob */
114  const void* data() const { return data_; }
115 
116 
117 
118  blob& operator=(const blob& b){
119  copy(b);
120  return *this;
121  }
122 
123 
124 
125  /** make a copy of the data passed in as arguments. */
126  void copy(size_t osize, void* odata) {
127  resize(osize);
128  // Copy the contents over
129  memcpy(data_, odata, osize);
130  }
131 
132  /** Make "deep" copy of the blob by replicate its binary data */
133  void copy(const blob& other) {
134  assert(other.size_ == 0 || other.data_ != NULL);
135  // Do an allocation (which is only done if necessary)
136  resize(other.size_);
137  // Copy the contents over
138  memcpy(data_, other.data_, size_);
139  }
140 
141  /** deprecated. Just use operator= */
142  blob copy() const{
143  return *this;
144  }
145  /** Resize the blob to any size including 0 */
146  void resize(size_t new_size) {
147  if(new_size == 0) {
148  // if resize to zero then just clear
149  clear();
150  } else if(size_ == new_size ) {
151  // if resize to current size then nop
152  assert(data_ != NULL);
153  } else {
154  clear();
155  assert(data_ == NULL && size_ == 0);
156  size_ = new_size;
157  data_ = malloc(new_size);
158  assert(data_ != NULL);
159  }
160  } // end of malloc
161 
162 
163  /** free the memory associated with this blob */
164  void clear() {
165  if(data_ != NULL) {
166  assert(size_ > 0);
167  free(data_);
168  data_ = NULL;
169  }
170  size_ = 0;
171  } // end of free
172 
173 
174  /** Swaps the contents of two blobs. A "safe" version of a shallow copy */
175  void swap(blob &b) {
176  void* tmp = b.data_;
177  size_t tmpsize = b.size_;
178 
179  b.data_ = data_;
180  b.size_ = size_;
181 
182  data_ = tmp;
183  size_ = tmpsize;
184  }
185 
186  void load(iarchive& arc) {
187  clear();
188  arc >> size_;
189  if (size_ == 0) {
190  data_ = NULL;
191  } else {
192  data_ = malloc(size_);
193  deserialize(arc, data_, size_);
194  }
195  }
196 
197  void save(oarchive& arc) const {
198  arc << size_;
199  if (size_ != 0) {
200  serialize(arc, data_, size_);
201  }
202  }
203  }; // end of blob
204 
205 
206 } // end of namespace
207 #endif
208