CXXR (C++ R)
GCStackRoot.hpp
Go to the documentation of this file.
1 /*CXXR $Id: GCStackRoot.hpp 1397 2013-08-16 18:25:59Z 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 
44 #ifndef GCSTACKROOT_HPP
45 #define GCSTACKROOT_HPP 1
46 
47 #include "CXXR/GCNode.hpp"
48 
49 namespace CXXR {
50  class RObject;
51 
64  public:
72  static void visitRoots(GCNode::const_visitor* v);
73  protected:
78  GCStackRootBase(const GCNode* node)
79  : m_next(s_roots), m_target(node), m_protecting(false)
80  {
81  s_roots = this;
83  }
84 
90  : m_next(s_roots), m_target(source.m_target), m_protecting(false)
91  {
92  s_roots = this;
93  }
94 
96  {
97 #ifndef NDEBUG
98  if (this != s_roots)
99  seq_error();
100 #endif
101  if (m_protecting)
102  destruct_aux();
103  s_roots = m_next;
104  }
105 
106  GCStackRootBase& operator=(const GCStackRootBase& source)
107  {
108  retarget(source.m_target);
109  return *this;
110  }
111 
117  void retarget(const GCNode* node)
118  {
120  if (m_protecting)
121  retarget_aux(node);
122  m_target = node;
123  }
124 
129  const GCNode* ptr() const
130  {
131  return m_target;
132  }
133  private:
134  friend class GCNode;
135 
136  static GCStackRootBase* s_roots;
137 
138  GCStackRootBase* m_next;
139  const GCNode* m_target;
140  bool m_protecting; // If this is set, it signifies that this
141  // GCStackRootBase object will have incremented the
142  // reference count of its target (if any). In the interests
143  // of efficiency, initially m_protecting is false; it is set
144  // by call to protectAll().
145  //
146  // m_protecting && m_next implies m_next->m_protecting .
147 
148  // Helper function for destructor:
149 #ifdef __GNUC__
150  __attribute__((hot, fastcall))
151 #endif
152  void destruct_aux();
153 
154  // Put all GCStackRootBase objects into the protecting state:
155 #ifdef __GNUC__
156  __attribute__((hot, fastcall))
157 #endif
158  static void protectAll();
159 
160  // Helper function for retarget():
161 #ifdef __GNUC__
162  __attribute__((hot, fastcall))
163 #endif
164  void retarget_aux(const GCNode* node);
165 
166  // Report out-of-sequence destructor call and abort program.
167  // (We can't use an exception here because it's called from a
168  // destructor.)
169 #ifdef __GNUC__
170  __attribute__((cold))
171 #endif
172  static void seq_error();
173  };
174 
210  template <class T = RObject>
211  class GCStackRoot : public GCStackRootBase {
212  public:
213  typedef T type;
214 
220  explicit GCStackRoot(T* node = 0)
221  : GCStackRootBase(node) {}
222 
229  GCStackRoot(const GCStackRoot& source) : GCStackRootBase(source) {}
230 
237  {
239  return *this;
240  }
241 
251  {
253  return *this;
254  }
255 
260  T* operator->() const
261  {
262  return get();
263  }
264 
271  T& operator*() const
272  {
273  return *get();
274  }
275 
283  operator T*() const
284  {
285  return get();
286  }
287 
292  T* get() const
293  {
294  return static_cast<T*>(const_cast<GCNode*>(ptr()));
295  }
296  };
297 } // namespace CXXR
298 
299 #endif // GCSTACKROOT_HPP