4 .void(entity this) _ref_finalize;
6 void ref_init(entity this, int init, void(entity this) finalize)
8 this._ref_count = init;
9 this._ref_finalize = finalize;
12 // todo: rename to `ref`
13 entity REF(entity this)
19 entity unref(Promise this)
22 if (!this._ref_count) {
23 LOG_DEBUGF("Finalize entity %i (from %s)", this, this.sourceLoc);
24 this._ref_finalize(this);
36 classfield(Promise) .int _promise_state;
37 classfield(Promise) .entity _promise_result;
38 classfield(Promise) .IntrusiveList _promise_handlers;
40 entityclass(PromiseHandler);
41 classfield(PromiseHandler) .Promise _promise_handler_ret;
42 classfield(PromiseHandler) .entity _promise_handler_data;
43 classfield(PromiseHandler) .Promise(Promise ret, entity result, entity userdata) _promise_handler_resolve;
44 classfield(PromiseHandler) .Promise(Promise ret, entity err, entity userdata) _promise_handler_reject;
46 void _Promise_finalize(Promise this)
51 Promise Promise_new_(Promise this)
53 ref_init(this, 2, _Promise_finalize);
54 this._promise_result = this; // promises default to being their own result to save on entities
58 void _Promise_handle(Promise this, PromiseHandler h);
60 void Promise_resolve(Promise this)
63 LOG_SEVERE("Attempted to resolve a null promise");
66 if (this._promise_state != PROMISE_PENDING) {
67 LOG_SEVEREF("Resolved non-pending promise %i", this);
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);
79 void Promise_reject(Promise this)
82 LOG_SEVERE("Attempted to reject a null promise");
85 if (this._promise_state != PROMISE_PENDING) {
86 LOG_SEVEREF("Rejected non-pending promise %i", this);
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);
98 Promise _Promise_then(
101 Promise(Promise ret, entity result, entity userdata) onResolve,
102 Promise(Promise ret, entity result, entity userdata) onReject,
106 void _Promise_handle(Promise this, PromiseHandler h)
108 switch (this._promise_state) {
109 case PROMISE_PENDING:
110 if (!this._promise_handlers) {
111 this._promise_handlers = IL_NEW();
113 IL_PUSH(this._promise_handlers, h);
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
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
134 Promise(Promise ret, entity result, entity userdata) onResolve,
135 Promise(Promise ret, entity err, entity userdata) onReject,
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);
148 Promise _Promise_onResolve_default(Promise ret, entity result, entity userdata)
150 ret._promise_result = result;
151 Promise_resolve(ret);
155 Promise _Promise_onReject_default(Promise ret, entity err, entity userdata)
157 ret._promise_result = err;
162 Promise _Promise_then(
165 Promise(Promise ret, entity result, entity userdata) onResolve,
166 Promise(Promise ret, entity result, entity userdata) onReject,
172 (onResolve ? onResolve : _Promise_onResolve_default),
173 (onReject ? onReject : _Promise_onReject_default),
180 Promise Promise_then_(
183 Promise(Promise ret, entity result, entity userdata) onResolve,
187 unref(ret); // ret is a temporary
188 return _Promise_then(this, ret, onResolve, func_null, userdata);
191 Promise Promise_catch_(
194 Promise(Promise ret, entity result, entity userdata) onReject,
198 unref(ret); // ret is a temporary
199 return _Promise_then(this, ret, func_null, onReject, userdata);
206 Promise Promise_sleep(float n)
208 Promise p = unref(Promise_new());
209 setthink(p, Promise_resolve);
210 p.nextthink = time + n;