RTXI  2.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
workspace.cpp
Go to the documentation of this file.
1 /*
2  The Real-Time eXperiment Interface (RTXI)
3  Copyright (C) 2011 Georgia Institute of Technology, University of Utah, Weill Cornell Medical College
4 
5  This program is free software: you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation, either version 3 of the License, or
8  (at your option) any later version.
9 
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 
18 */
19 
20 #include <algorithm>
21 #include <debug.h>
22 #include <event.h>
23 #include <rt.h>
24 #include <sstream>
25 #include <workspace.h>
26 
27 namespace
28 {
29 class ParameterChangeEvent:public RT::Event
30 {
31 
32 public:
33  ParameterChangeEvent(Settings::Object::ID,size_t,double,double *);
34  ~ParameterChangeEvent(void);
35  int callback(void);
36 
37 private:
38  Settings::Object::ID object;
39  size_t index;
40  double value;
41  double *data;
42 }; // class ParameterChangeEvent
43 }; // namespace
44 
45 ParameterChangeEvent::ParameterChangeEvent(Settings::Object::ID id,size_t i,double v,double *d)
46  : object(id), index(i), value(v), data(d) {}
47 
48 ParameterChangeEvent::~ParameterChangeEvent(void) {}
49 
50 int ParameterChangeEvent::callback(void)
51 {
52 
53  if (*data == value)
54  return 0;
55 
56  *data = value;
57 
59  event.setParam("object",(void *)object);
60  event.setParam("index",(void *)index);
61  event.setParam("value",(void *)data);
62  ::Event::Manager::getInstance()->postEventRT(&event);
63 
64  return 0;
65 }
66 
68  : IO::Block(name,d,n)
69 {
70  size_t count[] = { 0, 0, 0, 0 };
71  for (size_t i=0; i<n; ++i)
72  switch (d[i].flags & (PARAMETER|STATE|EVENT|COMMENT))
73  {
74  case PARAMETER:
75  count[0]++;
76  break;
77  case STATE:
78  count[1]++;
79  break;
80  case EVENT:
81  count[2]++;
82  break;
83  case COMMENT:
84  count[3]++;
85  break;
86  }
87 
88  parameter = std::vector<var_t>(count[0]);
89  state = std::vector<var_t>(count[1]);
90  event = std::vector<var_t>(count[2]);
91  comment = std::vector<comment_t>(count[3]);
92 
93  size_t i[] = { 0, 0, 0, 0 };
94  for (size_t j=0; j<n; ++j)
95  {
96  switch (d[j].flags & (PARAMETER|STATE|EVENT|COMMENT))
97  {
98  case PARAMETER:
99  parameter[i[0]].name = d[j].name;
100  parameter[i[0]].description = d[j].description;
101  parameter[i[0]].data = new double;
102  i[0]++;
103  break;
104  case STATE:
105  state[i[1]].name = d[j].name;
106  state[i[1]].description = d[j].description;
107  state[i[1]].data = 0;
108  i[1]++;
109  break;
110  case EVENT:
111  event[i[2]].name = d[j].name;
112  event[i[2]].description = d[j].description;
113  event[i[2]].data = 0;
114  i[2]++;
115  break;
116  case COMMENT:
117  comment[i[3]].name = d[j].name;
118  comment[i[3]].description = d[j].description;
119  comment[i[3]].comment = "";
120  i[3]++;
121  break;
122  }
123  }
124 
126 }
127 
129 {
131 
132  for (std::vector<var_t>::iterator i = parameter.begin(), end = parameter.end(); i != end; ++i)
133  delete i->data;
134 }
135 
137 {
138  if (type & (INPUT|OUTPUT))
139  return IO::Block::getCount(type);
140  if (type & PARAMETER)
141  return parameter.size();
142  if (type & STATE)
143  return state.size();
144  if (type & EVENT)
145  return event.size();
146  if (type & COMMENT)
147  return comment.size();
148 
149  return 0;
150 }
151 
152 std::string Workspace::Instance::getName(IO::flags_t type,size_t n) const
153 {
154  if (type & (INPUT|OUTPUT))
155  return IO::Block::getName(type,n);
156  if (type & PARAMETER && n < parameter.size())
157  return parameter[n].name;
158  if (type & STATE && n < state.size())
159  return state[n].name;
160  if (type & EVENT && n < event.size())
161  return event[n].name;
162  if (type & COMMENT && n < comment.size())
163  return comment[n].name;
164 
165  return "";
166 }
167 
168 std::string Workspace::Instance::getDescription(IO::flags_t type,size_t n) const
169 {
170  if (type & PARAMETER && n < parameter.size())
171  return parameter[n].description;
172  if (type & STATE && n < state.size())
173  return state[n].description;
174  if (type & EVENT && n < event.size())
175  return event[n].description;
176  if (type & COMMENT && n < comment.size())
177  return comment[n].description;
178 
179  return "";
180 }
181 
182 double Workspace::Instance::getValue(IO::flags_t type,size_t n) const
183 {
184  if (type & INPUT)
185  return input(n);
186  if (type & OUTPUT)
187  return output(n);
188  if (type & PARAMETER && n < parameter.size() && parameter[n].data)
189  return *parameter[n].data;
190  if (type & STATE && n < state.size() && state[n].data)
191  return *state[n].data;
192  if (type & EVENT && n < event.size() && event[n].data)
193  return *event[n].data;
194  if (type & COMMENT && n < comment.size())
195  {
196  std::istringstream sstr(comment[n].comment);
197  double value;
198  sstr >> value;
199  return value;
200  }
201  return 0.0;
202 }
203 
204 std::string Workspace::Instance::getValueString(IO::flags_t type,size_t n) const
205 {
206 
207  if (type & (INPUT | OUTPUT | PARAMETER | STATE | EVENT))
208  {
209  std::ostringstream value;
210 
211  if (type & INPUT)
212  value << input(n);
213  if (type & OUTPUT)
214  value << output(n);
215  if (type & PARAMETER && n < parameter.size() && parameter[n].data)
216  value << *parameter[n].data;
217  if (type & STATE && n < state.size() && state[n].data)
218  value << *state[n].data;
219  if (type & EVENT && n < event.size() && event[n].data)
220  value << *event[n].data;
221 
222  return value.str();
223  }
224 
225  if (type & COMMENT && n < comment.size())
226  return comment[n].comment;
227 
228  return "";
229 }
230 
231 void Workspace::Instance::setValue(size_t n,double value)
232 {
233  if (n >= parameter.size() || !parameter[n].data)
234  return;
235 
236  if (RT::OS::isRealtime() && *parameter[n].data != value)
237  {
238  *parameter[n].data = value;
239 
241  event.setParam("object",(void *)getID());
242  event.setParam("index",(void *)n);
243  event.setParam("value",(void *)parameter[n].data);
244  ::Event::Manager::getInstance()->postEventRT(&event);
245  }
246  else
247  {
248  ParameterChangeEvent event(getID(),n,value,parameter[n].data);
250  }
251 }
252 
253 void Workspace::Instance::setComment(size_t n,std::string newComment)
254 {
255  if (n >= comment.size())
256  return;
257 
258  comment[n].comment = newComment;
259 }
260 
262 {
263  if (type & PARAMETER && n < parameter.size())
264  return parameter[n].data;
265  if (type & STATE && n < state.size())
266  return state[n].data;
267  if (type & EVENT && n < event.size())
268  return event[n].data;
269  return 0;
270 }
271 
272 void Workspace::Instance::setData(IO::flags_t type,size_t n,double *data)
273 {
274  if (type & PARAMETER && n < parameter.size())
275  parameter[n].data = data;
276  if (type & STATE && n < state.size())
277  state[n].data = data;
278  if (type & EVENT && n < event.size())
279  event[n].data = data;
280 }
281 
282 void Workspace::Manager::foreachWorkspace(void (*callback)(Workspace::Instance *,void *),void *param)
283 {
284  Mutex::Locker lock(&mutex);
285  for (std::list<Instance *>::iterator i = instanceList.begin(); i != instanceList.end(); ++i)
286  callback(*i,param);
287 }
288 
290 {
291  if (!workspace)
292  {
293  ERROR_MSG("Workspace::Manager::insertWorkspace : invalid workspace\n");
294  return;
295  }
296 
297  Mutex::Locker lock(&mutex);
298 
299  if (std::find(instanceList.begin(),instanceList.end(),workspace) != instanceList.end())
300  {
301  ERROR_MSG("Workspace::Manager::insertWorkspace : workspace already present\n");
302  return;
303  }
304 
305  instanceList.push_back(workspace);
306 }
307 
309 {
310  if (!workspace)
311  {
312  ERROR_MSG("Workspace::Manager::removeWorkspace : invalid workspace\n");
313  return;
314  }
315 
316  Mutex::Locker lock(&mutex);
317  instanceList.remove(workspace);
318 }
319 
320 static Mutex mutex;
322 
324 {
325  if (instance)
326  return instance;
327 
328  /*************************************************************************
329  * Seems like alot of hoops to jump through, but static allocation isn't *
330  * thread-safe. So effort must be taken to ensure mutual exclusion. *
331  *************************************************************************/
332 
333  Mutex::Locker lock(&::mutex);
334  if (!instance)
335  {
336  static Manager manager;
337  instance = &manager;
338  }
339 
340  return instance;
341 }
static Manager * instance
Definition: workspace.h:263
void removeWorkspace(Instance *)
Definition: workspace.cpp:308
void insertWorkspace(Instance *)
Definition: workspace.cpp:289
std::string name
Definition: io.h:58
std::string getDescription(IO::flags_t type, size_t index) const
Definition: workspace.cpp:168
void foreachWorkspace(void(*callback)(Instance *, void *), void *param)
Definition: workspace.cpp:282
std::vector< var_t > parameter
Definition: workspace.h:203
Instance(std::string name, variable_t *variables, size_t size)
Definition: workspace.cpp:67
bool isRealtime(void)
std::string description
Definition: io.h:59
std::vector< comment_t > comment
Definition: workspace.h:214
Definition: mutex.h:28
unsigned long ID
Definition: settings.h:53
#define ERROR_MSG(fmt, args...)
Definition: debug.h:41
Connection Oriented Classes.
Definition: io.h:34
static Manager * getInstance(void)
Definition: event.cpp:149
double * getData(IO::flags_t type, size_t index)
Definition: workspace.cpp:261
static Manager * getInstance(void)
Definition: workspace.cpp:323
virtual int callback(void)=0
const char * WORKSPACE_PARAMETER_CHANGE_EVENT
Definition: event.cpp:35
std::string getName(void) const
Definition: io.h:214
unsigned long flags_t
Definition: io.h:40
size_t getCount(IO::flags_t type) const
Definition: workspace.cpp:136
Definition: rt.h:70
std::vector< var_t > state
Definition: workspace.h:204
void setValue(size_t index, double value)
Definition: workspace.cpp:231
void setData(IO::flags_t type, size_t index, double *value)
Definition: workspace.cpp:272
std::string getValueString(IO::flags_t type, size_t index) const
Definition: workspace.cpp:204
virtual size_t getCount(flags_t type) const
Definition: io.cpp:82
static System * getInstance(void)
Definition: rt.cpp:361
void setComment(size_t index, std::string comment)
Definition: workspace.cpp:253
int postEvent(Event *event, bool blocking=true)
Definition: rt.cpp:218
double getValue(IO::flags_t type, size_t index) const
Definition: workspace.cpp:182
virtual ~Instance(void)
Definition: workspace.cpp:128