CXXR (C++ R)
GCRoot.h
Go to the documentation of this file.
1 /*CXXR $Id: GCRoot.h 1353 2013-03-18 16:59:38Z arr $
2  *CXXR
3  *CXXR This file is part of CXXR, a project to refactor the R interpreter
4  *CXXR into C++. It may consist in whole or in part of program code and
5  *CXXR documentation taken from the R project itself, incorporated into
6  *CXXR CXXR (and possibly MODIFIED) under the terms of the GNU General Public
7  *CXXR Licence.
8  *CXXR
9  *CXXR CXXR is Copyright (C) 2008-13 Andrew R. Runnalls, subject to such other
10  *CXXR copyrights and copyright restrictions as may be stated below.
11  *CXXR
12  *CXXR CXXR is not part of the R project, and bugs and other issues should
13  *CXXR not be reported via r-bugs or other R project channels; instead refer
14  *CXXR to the CXXR website.
15  *CXXR */
16 
17 /*
18  * R : A Computer Language for Statistical Data Analysis
19  *
20  * This program is free software; you can redistribute it and/or modify
21  * it under the terms of the GNU General Public License as published by
22  * the Free Software Foundation; either version 2.1 of the License, or
23  * (at your option) any later version.
24  *
25  * This program is distributed in the hope that it will be useful,
26  * but WITHOUT ANY WARRANTY; without even the implied warranty of
27  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28  * GNU Lesser General Public License for more details.
29  *
30  * You should have received a copy of the GNU General Public License
31  * along with this program; if not, a copy is available at
32  * http://www.r-project.org/Licenses/
33  */
34 
41 #ifndef GCROOT_H
42 #define GCROOT_H 1
43 
44 #include "CXXR/RObject.h"
45 
46 #ifdef __cplusplus
47 
48 #include <list>
49 #include <tr1/unordered_map>
50 #include "CXXR/GCNode.hpp"
51 
52 namespace CXXR {
53  class RObject;
54 
62  class GCRootBase {
63  public:
71  static void visitRoots(GCNode::const_visitor* v);
72  protected:
77  GCRootBase(const GCNode* node);
78 
83  GCRootBase(const GCRootBase& source)
84  : m_it(s_roots->insert(s_roots->end(), *source.m_it))
85  {
86  GCNode::incRefCount(*m_it);
87  }
88 
89  ~GCRootBase()
90  {
91  const GCNode* node = *m_it;
92  GCNode::decRefCount(node);
93  s_roots->erase(m_it);
94  }
95 
96  GCRootBase& operator=(const GCRootBase& source)
97  {
98  const GCNode* newnode = *source.m_it;
99  GCNode::incRefCount(newnode);
100  const GCNode* oldnode = *m_it;
101  GCNode::decRefCount(oldnode);
102  *m_it = newnode;
103  return *this;
104  }
105 
111  void redirect(const GCNode* node)
112  {
114  GCNode::incRefCount(node);
115  const GCNode* oldnode = *m_it;
116  GCNode::decRefCount(oldnode);
117  *m_it = node;
118  }
119 
124  const GCNode* ptr() const
125  {
126  return *m_it;
127  }
128  private:
129  friend class GCNode;
130 
131  typedef std::list<const GCNode*, Allocator<const GCNode*> > List;
132  static List* s_roots;
133 
134  List::iterator m_it;
135 
136  // Clean up static data at end of run (called by
137  // GCNode::SchwarzCtr destructor:
138  static void cleanup() {}
139 
140  // Initialize static data (called by GCNode::SchwarzCtr
141  // constructor):
142  static void initialize();
143  };
144 
171  template <class T = RObject>
172  class GCRoot : public GCRootBase {
173  public:
179  explicit GCRoot(T* node = 0)
180  : GCRootBase(node) {}
181 
188  GCRoot(const GCRoot& source) : GCRootBase(source) {}
189 
195  GCRoot& operator=(const GCRoot& source)
196  {
197  GCRootBase::operator=(source);
198  return *this;
199  }
200 
209  GCRoot& operator=(T* node)
210  {
211  GCRootBase::redirect(node);
212  return *this;
213  }
214 
219  T* operator->() const
220  {
221  return get();
222  }
223 
230  T& operator*() const
231  {
232  return *get();
233  }
234 
242  operator T*() const
243  {
244  return get();
245  }
246 
251  T* get() const
252  {
253  return static_cast<T*>(const_cast<GCNode*>(ptr()));
254  }
255  };
256 } // namespace CXXR
257 
258 // For hashing, simply hash the encapsulated pointer:
259 namespace std {
260  namespace tr1 {
261  template <class T>
262  struct hash<CXXR::GCRoot<T> > {
263  std::size_t operator()(const CXXR::GCRoot<T>& gcrt) const
264  {
265  std::tr1::hash<T*> make_hash;
266  return make_hash(gcrt);
267  }
268  };
269  }
270 }
271 
272 extern "C" {
273 #endif /* __cplusplus */
274 
275  /* ***** C interface ***** */
276 
285  void R_PreserveObject(SEXP object);
286 
295  void R_ReleaseObject(SEXP object);
296 
297 #ifdef __cplusplus
298 } /* extern "C" */
299 #endif
300 
301 #endif // GCROOT_H