diff options
Diffstat (limited to 'objects/objident_controller.hh')
-rw-r--r-- | objects/objident_controller.hh | 192 |
1 files changed, 192 insertions, 0 deletions
diff --git a/objects/objident_controller.hh b/objects/objident_controller.hh new file mode 100644 index 0000000..2d83b20 --- /dev/null +++ b/objects/objident_controller.hh @@ -0,0 +1,192 @@ +#ifndef __OBJECTS_OBJIDENT_CONTROLLER_HH__ +#define __OBJECTS_OBJIDENT_CONTROLLER_HH__ + +#include "objects_parser.hh" +#include "objects_buffer.hh" +#include "common/tools.hh" + +namespace rtfl { + +namespace objects { + +/** + * \ident Filter Controller for handling `obj-ident` + * + * Motivation + * ---------- + * When using multiple inheritance in C++, the values for `this` are not + * identical in all contexts. Consider a class `C`, with `A` and `B` as base + * classes. The following code + * + * C *c = new C(); + * A *a = (A*)c; + * B *b = (B*)c; + * printf("a = %p\n", a); + * printf("b = %p\n", b); + * printf("c = %p\n", c); + * + * will output something like this: + * + * a = 0x1000 + * b = 0x1010 + * c = 0x1000 + * + * (Notice the different value of `b`.) The value of `b` will differ from `a` by + * `sizeof(A)`. + * + * For this reason, the tested program has to declare all values as identical, + * in the following way: + * + * [rtfl-obj-1.0]...:create:0x1000:A + * [rtfl-obj-1.0]...:create:0x1010:B + * [rtfl-obj-1.0]...:ident:0x1000:0x1000 + * [rtfl-obj-1.0]...:ident:0x1000:0x1010 + * [rtfl-obj-1.0]...:create:0x1000:C + * + * The first `ident` line declares `c` (the newly created instance of `C` as + * identical to `a` (`(A*)c`), the second declares it identical to `b` + * (`(B*)c`). + * + * General Approach + * ---------------- + * Handling `obj-ident` is kept out of the specific implementations of + * `ObjectsController` and implemented in a filter, `ObjIdentController`, which + * will translate all identities to actually identical identities; the output of + * `ObjIdentController` would, in the example above, be: + * + * [rtfl-obj-1.0]...:create:0x1000:A + * [rtfl-obj-1.0]...:create:0x1000:B + * [rtfl-obj-1.0]...:create:0x1000:C + * + * Details + * ------- + * The general problem is that some messages have to be changed (especially + * `...:create:0x1010:B` has to be changed to `...:create:0x1000:B`) before + * `obj-ident` is read. Even worse, it is not certain that `obj-ident` will + * follow at all: the second `obj-create` may actually define a _different_ + * object. For this reason, starting with `obj-create`, all messages are held + * back until something happens that makes it certain that _no_ related + * `obj-ident` will follow. + * + * Notice that a functioning implementation is possible even if the second + * condition is incompletely defined and implemented. + * + * (For more complex class hierarchies, it is not sufficient to react on + * `obj-ident` itself, since another `obj-ident` may follow, dealing with the + * same identities.) + * + * When is it certain that no related `obj-ident` will follow? + * + * 1. When a method is left (`obj-leave`), in which the objects have been + * created. + * 2. At the end of the stream. + * 3. (Not an exact condition, but a compromise:) After a timeout of a couple of + * seconds; after some time, it can be assumed that the construction of + * objects is over. + * + * (May be extended. See rtfl::objects::ObjIdentController::objLeave, + * rtfl::objects::ObjIdentController::ownTimeout, and + * rtfl::objects::ObjIdentController::ownFinish. + * + * Nice to have + * ------------ + * - Make timeouts configurable, also whether a timeout is triggered after a + * certain time after "obj-create" or a certain time after no commands (latter + * is currently implemented). + */ +class ObjIdentController: public ObjectsControllerBase +{ +private: + class PostController: public ObjectsControllerBase + { + tools::EquivalenceRelation *identities; + ObjectsController *successor; + + const char *mapId (const char *id); + + public: + PostController (ObjectsController *successor); + ~PostController (); + + void objMsg (tools::CommonLineInfo *info, const char *id, + const char *aspect, int prio, const char *message); + void objMark (tools::CommonLineInfo *info, const char *id, + const char *aspect, int prio, const char *message); + void objMsgStart (tools::CommonLineInfo *info, const char *id); + void objMsgEnd (tools::CommonLineInfo *info, const char *id); + void objEnter (tools::CommonLineInfo *info, const char *id, + const char *aspect, int prio, const char *funname, + const char *args); + void objLeave (tools::CommonLineInfo *info, const char *id, + const char *vals); + void objCreate (tools::CommonLineInfo *info, const char *id, + const char *klass); + void objIdent (tools::CommonLineInfo *info, const char *id1, + const char *id2); + void objNoIdent (tools::CommonLineInfo *info); + void objAssoc (tools::CommonLineInfo *info, const char *parent, + const char *child); + void objSet (tools::CommonLineInfo *info, const char *id, const char *var, + const char *val); + void objClassColor (tools::CommonLineInfo *info, const char *klass, + const char *color); + void objObjectColor (tools::CommonLineInfo *info, const char *id, + const char *color); + void objDelete (tools::CommonLineInfo *info, const char *id); + + void addIdentity (const char *id1, const char *id2); + }; + + enum { PASS = 0 }; + + ObjectsBuffer *buffer; + PostController *postController; + bool noIdent; + + int stackDepth; + bool createPending; + int minCreateStackDepth; + + void queue (); + void pass (); + +protected: + void ownTimeout (int type); + void ownFinish (); + +public: + ObjIdentController (ObjectsController *successor); + ~ObjIdentController (); + + void objMsg (tools::CommonLineInfo *info, const char *id, + const char *aspect, int prio, const char *message); + void objMark (tools::CommonLineInfo *info, const char *id, + const char *aspect, int prio, const char *message); + void objMsgStart (tools::CommonLineInfo *info, const char *id); + void objMsgEnd (tools::CommonLineInfo *info, const char *id); + void objEnter (tools::CommonLineInfo *info, const char *id, + const char *aspect, int prio, const char *funname, + const char *args); + void objLeave (tools::CommonLineInfo *info, const char *id, + const char *vals); + void objCreate (tools::CommonLineInfo *info, const char *id, + const char *klass); + void objIdent (tools::CommonLineInfo *info, const char *id1, + const char *id2); + void objNoIdent (tools::CommonLineInfo *info); + void objAssoc (tools::CommonLineInfo *info, const char *parent, + const char *child); + void objSet (tools::CommonLineInfo *info, const char *id, const char *var, + const char *val); + void objClassColor (tools::CommonLineInfo *info, const char *klass, + const char *color); + void objObjectColor (tools::CommonLineInfo *info, const char *id, + const char *color); + void objDelete (tools::CommonLineInfo *info, const char *id); +}; + +} // namespace objects + +} // namespace rtfl + +#endif // __OBJECTS_OBJIDENT_CONTROLLER_HH__ |