blob: 16ab11eb9ad4fda28aa257868f2acb722cd003ba [file] [log] [blame]
Zesstrad59c3892019-11-28 20:53:39 +01001SYNOPSIS
2 object shadow(object obj, int flag)
3
4BESCHREIBUNG
5 Damit wird das aktuelle Objekt dem Objekt <obj> als Shadow
6 uebergeworfen. Bei Erfolg liefert es 1, sonst 0 zurueck.
7
8 Das aufrufende Objekt muss vom Master-Objekt die Erlaubnis haben,
9 als Shadow zu wirken. Normalerweise kann einem Objekt, das
10 query_prevent_shadow() == 1 zurueck liefert, kein Shadow
11 uebergeworfen werden. In diesem Fall liefert shadow() 0 zurueck,
12 sonst das Objekt, dem der Shadow uebergeworfen wurde.
13
14 shadow() schlaeft fehl, wenn:
15 - der Shadow vesucht, eine "nomask" definierte Funktion zu
16 ueberlagern,
17 - wenn im Praeprozessor #pragma no_shadow gesetzt ist,
18 - wenn das aufrufende Objekt bereits ein Shadow ist,
19 - wenn das aufrufende Objekt selbst einen Shadow uebergeworfen hat,
20 - wenn das aufrufende Objekt ueber ein Environment verfuegt,
21 - wenn das Zielobjekt <obj> selbst ein Shadow ist.
22
23 Wenn ein Objekt A einem Objekt B als Shadow uebergeworfen wird,
24 werden alle call_other() Aufrufe fuer B an A umgeleitet. Wenn A die
25 Funktion, die von call_other() aufgerufen wird, nicht definiert hat,
26 wird der Aufruf an B weitergeleitet. Es gibt also nur ein Objekt,
27 welches call_other() Aufrufe fuer B machen kann: das Objekt A. Nicht
28 einmal das Objekt B kann einen call_other() auf sich selbst machen.
29 Hingegen werden alle normalen (internen) Funktionsaufrufe innerhalb
30 von B werden wie gewohnt innerhalb von B bearbeitet.
31
32BEISPIELE
33 Mit drei Objekten a.c, b.c und c.c:
34
35 --- a.c ---
36 void fun() {
37 debug_message(sprintf("%O [a] fun()\n", this_object()));
38 }
39 void fun3() {
40 debug_message(sprintf("%O [a] fun3()\n", this_object()));
41 }
42
43 --- b.c ---
44 int fun() {
45 debug_message(sprintf("%O [b] fun()\n", this_object()));
46 find_object("a")->fun();
47 }
48 void fun2() {
49 debug_message(sprintf("%O [b] fun2()\n", this_object()));
50 find_object("a")->fun3();
51 this_object()->fun3();
52 }
53
54 void do_shadow(object target) { shadow(target, 1); }
55
56 --- c.c ---
57 int fun() {
58 debug_message(sprintf("%O [c] fun()\n", this_object()));
59 find_object("a")->fun();
60 }
61 void fun3() {
62 debug_message(sprintf("%O [c] fun3()\n", this_object()));
63 }
64 void do_shadow(object target) { shadow(target, 1); }
65
66 Es wird nun folgender Code aufgerufen:
67
68 object a, b, c;
69
70 a = load_object("a");
71 b = load_object("b");
72 c = load_object("c");
73 b->do_shadow(a);
74 c->do_shadow(a);
75 debug_message("--- a->fun() ---\n");
76 a->fun();
77 debug_message("--- b->fun() ---\n");
78 b->fun();
79 debug_message("--- c->fun() ---\n");
80 c->fun();
81 debug_message("--- b->fun2() ---\n");
82 b->fun2();
83
84 Das ergibt diesen Output:
85
86 --- a->fun() ---
87 /c [c] fun()
88 /b [b] fun()
89 /a [a] fun()
90 --- b->fun() ---
91 /c [c] fun()
92 /b [b] fun()
93 /a [a] fun()
94 --- c->fun() ---
95 /c [c] fun()
96 /b [b] fun()
97 /a [a] fun()
98 --- b->fun2() ---
99 /b [b] fun2()
100 /a [a] fun3()
101 /c [c] fun3()
102
103 Merke: der erste Aufruf in b::fun2() findet zuerst c::fun3()!
104 Der Grund ist, dass fuer Aufrufe aus b fuer a der Treiber
105 annimmt, dass alle Shadows vor c schon ihre Chance hatten. Der
106 zweite Aufruf hingegen ergeht an b selbst, das der Treiber als
107 vom Shadow c ueberlagert erkennt.
108
109GESCHICHTE
110 Bis 3.2.1@46 fuehrte die Zerstoerung eines Objekts, dem ein Shadow
111 uebergeworfen war, auch zur Zerstoerung aller seiner Shadows.
112 Seit 3.2.1@47 ueberleben Shadows die Zerstoerung des Objektes, dem
113 sie uebergeworfen sind (ausser, die wird von prepare_destruct()
114 manuell erledigt).
115 Seit LDMud 3.2.8 koenne sich Objekte dank #pragma no_shadow gezielt
116 davor schuetzen, einen Shadow uebergeworfen zu bekommen.
117
118SIEHE AUCH
119 query_shadowing(E), unshadow(E), query_allow_shadow(M)