SYNOPSIS
object shadow(object obj, int flag)
BESCHREIBUNG
Damit wird das aktuelle Objekt dem Objekt <obj> als Shadow
uebergeworfen. Bei Erfolg liefert es 1, sonst 0 zurueck.
Das aufrufende Objekt muss vom Master-Objekt die Erlaubnis haben,
als Shadow zu wirken. Normalerweise kann einem Objekt, das
query_prevent_shadow() == 1 zurueck liefert, kein Shadow
uebergeworfen werden. In diesem Fall liefert shadow() 0 zurueck,
sonst das Objekt, dem der Shadow uebergeworfen wurde.
shadow() schlaeft fehl, wenn:
- der Shadow vesucht, eine "nomask" definierte Funktion zu
ueberlagern,
- wenn im Praeprozessor #pragma no_shadow gesetzt ist,
- wenn das aufrufende Objekt bereits ein Shadow ist,
- wenn das aufrufende Objekt selbst einen Shadow uebergeworfen hat,
- wenn das aufrufende Objekt ueber ein Environment verfuegt,
- wenn das Zielobjekt <obj> selbst ein Shadow ist.
Wenn ein Objekt A einem Objekt B als Shadow uebergeworfen wird,
werden alle call_other() Aufrufe fuer B an A umgeleitet. Wenn A die
Funktion, die von call_other() aufgerufen wird, nicht definiert hat,
wird der Aufruf an B weitergeleitet. Es gibt also nur ein Objekt,
welches call_other() Aufrufe fuer B machen kann: das Objekt A. Nicht
einmal das Objekt B kann einen call_other() auf sich selbst machen.
Hingegen werden alle normalen (internen) Funktionsaufrufe innerhalb
von B werden wie gewohnt innerhalb von B bearbeitet.
BEISPIELE
Mit drei Objekten a.c, b.c und c.c:
--- a.c ---
void fun() {
debug_message(sprintf("%O [a] fun()\n", this_object()));
}
void fun3() {
debug_message(sprintf("%O [a] fun3()\n", this_object()));
}
--- b.c ---
int fun() {
debug_message(sprintf("%O [b] fun()\n", this_object()));
find_object("a")->fun();
}
void fun2() {
debug_message(sprintf("%O [b] fun2()\n", this_object()));
find_object("a")->fun3();
this_object()->fun3();
}
void do_shadow(object target) { shadow(target, 1); }
--- c.c ---
int fun() {
debug_message(sprintf("%O [c] fun()\n", this_object()));
find_object("a")->fun();
}
void fun3() {
debug_message(sprintf("%O [c] fun3()\n", this_object()));
}
void do_shadow(object target) { shadow(target, 1); }
Es wird nun folgender Code aufgerufen:
object a, b, c;
a = load_object("a");
b = load_object("b");
c = load_object("c");
b->do_shadow(a);
c->do_shadow(a);
debug_message("--- a->fun() ---\n");
a->fun();
debug_message("--- b->fun() ---\n");
b->fun();
debug_message("--- c->fun() ---\n");
c->fun();
debug_message("--- b->fun2() ---\n");
b->fun2();
Das ergibt diesen Output:
--- a->fun() ---
/c [c] fun()
/b [b] fun()
/a [a] fun()
--- b->fun() ---
/c [c] fun()
/b [b] fun()
/a [a] fun()
--- c->fun() ---
/c [c] fun()
/b [b] fun()
/a [a] fun()
--- b->fun2() ---
/b [b] fun2()
/a [a] fun3()
/c [c] fun3()
Merke: der erste Aufruf in b::fun2() findet zuerst c::fun3()!
Der Grund ist, dass fuer Aufrufe aus b fuer a der Treiber
annimmt, dass alle Shadows vor c schon ihre Chance hatten. Der
zweite Aufruf hingegen ergeht an b selbst, das der Treiber als
vom Shadow c ueberlagert erkennt.
GESCHICHTE
Bis 3.2.1@46 fuehrte die Zerstoerung eines Objekts, dem ein Shadow
uebergeworfen war, auch zur Zerstoerung aller seiner Shadows.
Seit 3.2.1@47 ueberleben Shadows die Zerstoerung des Objektes, dem
sie uebergeworfen sind (ausser, die wird von prepare_destruct()
manuell erledigt).
Seit LDMud 3.2.8 koenne sich Objekte dank #pragma no_shadow gezielt
davor schuetzen, einen Shadow uebergeworfen zu bekommen.
SIEHE AUCH
query_shadowing(E), unshadow(E), query_allow_shadow(M)
|