Xonotic QuakeC
The free, fast arena FPS with crisp movement and a wide array of weapons
promise.qc
Go to the documentation of this file.
1#include "promise.qh"
2
4.void(entity this) _ref_finalize;
5
6void ref_init(entity this, int init, void(entity this) finalize)
7{
8 this._ref_count = init;
9 this._ref_finalize = finalize;
10}
11
12// todo: rename to `ref`
14{
15 this._ref_count += 1;
16 return this;
17}
18
19entity unref(Promise this)
20{
21 this._ref_count -= 1;
22 if (!this._ref_count) {
23 LOG_DEBUGF("Finalize entity %i (from %s)", this, this.sourceLoc);
24 this._ref_finalize(this);
25 return NULL;
26 }
27 return this;
28}
29
30enum {
34};
35
36classfield(Promise) .int _promise_state;
37classfield(Promise) .entity _promise_result;
38classfield(Promise) .IntrusiveList _promise_handlers;
39
40entityclass(PromiseHandler);
41classfield(PromiseHandler) .Promise _promise_handler_ret;
42classfield(PromiseHandler) .entity _promise_handler_data;
43classfield(PromiseHandler) .Promise(Promise ret, entity result, entity userdata) _promise_handler_resolve;
44classfield(PromiseHandler) .Promise(Promise ret, entity err, entity userdata) _promise_handler_reject;
45
46void _Promise_finalize(Promise this)
47{
48 delete(this);
49}
50
51Promise Promise_new_(Promise this)
52{
54 this._promise_result = this; // promises default to being their own result to save on entities
55 return this;
56}
57
58void _Promise_handle(Promise this, PromiseHandler h);
59
60void Promise_resolve(Promise this)
61{
62 if (!this) {
63 LOG_SEVERE("Attempted to resolve a null promise");
64 return;
65 }
66 if (this._promise_state != PROMISE_PENDING) {
67 LOG_SEVEREF("Resolved non-pending promise %i", this);
68 return;
69 }
70 this._promise_state = PROMISE_RESOLVED;
71 if (this._promise_handlers) {
72 IL_EACH(this._promise_handlers, true, _Promise_handle(this, it));
73 IL_DELETE(this._promise_handlers);
74 }
75 unref(this);
76 return;
77}
78
79void Promise_reject(Promise this)
80{
81 if (!this) {
82 LOG_SEVERE("Attempted to reject a null promise");
83 return;
84 }
85 if (this._promise_state != PROMISE_PENDING) {
86 LOG_SEVEREF("Rejected non-pending promise %i", this);
87 return;
88 }
89 this._promise_state = PROMISE_REJECTED;
90 if (this._promise_handlers) {
91 IL_EACH(this._promise_handlers, true, _Promise_handle(this, it));
92 IL_DELETE(this._promise_handlers);
93 }
94 unref(this);
95 return;
96}
97
98Promise _Promise_then(
99 Promise this,
100 Promise ret,
101 Promise(Promise ret, entity result, entity userdata) onResolve,
102 Promise(Promise ret, entity result, entity userdata) onReject,
103 entity userdata
104);
105
106void _Promise_handle(Promise this, PromiseHandler h)
107{
108 switch (this._promise_state) {
109 case PROMISE_PENDING:
110 if (!this._promise_handlers) {
111 this._promise_handlers = IL_NEW();
112 }
113 IL_PUSH(this._promise_handlers, h);
114 break;
115 case PROMISE_RESOLVED: {
116 Promise ret = h._promise_handler_ret;
117 Promise p = h._promise_handler_resolve(ret, this._promise_result, h._promise_handler_data);
118 if (p != ret) _Promise_then(p, ret, func_null, func_null, NULL); // bind p -> ret
119 delete(h);
120 break;
121 }
122 case PROMISE_REJECTED: {
123 Promise ret = h._promise_handler_ret;
124 Promise p = h._promise_handler_reject(ret, this._promise_result, h._promise_handler_data);
125 if (p != ret) _Promise_then(p, ret, func_null, func_null, NULL); // bind p -> ret
126 delete(h);
127 break;
128 }
129 }
130}
131
133 Promise this,
134 Promise(Promise ret, entity result, entity userdata) onResolve,
135 Promise(Promise ret, entity err, entity userdata) onReject,
136 Promise ret,
137 entity userdata
138)
139{
140 PromiseHandler h = new_pure(PromiseHandler);
141 h._promise_handler_ret = ret;
142 h._promise_handler_data = userdata;
143 h._promise_handler_resolve = onResolve;
144 h._promise_handler_reject = onReject;
145 _Promise_handle(this, h);
146}
147
148Promise _Promise_onResolve_default(Promise ret, entity result, entity userdata)
149{
150 ret._promise_result = result;
151 Promise_resolve(ret);
152 return ret;
153}
154
155Promise _Promise_onReject_default(Promise ret, entity err, entity userdata)
156{
157 ret._promise_result = err;
158 Promise_reject(ret);
159 return ret;
160}
161
163 Promise this,
164 Promise ret,
165 Promise(Promise ret, entity result, entity userdata) onResolve,
166 Promise(Promise ret, entity result, entity userdata) onReject,
167 entity userdata
168)
169{
171 this,
172 (onResolve ? onResolve : _Promise_onResolve_default),
173 (onReject ? onReject : _Promise_onReject_default),
174 ret,
175 userdata
176 );
177 return ret;
178}
179
181 Promise this,
182 Promise ret,
183 Promise(Promise ret, entity result, entity userdata) onResolve,
184 entity userdata
185)
186{
187 unref(ret); // ret is a temporary
188 return _Promise_then(this, ret, onResolve, func_null, userdata);
189}
190
192 Promise this,
193 Promise ret,
194 Promise(Promise ret, entity result, entity userdata) onReject,
195 entity userdata
196)
197{
198 unref(ret); // ret is a temporary
199 return _Promise_then(this, ret, func_null, onReject, userdata);
200}
201
202// utils
203
204#ifndef MENUQC
205
206Promise Promise_sleep(float n)
207{
208 Promise p = unref(Promise_new());
210 p.nextthink = time + n;
211 return p;
212}
213
214#endif
var entity(vector mins, vector maxs,.entity tofield) findbox_tofield_OrFallback
float time
ERASEABLE entity IL_PUSH(IntrusiveList this, entity it)
Push to tail.
#define IL_NEW()
#define IL_EACH(this, cond, body)
#define IL_DELETE(this)
Delete the list.
#define LOG_SEVEREF(...)
Definition log.qh:58
#define LOG_SEVERE(...)
Definition log.qh:57
#define LOG_DEBUGF(...)
Definition log.qh:81
var void func_null()
#define entityclass(...)
Definition oo.qh:52
#define new_pure(class)
purely logical entities (not linked to the area grid)
Definition oo.qh:67
#define classfield(name)
Definition oo.qh:57
string sourceLoc
Location entity was spawned from in source.
Definition oo.qh:27
#define NULL
Definition post.qh:14
@ PROMISE_RESOLVED
Definition promise.qc:32
@ PROMISE_PENDING
Definition promise.qc:31
@ PROMISE_REJECTED
Definition promise.qc:33
entity result
Definition promise.qc:43
Promise Promise_catch_(Promise this, Promise ret, Promise(Promise ret, entity result, entity userdata) onReject, entity userdata)
Definition promise.qc:191
void ref_init(entity this, int init, void(entity this) finalize)
Definition promise.qc:6
entity REF(entity this)
Definition promise.qc:13
void _Promise_handle(Promise this, PromiseHandler h)
Definition promise.qc:106
Promise _Promise_onResolve_default(Promise ret, entity result, entity userdata)
Definition promise.qc:148
Promise _Promise_onReject_default(Promise ret, entity err, entity userdata)
Definition promise.qc:155
void _Promise_finalize(Promise this)
Definition promise.qc:46
entity unref(Promise this)
Definition promise.qc:19
entity err
Definition promise.qc:44
Promise Promise_then_(Promise this, Promise ret, Promise(Promise ret, entity result, entity userdata) onResolve, entity userdata)
Definition promise.qc:180
int _ref_count
Definition promise.qc:3
entity entity userdata _promise_handler_reject
Definition promise.qc:44
void Promise_resolve(Promise this)
notify all Promise_then subscribers that this promise has resolved
Definition promise.qc:60
entity entity userdata _promise_handler_resolve
Definition promise.qc:43
Promise Promise_new_(Promise this)
Definition promise.qc:51
void Promise_reject(Promise this)
notify all Promise_catch subscribers that this promise has rejected
Definition promise.qc:79
Promise _Promise_then(Promise this, Promise ret, Promise(Promise ret, entity result, entity userdata) onResolve, Promise(Promise ret, entity result, entity userdata) onReject, entity userdata)
Definition promise.qc:162
void _Promise_done(Promise this, Promise(Promise ret, entity result, entity userdata) onResolve, Promise(Promise ret, entity err, entity userdata) onReject, Promise ret, entity userdata)
Definition promise.qc:132
#define Promise_new()
Definition promise.qh:5
#define setthink(e, f)