forked from alash3al/axync
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathaxync.php
More file actions
114 lines (108 loc) · 2.74 KB
/
axync.php
File metadata and controls
114 lines (108 loc) · 2.74 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
<?php
/**
* Axync - a cooperative multitasking kernel for PHP7, lets take PHP out of the box, just for the fun .
*
* This library uses PHP 7 features to create a simple and smart co-operative multitasking,
* you can easily use it as a main loop but also you can use it as a child co-operative multitasking processor,
* i created this library for the following reasons:
* - just for fun .
* - to prove that you can do what you want only if you want .
* - the issue isn't with the tool you are using, but <IT IS IN YOU> .
* - again just for fun .
*
* @version 1.0
* @license MIT License
* @author Mohammed Al Ashaal <alash3al.xyz>
*/
Class Axync {
/**
* array of registered coroutines
* @var array $coroutines
*/
protected $coroutines = [];
/**
* Constructor
*
* @param Callable ... $params
* @return $this
*/
public function __construct(Callable ... $params) {
$this->register(...$params);
}
/**
* register Generatable callbacks (callbacks that return generators)
*
* @param Callable ... $params
* @return $this
*/
public function register(Callable ... $params) {
foreach ( $params as $i => $obj ) {
$this->coroutines[] = $obj;
}
return $this;
}
/**
* execute each registered coroutine once .
*
* @return $this
*/
protected function tick() {
foreach ( $this->coroutines as $i => $co ) {
if ( is_callable($co) ) {
$co = $this->coroutines[$i] = $co();
if ( ! $co instanceof Generator ) {
throw new InvalidArgumentException(sprintf("The axync worker(%s) not valid", $i));
}
$co->rewind();
} else if ( ! $co->valid() ) {
unset($this->coroutines[$i]);
} else {
$co->next();
}
}
}
/**
* create a generator based tick.
*
* @return Generator
*/
protected function tickYield() {
foreach ( $this->coroutines as $i => $co ) {
if ( is_callable($co) ) {
$co = $this->coroutines[$i] = $co();
if ( ! $co instanceof Generator ) {
throw new InvalidArgumentException(sprintf("The axync worker(%s) not valid", $i));
}
$co->rewind();
} else if ( ! $co->valid() ) {
unset($this->coroutines[$i]);
} else {
$co->next();
}
yield;
}
}
/**
* execute each registered coroutine till the end (blocking operation) .
*
* @return $this
*/
public function exec() {
while ( sizeof($this->coroutines) > 0 ) {
$this->tick();
}
return $this;
}
/**
* create a generator that will execute each registered coroutine (non-blocking operation) .
*
* @return Generator
*/
public function toGenerator() {
return function(){
while ( sizeof($this->coroutines) > 0 ) {
yield from $this->tickYield();
}
};
}
}