1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
|
/*************************************************************************
* Copyright (C) 2004 by Olivier Galizzi *
* olivier.galizzi@imag.fr *
* Copyright (C) 2004 by Janek Kozicki *
* cosurgi@berlios.de *
* *
* This program is free software; it is licensed under the terms of the *
* GNU General Public License v2 or later. See file LICENSE for details. *
*************************************************************************/
#pragma once
#include <lib/multimethods/FunctorWrapper.hpp>
#include <lib/serialization/Serializable.hpp>
#include <core/Timing.hpp>
namespace yade { // Cannot have #include directive inside.
class TimingDeltas;
class Scene;
class Functor : public Serializable {
public:
virtual vector<std::string> getFunctorTypes() const { throw; }
shared_ptr<TimingDeltas> timingDeltas;
//! updated before every dispatch loop by the dispatcher; DO NOT ABUSE access to scene, except for getting global variables like scene->dt.
Scene* scene;
virtual ~Functor() {}; // defined in Dispatcher.cpp
// clang-format off
YADE_CLASS_BASE_DOC_ATTRS_CTOR_PY(Functor,Serializable,"Function-like object that is called by Dispatcher, if types of arguments match those the Functor declares to accept.",
((string,label,,,"Textual label for this object; must be a valid python identifier, you can refer to it directly from python.")),
/*ctor*/
#ifdef USE_TIMING_DELTAS
timingDeltas=shared_ptr<TimingDeltas>(new TimingDeltas);
#endif
,
.def_readonly("timingDeltas",&Functor::timingDeltas,"Detailed information about timing inside the Dispatcher itself. Empty unless enabled in the source code and O.timingEnabled==True.")
.add_property("bases",&Functor::getFunctorTypes,"Ordered list of types (as strings) this functor accepts.")
);
// clang-format on
};
REGISTER_SERIALIZABLE(Functor);
template <class _DispatchType1, class _ReturnType, class _ArgumentTypes> class Functor1D : public Functor, public FunctorWrapper<_ReturnType, _ArgumentTypes> {
public:
typedef _DispatchType1 DispatchType1;
typedef _ReturnType ReturnType;
typedef _ArgumentTypes ArgumentTypes;
#define FUNCTOR1D(type1) \
public: \
std::string get1DFunctorType1(void) const override { return string(#type1); } \
int checkArgTypes(const shared_ptr<DispatchType1>& arg1) const { return (bool)YADE_PTR_DYN_CAST<type1>(arg1) ? 1 : 0; }
virtual std::string get1DFunctorType1(void) const
{
throw runtime_error("Class " + this->getClassName() + " did not use FUNCTOR1D to declare its argument type?");
}
vector<string> getFunctorTypes(void) const override
{
vector<string> ret;
ret.push_back(get1DFunctorType1());
return ret;
};
// check that the object can be correctly cast to the derived class handled by the functor (will be used if ever utils.createInteraction can be called with list of functors only)
// virtual bool checkArgTypes(const shared_ptr<DispatchType1>& arg1){ throw runtime_error("Class "+this->getClassName()+" did not use FUNCTOR1D to declare its argument type?"); }
REGISTER_CLASS_AND_BASE(Functor1D, Functor FunctorWrapper);
/* do not REGISTER_ATTRIBUTES here, since we are template; derived classes should call REGISTER_ATTRIBUTES(Functor,(their)(own)(attributes)), bypassing Functor1D */
};
template <class _DispatchType1, class _DispatchType2, class _ReturnType, class _ArgumentTypes>
class Functor2D : public Functor, public FunctorWrapper<_ReturnType, _ArgumentTypes> {
public:
typedef _DispatchType1 DispatchType1;
typedef _DispatchType2 DispatchType2;
typedef _ReturnType ReturnType;
typedef _ArgumentTypes ArgumentTypes;
#define FUNCTOR2D(type1, type2) \
public: \
std::string get2DFunctorType1(void) const override { return string(#type1); }; \
std::string get2DFunctorType2(void) const override { return string(#type2); }; \
int checkArgTypes(const shared_ptr<DispatchType1>& arg1, const shared_ptr<DispatchType2>& arg2) const \
{ \
if (YADE_PTR_DYN_CAST<type1>(arg1) && YADE_PTR_DYN_CAST<type2>(arg2)) return 1; \
if (YADE_PTR_DYN_CAST<type1>(arg2) && YADE_PTR_DYN_CAST<type2>(arg1)) return -1; \
return 0; \
}
virtual std::string get2DFunctorType1(void) const
{
throw logic_error("Class " + this->getClassName() + " did not use FUNCTOR2D to declare its argument types?");
}
virtual std::string get2DFunctorType2(void) const
{
throw logic_error("Class " + this->getClassName() + " did not use FUNCTOR2D to declare its argument types?");
}
vector<string> getFunctorTypes() const override
{
vector<string> ret;
ret.push_back(get2DFunctorType1());
ret.push_back(get2DFunctorType2());
return ret;
};
// check that objects can be correctly cast to derived classes handled by the functor (see comment in Functor1D:: checkArgTypes)
// virtual bool checkArgTypes(const shared_ptr<DispatchType1>&, const shared_ptr<DispatchType2>&){ throw logic_error("Class "+this->getClassName()+" did not use FUNCTOR2D to declare its argument types?"); }
REGISTER_CLASS_AND_BASE(Functor2D, Functor FunctorWrapper);
/* do not REGISTER_ATTRIBUTES here, since we are template; derived classes should call REGISTER_ATTRIBUTES(Functor,(their)(own)(attributes)), bypassing Functor2D */
};
} // namespace yade
|