MocoExtendProblem: Interface Between OpenSim and MATLAB for Rapidly Developing Direct Collocation Goals in Moco 1.1.0
add custom Moco goals to existing matlab scripts
dispatch.h
Go to the documentation of this file.
1
60#ifndef INCLUDE_MEXPLUS_DISPATCH_H_
61#define INCLUDE_MEXPLUS_DISPATCH_H_
62
63#include <mex.h>
64#include <map>
65#include <memory>
66#include <string>
67
68#ifndef MEXPLUS_AT_EXIT
69#define MEXPLUS_AT_EXIT
70#endif
71
72#ifndef MEXPLUS_AT_INIT
73#define MEXPLUS_AT_INIT
74#endif
75
76#ifndef MEXPLUS_AT_ERROR
77#define MEXPLUS_AT_ERROR(name)
78#endif
79
80namespace mexplus {
81
82typedef bool OperationNameAdmitter(const std::string& name);
83
85inline void CreateOperation(OperationNameAdmitter* admitter,
86 OperationCreator* creator);
87
90class Operation {
91 public:
94 virtual ~Operation() {}
97 virtual void operator()(int nlhs,
98 mxArray *plhs[],
99 int nrhs,
100 const mxArray *prhs[]) = 0;
101};
102
106 public:
110 CreateOperation(admitter, this);
111 }
114 virtual ~OperationCreator() {}
117 virtual Operation* create() = 0;
118};
119
123template <class OperationClass>
125 public:
127 const char* tag) :
128 OperationCreator(admitter) {
129 if (tag)
130 mexPrintf("Tag: %s\n", tag);
131 }
132 virtual Operation* create() { return new OperationClass; }
133};
134
138 public:
139 typedef std::map<OperationNameAdmitter*, OperationCreator*> RegistryMap;
140
143 friend void CreateOperation(OperationNameAdmitter* admitter,
144 OperationCreator* creator);
147 static Operation* create(const std::string& name) {
148 RegistryMap::const_iterator it = find(name);
149 return (it == registry()->end()) ?
150 static_cast<Operation*>(NULL) : it->second->create();
151 }
155 static RegistryMap registry_table;
156 return &registry_table;
157 }
158
159 private:
160 static RegistryMap::const_iterator find(const std::string& name) {
161 RegistryMap::const_iterator it;
162 for (it = registry()->begin(); it != registry()->end(); it++) {
163 if ((*it->first)(name))
164 return it;
165 }
166 return it;
167 }
168};
169
173 OperationCreator* creator) {
174 OperationFactory::registry()->insert(std::make_pair(admitter, creator));
175}
176
210template<class T>
211class Session {
212 public:
213 typedef std::map<intptr_t, std::shared_ptr<T> > InstanceMap;
214
217 static intptr_t create(T* instance) {
218 InstanceMap* instances = getInstances();
219 intptr_t id = reinterpret_cast<intptr_t>(instance);
220 instances->insert(std::make_pair(id, std::shared_ptr<T>(instance)));
221 mexLock();
222 return id;
223 }
226 static void destroy(intptr_t id) {
227 getInstances()->erase(id);
228 mexUnlock();
229 }
230 static void destroy(const mxArray* pointer) {
231 destroy(getIntPointer(pointer));
232 }
235 static T* get(intptr_t id) {
236 InstanceMap* instances = getInstances();
237 typename InstanceMap::iterator instance = instances->find(id);
238 if (instance == instances->end())
239 mexErrMsgIdAndTxt("mexplus:session:notFound",
240 "Invalid id %d. Did you create?",
241 id);
242 return instance->second.get();
243 }
244 static T* get(const mxArray* pointer) {
245 return get(getIntPointer(pointer));
246 }
249 static const T& getConst(intptr_t id) {
250 return *get(id);
251 }
252 static const T& getConst(const mxArray* pointer) {
253 return getConst(getIntPointer(pointer));
254 }
257 static bool exist(intptr_t id) {
258 InstanceMap* instances = getInstances();
259 typename InstanceMap::iterator instance = instances->find(id);
260 return instance != instances->end();
261 }
262 static bool exist(const mxArray* pointer) {
263 return exist(getIntPointer(pointer));
264 }
267 static void clear() {
268 for (int i = 0; i < getInstances()->size(); ++i)
269 mexUnlock();
270 getInstances()->clear();
271 }
274 static const InstanceMap& getInstanceMap() { return *getInstances(); }
275
276 private:
283 static intptr_t getIntPointer(const mxArray* pointer) {
284 if (mxIsEmpty(pointer))
285 mexErrMsgIdAndTxt("mexplus:session:invalidType", "Id is empty.");
286 if (sizeof(intptr_t) == 8 && !mxIsInt64(pointer) && !mxIsUint64(pointer))
287 mexErrMsgIdAndTxt("mexplus:session:invalidType",
288 "Invalid id type %s.",
289 mxGetClassName(pointer));
290 if (sizeof(intptr_t) == 4 && !mxIsInt32(pointer) && !mxIsUint32(pointer))
291 mexErrMsgIdAndTxt("mexplus:session:invalidType",
292 "Invalid id type %s.",
293 mxGetClassName(pointer));
294 return *reinterpret_cast<intptr_t*>(mxGetData(pointer));
295 }
299 static InstanceMap instances;
300 return &instances;
301 }
302};
303
304} // namespace mexplus
305
315#define MEX_DEFINE(name) \
316class Operation_##name : public mexplus::Operation { \
317 public: \
318 virtual void operator()(int nlhs, \
319 mxArray *plhs[], \
320 int nrhs, \
321 const mxArray *prhs[]); \
322 private: \
323 static bool Operation_Admitter(const std::string& func) { \
324 return func == #name;\
325 } \
326 static const mexplus::OperationCreatorImpl<Operation_##name> creator_; \
327}; \
328const mexplus::OperationCreatorImpl<Operation_##name> \
329 Operation_##name::creator_(Operation_##name::Operation_Admitter, NULL); \
330void Operation_##name::operator()
331
345#define MEX_DEFINE2(name, admitter) \
346static const char* tag = NULL /*#name*/; \
347class Operation_##name : public mexplus::Operation { \
348 public: \
349 virtual void operator()(int nlhs, \
350 mxArray *plhs[], \
351 int nrhs, \
352 const mxArray *prhs[]); \
353 private: \
354 static const mexplus::OperationCreatorImpl<Operation_##name> creator_; \
355}; \
356const mexplus::OperationCreatorImpl<Operation_##name> \
357 Operation_##name::creator_(admitter, tag); \
358void Operation_##name::operator()
359
362#define MEX_DISPATCH \
363void mexFunction(int nlhs, mxArray *plhs[], \
364 int nrhs, const mxArray *prhs[]) { \
365 MEXPLUS_AT_INIT;\
366 if (nrhs < 1 || !mxIsChar(prhs[0])) \
367 mexErrMsgIdAndTxt("mexplus:dispatch:argumentError", \
368 "Invalid argument: missing operation."); \
369 std::string operation_name(\
370 mxGetChars(prhs[0]), \
371 mxGetChars(prhs[0]) + mxGetNumberOfElements(prhs[0])); \
372 std::unique_ptr<mexplus::Operation> operation(\
373 mexplus::OperationFactory::create(operation_name)); \
374 if (operation.get() == NULL) { \
375 MEXPLUS_AT_ERROR(operation_name); \
376 mexErrMsgIdAndTxt("mexplus:dispatch:argumentError", \
377 "Invalid operation: %s", operation_name.c_str()); \
378 } \
379 (*operation)(nlhs, plhs, nrhs - 1, prhs + 1); \
380 MEXPLUS_AT_EXIT; \
381}
382
383#endif // INCLUDE_MEXPLUS_DISPATCH_H_
Base class for operation creators.
Definition dispatch.h:105
OperationCreator(OperationNameAdmitter *admitter)
Register an operation in the constructor.
Definition dispatch.h:109
virtual Operation * create()=0
Implementation must return a new instance of the operation.
virtual ~OperationCreator()
Destructor.
Definition dispatch.h:114
Implementation of the operation creator to be used as composition in an Operator class.
Definition dispatch.h:124
virtual Operation * create()
Implementation must return a new instance of the operation.
Definition dispatch.h:132
OperationCreatorImpl(OperationNameAdmitter *admitter, const char *tag)
Definition dispatch.h:126
Factory class for operations.
Definition dispatch.h:137
static RegistryMap::const_iterator find(const std::string &name)
Definition dispatch.h:160
friend void CreateOperation(OperationNameAdmitter *admitter, OperationCreator *creator)
Register a new creator.
Definition dispatch.h:172
std::map< OperationNameAdmitter *, OperationCreator * > RegistryMap
Definition dispatch.h:139
static Operation * create(const std::string &name)
Create a new instance of the registered operation.
Definition dispatch.h:147
static RegistryMap * registry()
Obtain a pointer to the registration table.
Definition dispatch.h:154
Abstract operation class.
Definition dispatch.h:90
virtual void operator()(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])=0
Execute the operation.
virtual ~Operation()
Destructor.
Definition dispatch.h:94
Key-value storage to make a stateful MEX function.
Definition dispatch.h:211
std::map< intptr_t, std::shared_ptr< T > > InstanceMap
Definition dispatch.h:213
~Session()
Definition dispatch.h:280
static void clear()
Clear all session instances.
Definition dispatch.h:267
static intptr_t getIntPointer(const mxArray *pointer)
Convert mxArray to intptr_t.
Definition dispatch.h:283
static const T & getConst(const mxArray *pointer)
Definition dispatch.h:252
static void destroy(const mxArray *pointer)
Definition dispatch.h:230
static bool exist(intptr_t id)
Check if the given id exists.
Definition dispatch.h:257
static const InstanceMap & getInstanceMap()
Get instance map.
Definition dispatch.h:274
static bool exist(const mxArray *pointer)
Definition dispatch.h:262
static T * get(intptr_t id)
Retrieve an instance or throw if no instance is found.
Definition dispatch.h:235
static InstanceMap * getInstances()
Get static instance storage.
Definition dispatch.h:298
Session()
Constructor prohibited.
Definition dispatch.h:279
static T * get(const mxArray *pointer)
Definition dispatch.h:244
static void destroy(intptr_t id)
Destroy an instance.
Definition dispatch.h:226
static intptr_t create(T *instance)
Create an instance.
Definition dispatch.h:217
static const T & getConst(intptr_t id)
Retrieve a const instance or throw if no instance is found.
Definition dispatch.h:249
MEX function arguments helper library.
Definition arguments.h:40
bool OperationNameAdmitter(const std::string &name)
Definition dispatch.h:82
void CreateOperation(OperationNameAdmitter *admitter, OperationCreator *creator)
Register a new creator in OperationFactory.
Definition dispatch.h:172