1 /*
2  *  model.h
3  *
4  *  This file is part of NEST.
5  *
6  *  Copyright (C) 2004 The NEST Initiative
7  *
8  *  NEST is free software: you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation, either version 2 of the License, or
11  *  (at your option) any later version.
12  *
13  *  NEST is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with NEST.  If not, see <http://www.gnu.org/licenses/>.
20  *
21  */
22 
23 #ifndef MODEL_H
24 #define MODEL_H
25 
26 // C++ includes:
27 #include <new>
28 #include <string>
29 #include <vector>
30 
31 // Includes from libnestutil:
32 #include "allocator.h"
33 
34 // Includes from nestkernel:
35 #include "node.h"
36 
37 // Includes from sli:
38 #include "dictutils.h"
39 
40 namespace nest
41 {
42 class TimeConverter;
43 
44 /**
45  * Base class for all Models.
46  * Each Node class is associated with a corresponding Model
47  * class. The Model class is responsible for the creation and class
48  * wide parametrisation of its associated Node objects.
49  *
50  * class Model manages the thread-sorted memory pool of the model.
51  * The default constructor uses one thread as default. Use set_threads() to
52  * use more than one thread.
53  * @ingroup user_interface
54  * @see Node
55  */
56 class Model
57 {
58 public:
59   Model( const std::string& name );
Model(const Model & m)60   Model( const Model& m )
61     : name_( m.name_ )
62     , type_id_( m.type_id_ )
63     , memory_( m.memory_ )
64   {
65   }
66 
~Model()67   virtual ~Model()
68   {
69   }
70 
71   /**
72    * Create clone with new name.
73    */
74   virtual Model* clone( const std::string& ) const = 0;
75 
76   /**
77    * Set number of threads based on number set in network.
78    * As long as no nodes of the model have been allocated, the number
79    * of threads may be changed.
80    * @note Requires that network pointer in NestModule is initialized.
81    */
82   void set_threads();
83 
84   /**
85    * Allocate new Node and return its pointer.
86    * allocate() is not const, because it
87    * is allowed to modify the Model object for
88    * 'administrative' purposes.
89    */
90   Node* allocate( thread t );
91 
92   void free( thread t, Node* );
93 
94   /**
95    * Deletes all nodes which belong to this model.
96    */
97 
98   void clear();
99 
100   /**
101    * Reserve memory for at least n additional Nodes.
102    * A number of memory managers work more efficiently if they have
103    * an idea about the number of Nodes to be allocated.
104    * This function prepares the memory manager for the subsequent
105    * allocation of n additional Nodes.
106    * @param t Thread for which the Nodes are reserved.
107    * @param n Number of Nodes to be allocated.
108    */
109   void reserve_additional( thread t, size_t n );
110 
111   /**
112    * Return name of the Model.
113    * This function returns the name of the Model as C++ string. The
114    * name is defined by the constructor. The result is identical to the value
115    * of Node::get_name();
116    * @see Model::Model()
117    * @see Node::get_name()
118    */
119   std::string get_name() const;
120 
121   /**
122    * Return the available memory. The result is given in number of elements,
123    * not in bytes.
124    * Note that this function reports a sum over all threads.
125    */
126   size_t mem_available();
127 
128   /**
129    * Return the memory capacity. The result is given in number of elements,
130    * not in bytes.
131    * Note that this function reports a sum over all threads.
132    */
133   size_t mem_capacity();
134 
135   virtual bool has_proxies() = 0;
136   virtual bool one_node_per_process() = 0;
137   virtual bool is_off_grid() = 0;
138   virtual void calibrate_time( const TimeConverter& tc ) = 0;
139 
140   /**
141    * Change properties of the prototype node according to the
142    * entries in the dictionary.
143    * @param d Dictionary with named parameter settings.
144    * @ingroup status_interface
145    */
146   void set_status( DictionaryDatum );
147 
148   /**
149    * Export properties of the prototype node by setting
150    * entries in the status dictionary.
151    * @param d Dictionary.
152    * @ingroup status_interface
153    */
154   DictionaryDatum get_status( void );
155 
156   virtual port send_test_event( Node&, rport, synindex, bool ) = 0;
157 
158   virtual void sends_secondary_event( GapJunctionEvent& ge ) = 0;
159   virtual void sends_secondary_event( InstantaneousRateConnectionEvent& re ) = 0;
160   virtual void sends_secondary_event( DiffusionConnectionEvent& de ) = 0;
161   virtual void sends_secondary_event( DelayedRateConnectionEvent& re ) = 0;
162 
163   /**
164    * Check what type of signal this model is sending.
165    * Required so that proxynode can formward this call
166    * to model that in turn delegates the call to the underlying
167    * prototype.
168    */
169   virtual SignalType sends_signal() const = 0;
170 
171   /**
172    * Return the size of the prototype.
173    */
174   virtual size_t get_element_size() const = 0;
175 
176   /**
177    * Return const reference to the prototype.
178    */
179   virtual Node const& get_prototype( void ) const = 0;
180 
181   /**
182    * Set the model id on the prototype.
183    */
184   virtual void set_model_id( int ) = 0;
185 
186   /**
187    * Get the model id from the prototype.
188    */
189   virtual int get_model_id() = 0;
190 
191   /**
192    * Issue deprecation warning on first call if model is deprecated.
193    *
194    * @param calling function
195    */
196   virtual void deprecation_warning( const std::string& ) = 0;
197 
198   /**
199    * Set the model id on the prototype.
200    */
201   void
set_type_id(index id)202   set_type_id( index id )
203   {
204     type_id_ = id;
205   }
206 
207   index
get_type_id()208   get_type_id() const
209   {
210     return type_id_;
211   }
212 
213 private:
214   virtual void set_status_( DictionaryDatum ) = 0;
215 
216   virtual DictionaryDatum get_status_() = 0;
217 
218 
219   /**
220    * Set the number of threads.
221    * @see set_threads()
222    */
223   void set_threads_( thread t );
224 
225   /**
226    * Initialize the pool allocator with the Node specific values.
227    */
228   virtual void init_memory_( sli::pool& ) = 0;
229 
230   /**
231    * Allocate a new object at the specified memory position.
232    */
233   virtual Node* allocate_( void* ) = 0;
234 
235   /**
236    * Name of the Model.
237    * This name will be used to identify all Nodes which are
238    * created by this model object.
239    */
240   std::string name_;
241 
242   /**
243    * Identifier of the model C++ type.
244    * For pristine models, the type_id equals the model_id.
245    * For copied models, the type_id equals the type_id of the base model.
246    * This number is needed to automatically save and restore copied models.
247    */
248   index type_id_;
249 
250   /**
251    * Memory for all nodes sorted by threads.
252    */
253   std::vector< sli::pool > memory_;
254 };
255 
256 
257 inline Node*
allocate(thread t)258 Model::allocate( thread t )
259 {
260   assert( ( size_t ) t < memory_.size() );
261   return allocate_( memory_[ t ].alloc() );
262 }
263 
264 inline void
free(thread t,Node * n)265 Model::free( thread t, Node* n )
266 {
267   assert( ( size_t ) t < memory_.size() );
268   memory_[ t ].free( n );
269 }
270 
271 inline std::string
get_name()272 Model::get_name() const
273 {
274   return name_;
275 }
276 }
277 #endif
278