• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

krakjoe / parallel / 13891678545

14 Mar 2025 04:24PM UTC coverage: 96.923%. Remained the same
13891678545

push

github

web-flow
Update docs (#340)

2992 of 3087 relevant lines covered (96.92%)

5766.32 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

95.59
/src/future.c
1
/*
2
  +----------------------------------------------------------------------+
3
  | parallel                                                             |
4
  +----------------------------------------------------------------------+
5
  | Copyright (c) Joe Watkins 2019-2024                                  |
6
  +----------------------------------------------------------------------+
7
  | This source file is subject to version 3.01 of the PHP license,      |
8
  | that is bundled with this package in the file LICENSE, and is        |
9
  | available through the world-wide-web at the following url:           |
10
  | http://www.php.net/license/3_01.txt                                  |
11
  | If you did not receive a copy of the PHP license and are unable to   |
12
  | obtain it through the world-wide-web, please send a note to          |
13
  | license@php.net so we can mail you a copy immediately.               |
14
  +----------------------------------------------------------------------+
15
  | Author: krakjoe                                                      |
16
  +----------------------------------------------------------------------+
17
 */
18
#ifndef HAVE_PARALLEL_FUTURE
19
#define HAVE_PARALLEL_FUTURE
20

21
#include "parallel.h"
22

23
zend_class_entry *php_parallel_future_ce;
24
zend_object_handlers php_parallel_future_handlers;
25

26
zend_string *php_parallel_future_string_runtime;
27

28
zend_bool php_parallel_future_lock(php_parallel_future_t *future) {
84✔
29
    return php_parallel_monitor_lock(future->monitor);
84✔
30
}
31

32
zend_bool php_parallel_future_readable(php_parallel_future_t *future) {
84✔
33
    return php_parallel_monitor_check(future->monitor, PHP_PARALLEL_READY);
84✔
34
}
35

36
static zend_always_inline void php_parallel_future_value_inline(php_parallel_future_t *future, zval *return_value) {
630✔
37
    if (!php_parallel_monitor_check(future->monitor, PHP_PARALLEL_DONE)) {
630✔
38
        zval garbage = future->value;
600✔
39

40
        PARALLEL_ZVAL_COPY(
600✔
41
            &future->value, &garbage, 0);
42

43
        if (Z_OPT_REFCOUNTED(garbage)) {
600✔
44
            PARALLEL_ZVAL_DTOR(&garbage);
105✔
45
        }
46

47
        php_parallel_monitor_set(future->monitor, PHP_PARALLEL_DONE);
600✔
48
    }
49

50
    ZVAL_COPY(return_value, &future->value);
630✔
51
}
52

53
void php_parallel_future_value(php_parallel_future_t *future, zval *return_value) {
30✔
54
    php_parallel_monitor_lock(future->monitor);
30✔
55

56
    if (php_parallel_monitor_check(future->monitor, PHP_PARALLEL_ERROR)) {
30✔
57
        ZVAL_OBJ(return_value,
15✔
58
            php_parallel_exceptions_restore(&future->value));
59
        php_parallel_monitor_unlock(future->monitor);
15✔
60
        return;
15✔
61
    } else if (php_parallel_monitor_check(future->monitor,
15✔
62
                PHP_PARALLEL_KILLED|PHP_PARALLEL_CANCELLED)) {
63
        ZVAL_NULL(return_value);
×
64
        php_parallel_monitor_unlock(future->monitor);
×
65
        return;
×
66
    }
67

68
    php_parallel_future_value_inline(future, return_value);
15✔
69

70
    php_parallel_monitor_unlock(future->monitor);
15✔
71
}
72

73
zend_bool php_parallel_future_unlock(php_parallel_future_t *future) {
84✔
74
    return php_parallel_monitor_unlock(future->monitor);
84✔
75
}
76

77
ZEND_BEGIN_ARG_INFO_EX(php_parallel_future_value_arginfo, 0, 0, 0)
78
ZEND_END_ARG_INFO()
79

80
PHP_METHOD(Parallel_Future, value)
690✔
81
{
82
    php_parallel_future_t *future = php_parallel_future_from(getThis());
690✔
83
    int32_t state;
690✔
84

85
    PARALLEL_PARAMETERS_NONE(return);
690✔
86

87
    php_parallel_monitor_lock(future->monitor);
690✔
88

89
    if (php_parallel_monitor_check(future->monitor, PHP_PARALLEL_CANCELLED)) {
690✔
90
        php_parallel_exception_ex(
15✔
91
            php_parallel_future_error_cancelled_ce,
92
            "cannot retrieve value");
93
        php_parallel_monitor_unlock(future->monitor);
15✔
94
        return;
15✔
95
    }
96

97
    if (php_parallel_monitor_check(future->monitor, PHP_PARALLEL_KILLED)) {
675✔
98
        php_parallel_exception_ex(
15✔
99
            php_parallel_future_error_killed_ce,
100
            "cannot retrieve value");
101
        php_parallel_monitor_unlock(future->monitor);
15✔
102
        return;
15✔
103
    }
104

105
    if (php_parallel_monitor_check(future->monitor, PHP_PARALLEL_DONE)) {
660✔
106
        php_parallel_monitor_unlock(future->monitor);
30✔
107

108
        goto _php_parallel_future_value;
30✔
109
    } else {
110
        state = php_parallel_monitor_wait_locked(future->monitor,
630✔
111
                    PHP_PARALLEL_READY|
112
                    PHP_PARALLEL_FAILURE|
113
                    PHP_PARALLEL_ERROR);
114
        php_parallel_monitor_unlock(future->monitor);
630✔
115
    }
116

117
    if ((state == FAILURE) || (state & PHP_PARALLEL_FAILURE)) {
630✔
118
        php_parallel_exception_ex(
×
119
            php_parallel_future_error_ce,
120
            "cannot retrieve value");
121
        php_parallel_monitor_set(future->monitor,
×
122
            PHP_PARALLEL_READY|PHP_PARALLEL_FAILURE);
123
        return;
×
124
    }
125

126
    if ((state & PHP_PARALLEL_ERROR)) {
630✔
127
        zval exception;
45✔
128

129
        ZVAL_OBJ(&exception,
45✔
130
            php_parallel_exceptions_restore(&future->value));
131

132
        php_parallel_monitor_set(future->monitor,
45✔
133
            PHP_PARALLEL_READY|PHP_PARALLEL_ERROR);
134

135
        zend_throw_exception_object(&exception);
45✔
136
        return;
45✔
137
    }
138

139
    php_parallel_monitor_set(future->monitor, PHP_PARALLEL_READY);
585✔
140

141
_php_parallel_future_value:
615✔
142
    php_parallel_future_value_inline(future, return_value);
615✔
143
}
144

145
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(php_parallel_future_cancel_arginfo, 0, 0, _IS_BOOL, 0)
146
ZEND_END_ARG_INFO()
147

148
PHP_METHOD(Parallel_Future, cancel)
120✔
149
{
150
    php_parallel_future_t *future =
120✔
151
        php_parallel_future_from(getThis());
120✔
152

153
    PARALLEL_PARAMETERS_NONE(return);
120✔
154

155
    if (php_parallel_monitor_check(future->monitor, PHP_PARALLEL_CANCELLED)) {
120✔
156
        php_parallel_exception_ex(
15✔
157
            php_parallel_future_error_cancelled_ce,
158
            "task was already cancelled");
159
        return;
15✔
160
    }
161

162
    if (php_parallel_monitor_check(future->monitor, PHP_PARALLEL_KILLED)) {
105✔
163
        php_parallel_exception_ex(
15✔
164
            php_parallel_future_error_killed_ce,
165
            "runtime executing task was killed");
166
        return;
15✔
167
    }
168

169
    RETURN_BOOL(php_parallel_scheduler_cancel(future));
105✔
170
}
171

172
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(php_parallel_future_cancelled_arginfo, 0, 0, _IS_BOOL, 0)
173
ZEND_END_ARG_INFO()
174

175
PHP_METHOD(Parallel_Future, cancelled)
60✔
176
{
177
    php_parallel_future_t *future =
60✔
178
        php_parallel_future_from(getThis());
60✔
179

180
    PARALLEL_PARAMETERS_NONE(return);
60✔
181

182
    RETURN_BOOL(php_parallel_monitor_check(future->monitor, PHP_PARALLEL_CANCELLED));
75✔
183
}
184

185
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(php_parallel_future_done_arginfo, 0, 0, _IS_BOOL, 0)
186
ZEND_END_ARG_INFO()
187

188
PHP_METHOD(Parallel_Future, done)
30✔
189
{
190
    php_parallel_future_t *future =
30✔
191
        php_parallel_future_from(getThis());
30✔
192

193
    RETURN_BOOL(php_parallel_monitor_check(future->monitor, PHP_PARALLEL_READY));
30✔
194
}
195

196
ZEND_BEGIN_ARG_INFO_EX(php_parallel_future_construct_arginfo, 0, 0, 0)
197
ZEND_END_ARG_INFO()
198

199
PHP_METHOD(Parallel_Future, __construct)
15✔
200
{
201
    php_parallel_future_t *future = php_parallel_future_from(getThis());
15✔
202

203
    php_parallel_exception_ex(
15✔
204
        php_parallel_future_error_ce,
205
        "construction of Future objects is not allowed");
206

207
    php_parallel_monitor_set(future->monitor, PHP_PARALLEL_READY|PHP_PARALLEL_DONE);
15✔
208
}
15✔
209

210
zend_function_entry php_parallel_future_methods[] = {
211
    PHP_ME(Parallel_Future, __construct, php_parallel_future_construct_arginfo, ZEND_ACC_PUBLIC)
212
    PHP_ME(Parallel_Future, value, php_parallel_future_value_arginfo, ZEND_ACC_PUBLIC)
213
    PHP_ME(Parallel_Future, done, php_parallel_future_done_arginfo, ZEND_ACC_PUBLIC)
214
    PHP_ME(Parallel_Future, cancel, php_parallel_future_cancel_arginfo, ZEND_ACC_PUBLIC)
215
    PHP_ME(Parallel_Future, cancelled, php_parallel_future_cancelled_arginfo, ZEND_ACC_PUBLIC)
216
    PHP_FE_END
217
};
218

219
zend_object* php_parallel_future_create(zend_class_entry *type) {
900✔
220
    php_parallel_future_t *future = ecalloc(1,
900✔
221
            sizeof(php_parallel_future_t) + zend_object_properties_size(type));
222

223
    zend_object_std_init(&future->std, type);
900✔
224

225
    future->std.handlers = &php_parallel_future_handlers;
900✔
226

227
    future->monitor = php_parallel_monitor_create();
900✔
228

229
    return &future->std;
900✔
230
}
231

232
void php_parallel_future_destroy(zend_object *o) {
900✔
233
    php_parallel_future_t *future =
900✔
234
        php_parallel_future_fetch(o);
900✔
235

236
    php_parallel_monitor_lock(future->monitor);
900✔
237

238
    if (!php_parallel_monitor_check(future->monitor, PHP_PARALLEL_READY)) {
900✔
239
        php_parallel_monitor_wait_locked(future->monitor, PHP_PARALLEL_READY);
30✔
240
    }
241

242
    php_parallel_monitor_unlock(future->monitor);
900✔
243

244
    switch (Z_TYPE(future->value)) {
900✔
245
        case IS_PTR:
60✔
246
            php_parallel_exceptions_destroy(Z_PTR(future->value));
60✔
247
        break;
60✔
248

249
        default:
840✔
250
            if (Z_OPT_REFCOUNTED(future->value)) {
840✔
251
                PARALLEL_ZVAL_DTOR(&future->value);
120✔
252
            }
253
    }
254

255
    if (future->runtime) {
900✔
256
       OBJ_RELEASE(&future->runtime->std);
885✔
257
    }
258

259
    php_parallel_monitor_destroy(future->monitor);
900✔
260

261
    zend_object_std_dtor(o);
900✔
262
}
900✔
263

264
static HashTable* php_parallel_future_debug(zend_object *zo, int *temp) {
30✔
265
    php_parallel_future_t *future = php_parallel_future_fetch(zo);
30✔
266
    HashTable *debug;
30✔
267
    zval zdbg;
30✔
268

269
    ALLOC_HASHTABLE(debug);
30✔
270
    zend_hash_init(debug, 3, NULL, ZVAL_PTR_DTOR, 0);
30✔
271

272
    *temp = 1;
30✔
273

274
    GC_ADDREF(&future->runtime->std);
30✔
275

276
    ZVAL_OBJ(&zdbg, &future->runtime->std);
30✔
277

278
    zend_hash_add(
30✔
279
        debug,
280
        php_parallel_future_string_runtime,
281
        &zdbg);
282

283
    return debug;
30✔
284
}
285

286
PHP_MINIT_FUNCTION(PARALLEL_FUTURE)
2,660✔
287
{
288
    zend_class_entry ce;
2,660✔
289

290
    memcpy(&php_parallel_future_handlers, php_parallel_standard_handlers(), sizeof(zend_object_handlers));
2,660✔
291

292
    php_parallel_future_handlers.offset = XtOffsetOf(php_parallel_future_t, std);
2,660✔
293
    php_parallel_future_handlers.free_obj = php_parallel_future_destroy;
2,660✔
294
    php_parallel_future_handlers.get_debug_info = php_parallel_future_debug;
2,660✔
295

296
    INIT_NS_CLASS_ENTRY(ce, "parallel", "Future", php_parallel_future_methods);
2,660✔
297

298
    php_parallel_future_ce = zend_register_internal_class(&ce);
2,660✔
299
    php_parallel_future_ce->create_object = php_parallel_future_create;
2,660✔
300
    php_parallel_future_ce->ce_flags |= ZEND_ACC_FINAL;
2,660✔
301

302
    #ifdef ZEND_ACC_NOT_SERIALIZABLE
303
        php_parallel_future_ce->ce_flags |= ZEND_ACC_NOT_SERIALIZABLE;
1,828✔
304
    #else
305
        php_parallel_future_ce->serialize = zend_class_serialize_deny;
832✔
306
        php_parallel_future_ce->unserialize = zend_class_unserialize_deny;
832✔
307
    #endif
308

309
    php_parallel_future_string_runtime = zend_string_init_interned(ZEND_STRL("runtime"), 1);
2,660✔
310

311
    return SUCCESS;
2,660✔
312
}
313

314
PHP_MSHUTDOWN_FUNCTION(PARALLEL_FUTURE)
2,660✔
315
{
316
    zend_string_release(php_parallel_future_string_runtime);
2,660✔
317

318
    return SUCCESS;
2,660✔
319
}
320
#endif
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc