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

krakjoe / parallel / 20274017619

16 Dec 2025 03:50PM UTC coverage: 96.75% (-0.07%) from 96.815%
20274017619

Pull #357

github

web-flow
Merge ef2111af6 into 14042a874
Pull Request #357: Cleanup code formatting and docs

1527 of 1615 new or added lines in 27 files covered. (94.55%)

1 existing line in 1 file now uncovered.

2798 of 2892 relevant lines covered (96.75%)

6580.39 hits per line

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

95.38
/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
bool php_parallel_future_lock(php_parallel_future_t *future) { return php_parallel_monitor_lock(future->monitor); }
117✔
29

30
bool php_parallel_future_readable(php_parallel_future_t *future)
117✔
31
{
32
    return php_parallel_monitor_check(future->monitor, PHP_PARALLEL_READY);
117✔
33
}
34

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

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

42
        if (Z_OPT_REFCOUNTED(garbage)) {
780✔
43
            PARALLEL_ZVAL_DTOR(&garbage);
126✔
44
        }
45

46
        php_parallel_monitor_set(future->monitor, PHP_PARALLEL_DONE);
780✔
47
    }
48

49
    ZVAL_COPY(return_value, &future->value);
816✔
50
}
51

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

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

66
    php_parallel_future_value_inline(future, return_value);
18✔
67

68
    php_parallel_monitor_unlock(future->monitor);
18✔
69
}
70

71
bool php_parallel_future_unlock(php_parallel_future_t *future) { return php_parallel_monitor_unlock(future->monitor); }
117✔
72

73
ZEND_BEGIN_ARG_INFO_EX(php_parallel_future_value_arginfo, 0, 0, 0)
74
ZEND_END_ARG_INFO()
75

76
PHP_METHOD(Parallel_Future, value)
888✔
77
{
78
    php_parallel_future_t *future = php_parallel_future_from(getThis());
888✔
79
    int32_t state;
888✔
80

81
    PARALLEL_PARAMETERS_NONE(return);
888✔
82

83
    php_parallel_monitor_lock(future->monitor);
888✔
84

85
    if (php_parallel_monitor_check(future->monitor, PHP_PARALLEL_CANCELLED)) {
888✔
86
        php_parallel_exception_ex(php_parallel_future_error_cancelled_ce, "cannot retrieve value");
18✔
87
        php_parallel_monitor_unlock(future->monitor);
18✔
88
        return;
18✔
89
    }
90

91
    if (php_parallel_monitor_check(future->monitor, PHP_PARALLEL_KILLED)) {
870✔
92
        php_parallel_exception_ex(php_parallel_future_error_killed_ce, "cannot retrieve value");
18✔
93
        php_parallel_monitor_unlock(future->monitor);
18✔
94
        return;
18✔
95
    }
96

97
    if (php_parallel_monitor_check(future->monitor, PHP_PARALLEL_DONE)) {
852✔
98
        php_parallel_monitor_unlock(future->monitor);
36✔
99

100
        goto _php_parallel_future_value;
36✔
101
    } else {
102
        state = php_parallel_monitor_wait_locked(future->monitor,
816✔
103
                                                 PHP_PARALLEL_READY | PHP_PARALLEL_FAILURE | PHP_PARALLEL_ERROR);
104
        php_parallel_monitor_unlock(future->monitor);
816✔
105
    }
106

107
    if ((state == FAILURE) || (state & PHP_PARALLEL_FAILURE)) {
816✔
NEW
108
        php_parallel_exception_ex(php_parallel_future_error_ce, "cannot retrieve value");
×
NEW
109
        php_parallel_monitor_set(future->monitor, PHP_PARALLEL_READY | PHP_PARALLEL_FAILURE);
×
NEW
110
        return;
×
111
    }
112

113
    if ((state & PHP_PARALLEL_ERROR)) {
816✔
114
        zval exception;
54✔
115

116
        ZVAL_OBJ(&exception, php_parallel_exceptions_restore(&future->value));
54✔
117

118
        php_parallel_monitor_set(future->monitor, PHP_PARALLEL_READY | PHP_PARALLEL_ERROR);
54✔
119

120
        zend_throw_exception_object(&exception);
54✔
121
        return;
54✔
122
    }
123

124
    php_parallel_monitor_set(future->monitor, PHP_PARALLEL_READY);
762✔
125

126
_php_parallel_future_value:
798✔
127
    php_parallel_future_value_inline(future, return_value);
798✔
128
}
129

130
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(php_parallel_future_cancel_arginfo, 0, 0, _IS_BOOL, 0)
131
ZEND_END_ARG_INFO()
132

133
PHP_METHOD(Parallel_Future, cancel)
144✔
134
{
135
    php_parallel_future_t *future = php_parallel_future_from(getThis());
144✔
136

137
    PARALLEL_PARAMETERS_NONE(return);
144✔
138

139
    if (php_parallel_monitor_check(future->monitor, PHP_PARALLEL_CANCELLED)) {
144✔
140
        php_parallel_exception_ex(php_parallel_future_error_cancelled_ce, "task was already cancelled");
18✔
141
        return;
18✔
142
    }
143

144
    if (php_parallel_monitor_check(future->monitor, PHP_PARALLEL_KILLED)) {
126✔
145
        php_parallel_exception_ex(php_parallel_future_error_killed_ce, "runtime executing task was killed");
18✔
146
        return;
18✔
147
    }
148

149
    RETURN_BOOL(php_parallel_scheduler_cancel(future));
126✔
150
}
151

152
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(php_parallel_future_cancelled_arginfo, 0, 0, _IS_BOOL, 0)
153
ZEND_END_ARG_INFO()
154

155
PHP_METHOD(Parallel_Future, cancelled)
72✔
156
{
157
    php_parallel_future_t *future = php_parallel_future_from(getThis());
72✔
158

159
    PARALLEL_PARAMETERS_NONE(return);
72✔
160

161
    RETURN_BOOL(php_parallel_monitor_check(future->monitor, PHP_PARALLEL_CANCELLED));
90✔
162
}
163

164
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(php_parallel_future_done_arginfo, 0, 0, _IS_BOOL, 0)
165
ZEND_END_ARG_INFO()
166

167
PHP_METHOD(Parallel_Future, done)
36✔
168
{
169
    php_parallel_future_t *future = php_parallel_future_from(getThis());
36✔
170

171
    RETURN_BOOL(php_parallel_monitor_check(future->monitor, PHP_PARALLEL_READY));
36✔
172
}
173

174
ZEND_BEGIN_ARG_INFO_EX(php_parallel_future_construct_arginfo, 0, 0, 0)
175
ZEND_END_ARG_INFO()
176

177
PHP_METHOD(Parallel_Future, __construct)
18✔
178
{
179
    php_parallel_future_t *future = php_parallel_future_from(getThis());
18✔
180

181
    php_parallel_exception_ex(php_parallel_future_error_ce, "construction of Future objects is not allowed");
18✔
182

183
    php_parallel_monitor_set(future->monitor, PHP_PARALLEL_READY | PHP_PARALLEL_DONE);
18✔
184
}
18✔
185

186
zend_function_entry php_parallel_future_methods[] = {
187
    PHP_ME(Parallel_Future, __construct, php_parallel_future_construct_arginfo,
188
           ZEND_ACC_PUBLIC) PHP_ME(Parallel_Future, value, php_parallel_future_value_arginfo, ZEND_ACC_PUBLIC)
189
        PHP_ME(Parallel_Future, done, php_parallel_future_done_arginfo, ZEND_ACC_PUBLIC)
190
            PHP_ME(Parallel_Future, cancel, php_parallel_future_cancel_arginfo, ZEND_ACC_PUBLIC)
191
                PHP_ME(Parallel_Future, cancelled, php_parallel_future_cancelled_arginfo, ZEND_ACC_PUBLIC) PHP_FE_END};
192

193
zend_object *php_parallel_future_create(zend_class_entry *type)
1,140✔
194
{
195
    php_parallel_future_t *future = ecalloc(1, sizeof(php_parallel_future_t) + zend_object_properties_size(type));
1,140✔
196

197
    zend_object_std_init(&future->std, type);
1,140✔
198

199
    future->std.handlers = &php_parallel_future_handlers;
1,140✔
200

201
    future->monitor = php_parallel_monitor_create();
1,140✔
202

203
    return &future->std;
1,140✔
204
}
205

206
void php_parallel_future_destroy(zend_object *o)
1,140✔
207
{
208
    php_parallel_future_t *future = php_parallel_future_fetch(o);
1,140✔
209

210
    php_parallel_monitor_lock(future->monitor);
1,140✔
211

212
    if (!php_parallel_monitor_check(future->monitor, PHP_PARALLEL_READY)) {
1,140✔
213
        php_parallel_monitor_wait_locked(future->monitor, PHP_PARALLEL_READY);
36✔
214
    }
215

216
    php_parallel_monitor_unlock(future->monitor);
1,140✔
217

218
    switch (Z_TYPE(future->value)) {
1,140✔
219
    case IS_PTR:
72✔
220
        php_parallel_exceptions_destroy(Z_PTR(future->value));
72✔
221
        break;
72✔
222

223
    default:
1,068✔
224
        if (Z_OPT_REFCOUNTED(future->value)) {
1,068✔
225
            PARALLEL_ZVAL_DTOR(&future->value);
144✔
226
        }
227
    }
228

229
    if (future->runtime) {
1,140✔
230
        OBJ_RELEASE(&future->runtime->std);
1,122✔
231
    }
232

233
    php_parallel_monitor_destroy(future->monitor);
1,140✔
234

235
    zend_object_std_dtor(o);
1,140✔
236
}
1,140✔
237

238
static HashTable *php_parallel_future_debug(zend_object *zo, int *temp)
36✔
239
{
240
    php_parallel_future_t *future = php_parallel_future_fetch(zo);
36✔
241
    HashTable *debug;
36✔
242
    zval zdbg;
36✔
243

244
    ALLOC_HASHTABLE(debug);
36✔
245
    zend_hash_init(debug, 3, NULL, ZVAL_PTR_DTOR, 0);
36✔
246

247
    *temp = 1;
36✔
248

249
    GC_ADDREF(&future->runtime->std);
36✔
250

251
    ZVAL_OBJ(&zdbg, &future->runtime->std);
36✔
252

253
    zend_hash_add(debug, php_parallel_future_string_runtime, &zdbg);
36✔
254

255
    return debug;
36✔
256
}
257

258
PHP_MINIT_FUNCTION(PARALLEL_FUTURE)
3,168✔
259
{
260
    zend_class_entry ce;
3,168✔
261

262
    memcpy(&php_parallel_future_handlers, php_parallel_standard_handlers(), sizeof(zend_object_handlers));
3,168✔
263

264
    php_parallel_future_handlers.offset = XtOffsetOf(php_parallel_future_t, std);
3,168✔
265
    php_parallel_future_handlers.free_obj = php_parallel_future_destroy;
3,168✔
266
    php_parallel_future_handlers.get_debug_info = php_parallel_future_debug;
3,168✔
267

268
    INIT_NS_CLASS_ENTRY(ce, "parallel", "Future", php_parallel_future_methods);
3,168✔
269

270
    php_parallel_future_ce = zend_register_internal_class(&ce);
3,168✔
271
    php_parallel_future_ce->create_object = php_parallel_future_create;
3,168✔
272
    php_parallel_future_ce->ce_flags |= ZEND_ACC_FINAL;
3,168✔
273

274
#ifdef ZEND_ACC_NOT_SERIALIZABLE
275
    php_parallel_future_ce->ce_flags |= ZEND_ACC_NOT_SERIALIZABLE;
2,330✔
276
#else
277
    php_parallel_future_ce->serialize = zend_class_serialize_deny;
838✔
278
    php_parallel_future_ce->unserialize = zend_class_unserialize_deny;
838✔
279
#endif
280

281
    php_parallel_future_string_runtime = zend_string_init_interned(ZEND_STRL("runtime"), 1);
3,168✔
282

283
    return SUCCESS;
3,168✔
284
}
285

286
PHP_MSHUTDOWN_FUNCTION(PARALLEL_FUTURE)
3,168✔
287
{
288
    zend_string_release(php_parallel_future_string_runtime);
3,168✔
289

290
    return SUCCESS;
3,168✔
291
}
292
#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