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

krakjoe / parallel / 20284038403

16 Dec 2025 09:59PM UTC coverage: 96.75% (-0.07%) from 96.815%
20284038403

Pull #357

github

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

2672 of 2765 new or added lines in 27 files covered. (96.64%)

1 existing line in 1 file now uncovered.

2798 of 2892 relevant lines covered (96.75%)

6636.75 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); }
137✔
29

30
bool php_parallel_future_readable(php_parallel_future_t *future)
137✔
31
{
32
        return php_parallel_monitor_check(future->monitor, PHP_PARALLEL_READY);
137✔
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); }
137✔
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