GNU Octave  6.2.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
action-container.h
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (C) 1993-2021 The Octave Project Developers
4 //
5 // See the file COPYRIGHT.md in the top-level directory of this
6 // distribution or <https://octave.org/copyright/>.
7 //
8 // This file is part of Octave.
9 //
10 // Octave is free software: you can redistribute it and/or modify it
11 // under the terms of the GNU General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // Octave is distributed in the hope that it will be useful, but
16 // WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU General Public License for more details.
19 //
20 // You should have received a copy of the GNU General Public License
21 // along with Octave; see the file COPYING. If not, see
22 // <https://www.gnu.org/licenses/>.
23 //
24 ////////////////////////////////////////////////////////////////////////
25 
26 #if ! defined (octave_action_container_h)
27 #define octave_action_container_h 1
28 
29 #include "octave-config.h"
30 
31 #include <functional>
32 
33 // This class allows registering actions in a list for later
34 // execution, either explicitly or when the container goes out of
35 // scope.
36 
37 // FIXME: is there a better name for this class?
38 
39 namespace octave
40 {
41  class
43  {
44  public:
45 
46  // A generic unwind_protect element. Knows how to run itself and
47  // discard itself. Also, contains a pointer to the next element.
48  class elem
49  {
50  public:
51 
52  friend class action_container;
53 
54  elem (void) { }
55 
56  // No copying!
57 
58  elem (const elem&) = delete;
59 
60  elem& operator = (const elem&) = delete;
61 
62  virtual ~elem (void) = default;
63 
64  virtual void run (void) { }
65  };
66 
67  // An element that merely runs a void (*)(void) function.
68 
69  class fcn_elem : public elem
70  {
71  public:
72 
73  template <typename F, typename... Args>
74  fcn_elem (F&& fcn, Args&&... args)
75  : m_fcn (std::bind (fcn, args...))
76  { }
77 
78  void run (void) { m_fcn (); }
79 
80  private:
81 
82  std::function<void (void)> m_fcn;
83  };
84 
85  // An element that stores arbitrary variable, and restores it.
86 
87  template <typename T>
88  class restore_var_elem : public elem
89  {
90  public:
91 
92  restore_var_elem (T& ref, const T& val)
93  : m_ptr (&ref), m_val (val) { }
94 
95  // No copying!
96 
98 
99  restore_var_elem& operator = (const restore_var_elem&) = delete;
100 
101  void run (void) { *m_ptr = m_val; }
102 
103  private:
104 
105  T *m_ptr, m_val;
106  };
107 
108  // Deletes a class allocated using new.
109 
110  template <typename T>
111  class delete_ptr_elem : public elem
112  {
113  public:
114 
116  : m_ptr (ptr) { }
117 
118  // No copying!
119 
120  delete_ptr_elem (const delete_ptr_elem&) = delete;
121 
122  delete_ptr_elem operator = (const delete_ptr_elem&) = delete;
123 
124  void run (void) { delete m_ptr; }
125 
126  private:
127 
128  T *m_ptr;
129  };
130 
131  action_container (void) { }
132 
133  // No copying!
134 
136 
137  action_container& operator = (const action_container&) = delete;
138 
139  virtual ~action_container (void) = default;
140 
141  template <typename F, typename... Args>
142  void add (F&& fcn, Args&&... args)
143  {
144  add_action (new fcn_elem (std::forward<F> (fcn),
145  std::forward<Args> (args)...));
146  }
147 
148  // Use separate template types for function pointer parameter
149  // declarations and captured arguments so that differences in
150  // const are handled properly.
151 
152  template <typename... Params, typename... Args>
153  void add_fcn (void (*fcn) (Params...), Args&&... args)
154  {
155  add_action (new fcn_elem (fcn, std::forward<Args> (args)...));
156  }
157 
158  template <typename T, typename... Params, typename... Args>
159  void add_method (T *obj, void (T::*method) (Params...), Args&&... args)
160  {
161  add_action (new fcn_elem (method, obj, std::forward<Args> (args)...));
162  }
163 
164  template <typename T, typename... Params, typename... Args>
165  void add_method (T& obj, void (T::*method) (Params...), Args&&... args)
166  {
167  add_action (new fcn_elem (method, &obj, std::forward<Args> (args)...));
168  }
169 
170  // Call to delete (T*).
171 
172  template <typename T>
173  void add_delete (T *obj)
174  {
175  add_action (new delete_ptr_elem<T> (obj));
176  }
177 
178  // Protect any variable.
179  template <typename T>
180  void protect_var (T& var)
181  {
182  add_action (new restore_var_elem<T> (var, var));
183  }
184 
185  // Protect any variable, value given.
186  template <typename T>
187  void protect_var (T& var, const T& val)
188  {
189  add_action (new restore_var_elem<T> (var, val));
190  }
191 
192  operator bool (void) const { return ! empty (); }
193 
194  virtual void run_first (void) = 0;
195 
196  void run (size_t num);
197 
198  void run (void) { run (size ()); }
199 
200  virtual void discard_first (void) = 0;
201 
202  void discard (size_t num)
203  {
204  if (num > size ())
205  num = size ();
206 
207  for (size_t i = 0; i < num; i++)
208  discard_first ();
209  }
210 
211  void discard (void) { discard (size ()); }
212 
213  virtual size_t size (void) const = 0;
214 
215  bool empty (void) const { return size () == 0; }
216 
217  protected:
218 
219  virtual void add_action (elem *new_elem) = 0;
220  };
221 }
222 
223 #endif
delete_ptr_elem(const delete_ptr_elem &)=delete
virtual ~elem(void)=default
elem(const elem &)=delete
fcn_elem(F &&fcn, Args &&... args)
std::function< void(void)> m_fcn
restore_var_elem(const restore_var_elem &)=delete
void add_method(T &obj, void(T::*method)(Params...), Args &&... args)
virtual size_t size(void) const =0
action_container(const action_container &)=delete
virtual void run_first(void)=0
void add_method(T *obj, void(T::*method)(Params...), Args &&... args)
void add_fcn(void(*fcn)(Params...), Args &&... args)
void add(F &&fcn, Args &&... args)
virtual void add_action(elem *new_elem)=0
virtual ~action_container(void)=default
virtual void discard_first(void)=0
void protect_var(T &var, const T &val)