Skip to content

Commit 1405a7d

Browse files
committed
add Co\Scheduler
1 parent e922685 commit 1405a7d

File tree

3 files changed

+155
-2
lines changed

3 files changed

+155
-2
lines changed

php_swoole_cxx.h

+7-2
Original file line numberDiff line numberDiff line change
@@ -251,12 +251,12 @@ class ArrayIterator
251251
zend_ulong _index;
252252
};
253253

254-
class array
254+
class Array
255255
{
256256
public:
257257
zval *arr;
258258

259-
array(zval *_arr)
259+
Array(zval *_arr)
260260
{
261261
assert(Z_TYPE_P(_arr) == IS_ARRAY);
262262
arr = _arr;
@@ -272,6 +272,11 @@ class array
272272
return add_index_zval(arr, index, value) == SUCCESS;
273273
}
274274

275+
inline bool append(zval *value)
276+
{
277+
return add_next_index_zval(arr, value) == SUCCESS;
278+
}
279+
275280
inline bool set(zend_ulong index, zend_resource *res)
276281
{
277282
zval tmp;

swoole_coroutine_scheduler.cc

+115
Original file line numberDiff line numberDiff line change
@@ -22,22 +22,98 @@
2222
#include "coroutine_c_api.h"
2323

2424
#include <unordered_map>
25+
#include <queue>
2526

2627
using namespace std;
2728
using swoole::coroutine::System;
2829
using swoole::coroutine::Socket;
2930
using swoole::Coroutine;
3031
using swoole::PHPCoroutine;
3132

33+
struct scheduler_t
34+
{
35+
queue<php_swoole_fci*> *list;
36+
zend_object std;
37+
};
38+
3239
static zend_class_entry *swoole_coroutine_iterator_ce;
3340
static zend_class_entry *swoole_coroutine_context_ce;
41+
static zend_class_entry *swoole_coroutine_scheduler_ce;
42+
static zend_object_handlers swoole_coroutine_scheduler_handlers;
3443

3544
static unordered_map<long, Coroutine *> user_yield_coros;
3645

46+
ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_void, 0, 0, 0)
47+
ZEND_END_ARG_INFO()
48+
49+
ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_coroutine_scheduler_add, 0, 0, 1)
50+
ZEND_ARG_CALLABLE_INFO(0, func, 0)
51+
ZEND_ARG_VARIADIC_INFO(0, params)
52+
ZEND_END_ARG_INFO()
53+
54+
ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_coroutine_scheduler_set, 0, 0, 1)
55+
ZEND_ARG_ARRAY_INFO(0, settings, 0)
56+
ZEND_END_ARG_INFO()
57+
58+
static PHP_METHOD(swoole_coroutine_scheduler, add);
59+
static PHP_METHOD(swoole_coroutine_scheduler, start);
60+
61+
static sw_inline scheduler_t* scheduler_get_object(zend_object *obj)
62+
{
63+
return (scheduler_t *) ((char *) obj - swoole_coroutine_scheduler_handlers.offset);
64+
}
65+
66+
static zend_object *scheduler_create_object(zend_class_entry *ce)
67+
{
68+
scheduler_t *s = (scheduler_t *) ecalloc(1, sizeof(scheduler_t) + zend_object_properties_size(ce));
69+
zend_object_std_init(&s->std, ce);
70+
object_properties_init(&s->std, ce);
71+
s->std.handlers = &swoole_coroutine_scheduler_handlers;
72+
return &s->std;
73+
}
74+
75+
static void scheduler_free_object(zend_object *object)
76+
{
77+
scheduler_t *s = scheduler_get_object(object);
78+
if (s->list)
79+
{
80+
while(!s->list->empty())
81+
{
82+
php_swoole_fci *fci = s->list->front();
83+
s->list->pop();
84+
sw_zend_fci_cache_discard(&fci->fci_cache);
85+
sw_zend_fci_params_discard(&fci->fci);
86+
efree(fci);
87+
}
88+
delete s->list;
89+
s->list = nullptr;
90+
}
91+
zend_object_std_dtor(&s->std);
92+
}
93+
94+
95+
static const zend_function_entry swoole_coroutine_scheduler_methods[] =
96+
{
97+
PHP_ME(swoole_coroutine_scheduler, add, arginfo_swoole_coroutine_scheduler_add, ZEND_ACC_PUBLIC)
98+
PHP_ME(swoole_coroutine_scheduler, set, arginfo_swoole_coroutine_scheduler_set, ZEND_ACC_PUBLIC)
99+
PHP_ME(swoole_coroutine_scheduler, start, arginfo_swoole_void, ZEND_ACC_PUBLIC)
100+
PHP_FE_END
101+
};
102+
37103
void swoole_coroutine_scheduler_init(int module_number)
38104
{
39105
SW_INIT_CLASS_ENTRY_BASE(swoole_coroutine_iterator, "Swoole\\Coroutine\\Iterator", NULL, "Co\\Iterator", NULL, spl_ce_ArrayIterator);
40106
SW_INIT_CLASS_ENTRY_BASE(swoole_coroutine_context, "Swoole\\Coroutine\\Context", NULL, "Co\\Context", NULL, spl_ce_ArrayObject);
107+
108+
SW_INIT_CLASS_ENTRY(swoole_coroutine_scheduler, "Swoole\\Coroutine\\Scheduler", NULL, "Co\\Scheduler", swoole_coroutine_scheduler_methods);
109+
SW_SET_CLASS_SERIALIZABLE(swoole_coroutine_scheduler, zend_class_serialize_deny, zend_class_unserialize_deny);
110+
SW_SET_CLASS_CLONEABLE(swoole_coroutine_scheduler, sw_zend_class_clone_deny);
111+
SW_SET_CLASS_UNSET_PROPERTY_HANDLER(swoole_coroutine_scheduler, sw_zend_class_unset_property_deny);
112+
SW_SET_CLASS_CREATE_WITH_ITS_OWN_HANDLERS(swoole_coroutine_scheduler);
113+
SW_SET_CLASS_CUSTOM_OBJECT(swoole_coroutine_scheduler, scheduler_create_object, scheduler_free_object, scheduler_t, std);
114+
swoole_coroutine_scheduler_ce->ce_flags |= ZEND_ACC_FINAL;
115+
116+
zend_declare_property_null(swoole_coroutine_scheduler_ce, ZEND_STRL("_list"), ZEND_ACC_PRIVATE);
41117
}
42118

43119
PHP_FUNCTION(swoole_coroutine_create)
@@ -290,6 +366,45 @@ PHP_METHOD(swoole_coroutine_scheduler, list)
290366
zval_ptr_dtor(&zlist);
291367
}
292368

369+
static PHP_METHOD(swoole_coroutine_scheduler, add)
370+
{
371+
auto s = scheduler_get_object(Z_OBJ_P(getThis()));
372+
php_swoole_fci *fci = (php_swoole_fci *) ecalloc(1, sizeof(php_swoole_fci));
373+
374+
ZEND_PARSE_PARAMETERS_START(1, -1)
375+
Z_PARAM_FUNC(fci->fci, fci->fci_cache)
376+
Z_PARAM_VARIADIC('*', fci->fci.params, fci->fci.param_count)
377+
ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
378+
379+
if (!s->list)
380+
{
381+
s->list = new queue<php_swoole_fci*>;
382+
}
383+
sw_zend_fci_cache_persist(&fci->fci_cache);
384+
sw_zend_fci_params_persist(&fci->fci);
385+
s->list->push(fci);
386+
}
387+
388+
static PHP_METHOD(swoole_coroutine_scheduler, start)
389+
{
390+
php_swoole_reactor_init();
391+
392+
scheduler_t *s = scheduler_get_object(Z_OBJ_P(getThis()));
393+
while (!s->list->empty())
394+
{
395+
php_swoole_fci *fci = s->list->front();
396+
s->list->pop();
397+
PHPCoroutine::create(&fci->fci_cache, fci->fci.param_count, fci->fci.params);
398+
sw_zend_fci_cache_discard(&fci->fci_cache);
399+
sw_zend_fci_params_discard(&fci->fci);
400+
efree(fci);
401+
}
402+
403+
php_swoole_event_wait();
404+
delete s->list;
405+
s->list = nullptr;
406+
}
407+
293408
PHP_METHOD(swoole_coroutine_scheduler, enableScheduler)
294409
{
295410
RETURN_BOOL(PHPCoroutine::enable_scheduler());
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
--TEST--
2+
swoole_coroutine_scheduler: user yield and resume1
3+
--SKIPIF--
4+
<?php require __DIR__ . '/../include/skipif.inc'; ?>
5+
--FILE--
6+
<?php
7+
require __DIR__ . '/../include/bootstrap.php';
8+
9+
$sch = new Co\Scheduler;
10+
11+
$sch->set(['max_coroutine' => 100]);
12+
13+
$sch->add(function ($t, $n) {
14+
Co::sleep($t);
15+
echo "$n\n";
16+
}, 0.2, 'A');
17+
18+
$sch->add(function ($t, $n) {
19+
Co::sleep($t);
20+
echo "$n\n";
21+
}, 0.1, 'B');
22+
23+
$sch->add(function () {
24+
var_dump(Co::getCid());
25+
});
26+
27+
$sch->start();
28+
29+
?>
30+
--EXPECTF--
31+
int(%d)
32+
B
33+
A

0 commit comments

Comments
 (0)