OpenCog Framework  Branch: master, revision 6f0b7fc776b08468cf1b74aa9db028f387b4f0c0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
Handle.h
Go to the documentation of this file.
1 /*
2  * opencog/atomspace/Handle.h
3  *
4  * Copyright (C) 2008-2010 OpenCog Foundation
5  * Copyright (C) 2002-2007 Novamente LLC
6  * Copyright (C) 2013 Linas Vepstas <linasvepstas@gmail.com>
7  * All Rights Reserved
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU Affero General Public License v3 as
11  * published by the Free Software Foundation and including the exceptions
12  * at http://opencog.org/wiki/Licenses
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU Affero General Public License
20  * along with this program; if not, write to:
21  * Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23  */
24 
25 #ifndef _OPENCOG_HANDLE_H
26 #define _OPENCOG_HANDLE_H
27 
28 #include <cstddef>
29 #include <cstdio>
30 #include <iostream>
31 #include <climits>
32 #include <functional>
33 #include <memory>
34 #include <string>
35 #include <sstream>
36 #include <unordered_set>
37 #include <vector>
38 
42 namespace opencog
43 {
44 
46 typedef unsigned long UUID;
47 
48 class Atom;
49 typedef std::shared_ptr<Atom> AtomPtr;
50 
52 class AtomTable;
53 class Handle
54 {
55 
56 friend class AtomTable;
57 friend class AtomStorage; // persistance
58 friend class AtomspaceHTabler; // persistance
59 
60 private:
61 
64 
65  Atom* resolve();
66  Atom* cresolve() const;
67  static AtomPtr do_res(const Handle*);
68  static std::vector<const AtomTable*> _resolver;
69 
71  static void set_resolver(const AtomTable*);
72  static void clear_resolver(const AtomTable*);
73 
74  static const AtomPtr NULL_POINTER;
75 public:
76 
77  static const Handle UNDEFINED;
78 
79  explicit Handle(const AtomPtr& atom);
80  explicit Handle(const UUID u) : _uuid(u) {}
81  explicit Handle() : _uuid(ULONG_MAX) {}
82  Handle(const Handle& h) : _uuid(h._uuid), _ptr(h._ptr) {}
83  ~Handle() {}
84 
85  inline UUID value(void) const {
86  return _uuid;
87  }
88 
89  inline Handle& operator=(const Handle& h) {
90  if (this->_uuid == h._uuid) {
91  Atom* a = h._ptr.get();
92  // The 'typical' case here is where a isn't null,
93  // but this is. The weirdo case is where both
94  // aren't null, and yet differ.
95  // Mostly, we want to avoid the CPU overhead of calling
96  // resolve(), it we can; so the goal of this if-stmt is
97  // to upgrade the ptr from null to non-null.
98  if (a != NULL and a != this->_ptr.get())
99  this->_ptr = h._ptr;
100  return *this;
101  }
102  this->_uuid = h._uuid;
103  this->_ptr = h._ptr;
104  return *this;
105  }
106 
107  Handle& operator=(const AtomPtr& a);
108 
109  inline Atom* operator->() {
110  Atom* ptr = _ptr.get();
111  if (ptr) return ptr;
112  if (ULONG_MAX == _uuid) return NULL;
113  return resolve();
114  }
115 
116  inline Atom* operator->() const {
117  Atom* ptr = _ptr.get();
118  if (ptr) return ptr;
119  if (ULONG_MAX == _uuid) return NULL;
120  return cresolve();
121  }
122 
123  // Allows expressions like "if(h)..." to work when h has a non-null pointer.
124  explicit inline operator bool() const noexcept {
125  if (_ptr.get()) return true;
126  return NULL != cresolve(); // might be null because we haven't resolved it yet!
127  }
128 
129  inline bool operator==(std::nullptr_t) const noexcept {
130  if (_ptr.get()) return false;
131  return NULL == cresolve(); // might be null because we haven't resolved it yet!
132  }
133 
134  inline bool operator!=(std::nullptr_t) const noexcept {
135  if (_ptr.get()) return true;
136  return NULL != cresolve(); // might be null because we haven't resolved it yet!
137  }
138 
139  // Handles are equivalent when their uuid's compare. It may happen
140  // that one has a null pointer, and the other one doesn't; we don't
141  // care about that. It should never ever happen that we have two
142  // identical uuid's but inequivalent pointers!! Well, unless both
143  // uuids are -1, in which case, we are comparing atoms that have
144  // not yet been inserted into the atomspace. We refuse to deal with
145  // this situation here, because it is a confusing mess to try to
146  // compare atoms that are not in the atomspace; the notion of
147  // equality and equivalence differ, and it depends strong on the
148  // atom type.
149  inline bool operator==(const Handle& h) const noexcept { return _uuid == h._uuid; }
150  inline bool operator!=(const Handle& h) const noexcept { return _uuid != h._uuid; }
151  inline bool operator< (const Handle& h) const noexcept { return _uuid < h._uuid; }
152  inline bool operator> (const Handle& h) const noexcept { return _uuid > h._uuid; }
153  inline bool operator<=(const Handle& h) const noexcept { return _uuid <= h._uuid; }
154  inline bool operator>=(const Handle& h) const noexcept { return _uuid >= h._uuid; }
155 
156 
168  static int compare(const Handle& h1, const Handle& h2)
169  {
170  if (h1 < h2) return -1;
171  if (h1 > h2) return 1;
172  return 0;
173  }
174 
175  operator AtomPtr() const {
176  if (_ptr.get()) return _ptr;
177  if (ULONG_MAX == _uuid) return NULL_POINTER;
178  Handle h(*this);
179  return h.resolve_ptr();
180  }
181  operator AtomPtr() {
182  if (_ptr.get()) return _ptr;
183  if (ULONG_MAX == _uuid) return NULL_POINTER;
184  return resolve_ptr();
185  }
186 /***
187  operator const AtomPtr&() {
188  if (_ptr.get()) return _ptr;
189  if (ULONG_MAX == _uuid) return NULL_POINTER;
190  return resolve_ptr();
191  }
192 ***/
193 };
194 
195 static inline bool operator== (std::nullptr_t, const Handle& rhs) noexcept
196  { return rhs == NULL; }
197 
198 static inline bool operator!= (std::nullptr_t, const Handle& rhs) noexcept
199  { return rhs != NULL; }
200 
202 public:
203  inline bool operator()(const Handle& h) const { return this->test(h); }
204  virtual bool test(const Handle&) const = 0;
205 };
207 public:
208  inline bool operator()(const AtomPtr& a) const { return this->test(a); }
209  virtual bool test(const AtomPtr&) const = 0;
210 };
212 public:
213  inline bool operator()(const AtomPtr& a, const AtomPtr& b) const
214  { return this->test(a,b); }
215  virtual bool test(const AtomPtr&, const AtomPtr&) const = 0;
216 };
217 
218 
221 struct handle_hash : public std::unary_function<Handle, size_t>
222 {
223  size_t operator()(const Handle& h) const
224  {
225  return static_cast<std::size_t>(h.value());
226  }
227 };
228 
230 inline std::size_t hash_value(Handle const& h)
231 {
232  return static_cast<std::size_t>(h.value());
233 }
234 
238 {
239  bool operator()(const Handle& hl, const Handle& hr) const
240  {
241  return hl.value() < hr.value();
242  }
243 };
244 
246 typedef std::vector<Handle> HandleSeq;
248 typedef std::vector<HandleSeq> HandleSeqSeq;
250 typedef std::unordered_set<Handle, handle_hash> UnorderedHandleSet;
251 
253 {
254  bool operator()(const HandleSeq& hsl, const HandleSeq& hsr) const
255  {
256  size_t sl = hsl.size();
257  size_t sr = hsr.size();
258  if (sl != sr) return sl < sr;
259  for (size_t i=0; i<sl; i++) {
260  UUID ul = hsl[i].value();
261  UUID ur = hsr[i].value();
262  if (ul != ur) return ul < ur;
263  }
264  return false;
265  }
266 };
267 
269 static inline std::string operator+ (const char *lhs, Handle h)
270 {
271  std::string rhs = lhs;
272  char buff[25];
273  snprintf(buff, 24, "%lu)", h.value());
274  return rhs + buff;
275 }
276 
278 static inline std::string operator+ (const std::string &lhs, Handle h)
279 {
280  char buff[25];
281  snprintf(buff, 24, "%lu)", h.value());
282  return lhs + buff;
283 }
284 
285 } // namespace opencog
286 
287 namespace std {
288 inline std::ostream& operator<<(std::ostream& out, const opencog::Handle& h)
289 {
290  out << h.value();
291  return out;
292 }
293 
294 #ifdef THIS_USED_TO_WORK_GREAT_BUT_IS_BROKEN_IN_GCC472
295 // The below used to work, but broke in gcc-4.7.2. The reason it
296 // broke is that it fails to typedef result_type and argument_type,
297 // which ... somehow used to work automagically?? It doesn't any more.
298 // I have no clue why gcc-4.7.2 broke this, and neither does google or
299 // stackoverflow. You have two choices: use handle_hash, above, or
300 // cross your fingers, and hope the definition in the #else clause,
301 // below, works.
302 
303 template<>
304 inline std::size_t
306 {
307  return static_cast<std::size_t>(h.value());
308 }
309 
310 #else
311 
312 // This works for e, per note immediately above.
313 template<>
314 struct hash<opencog::Handle>
315 {
316  typedef std::size_t result_type;
318  std::size_t
319  operator()(opencog::Handle h) const noexcept
320  { return static_cast<std::size_t>(h.value()); }
321 };
322 
323 #endif // THIS_USED_TO_WORK_GREAT_BUT_IS_BROKEN_IN_GCC472
324 
325 } //namespace std
326 
328 #endif // _OPENCOG_HANDLE_H
bool operator()(const AtomPtr &a, const AtomPtr &b) const
Definition: Handle.h:213
bool operator==(const Handle &h) const noexcept
Definition: Handle.h:149
static AtomPtr do_res(const Handle *)
Definition: Handle.cc:66
Handle(const Handle &h)
Definition: Handle.h:82
AtomPtr resolve_ptr()
Definition: Handle.cc:87
bool operator()(const Handle &h) const
Definition: Handle.h:203
static std::vector< const AtomTable * > _resolver
Definition: Handle.h:68
bool operator()(const HandleSeq &hsl, const HandleSeq &hsr) const
Definition: Handle.h:254
bool operator!=(const Handle &h) const noexcept
Definition: Handle.h:150
std::vector< Handle > HandleSeq
a list of handles
Definition: Handle.h:246
static bool operator==(std::nullptr_t, const Handle &rhs) noexcept
Definition: Handle.h:195
std::shared_ptr< Atom > AtomPtr
Definition: Handle.h:48
bool operator()(const AtomPtr &a) const
Definition: Handle.h:208
Atom * operator->() const
Definition: Handle.h:116
virtual bool test(const Handle &) const =0
virtual bool test(const AtomPtr &) const =0
std::vector< HandleSeq > HandleSeqSeq
a list of lists of handles
Definition: Handle.h:248
Handle & operator=(const Handle &h)
Definition: Handle.h:89
UUID _uuid
Definition: Handle.h:62
static const Handle UNDEFINED
Definition: Handle.h:77
bool operator>=(const Handle &h) const noexcept
Definition: Handle.h:154
bool operator>(const Handle &h) const noexcept
Definition: Handle.h:152
unsigned long UUID
UUID == Universally Unique Identifier.
Definition: Handle.h:46
bool operator==(std::nullptr_t) const noexcept
Definition: Handle.h:129
bool operator<(const Handle &h) const noexcept
Definition: Handle.h:151
size_t operator()(const Handle &h) const
Definition: Handle.h:223
AtomPtr _ptr
Definition: Handle.h:63
Atom * cresolve() const
Definition: Handle.cc:82
ostream & operator<<(ostream &out, const opencog::AtomSpace &as)
Definition: AtomSpace.cc:382
virtual bool test(const AtomPtr &, const AtomPtr &) const =0
UUID value(void) const
Definition: Handle.h:85
static bool operator!=(std::nullptr_t, const Handle &rhs) noexcept
Definition: Handle.h:198
static void set_resolver(const AtomTable *)
Definition: Handle.cc:52
static std::string operator+(const char *lhs, Handle h)
append string representation of the Hash to the string
Definition: Handle.h:269
std::unordered_set< Handle, handle_hash > UnorderedHandleSet
a hash that associates the handle to its unique identificator
Definition: Handle.h:250
Handle(const UUID u)
Definition: Handle.h:80
static void clear_resolver(const AtomTable *)
Definition: Handle.cc:57
Atom * resolve()
Definition: Handle.cc:75
Atom * operator->()
Definition: Handle.h:109
bool operator<=(const Handle &h) const noexcept
Definition: Handle.h:153
bool operator!=(std::nullptr_t) const noexcept
Definition: Handle.h:134
std::size_t hash_value(Handle const &h)
Boost needs this function to be called by exactly this name.
Definition: Handle.h:230
bool operator()(const Handle &hl, const Handle &hr) const
Definition: Handle.h:239
opencog::Handle argument_type
Definition: Handle.h:317
std::size_t operator()(opencog::Handle h) const noexcept
Definition: Handle.h:319
static int compare(const Handle &h1, const Handle &h2)
Definition: Handle.h:168
static const AtomPtr NULL_POINTER
Definition: Handle.h:74