spawn

为了易用性,我们为AsyncTask的创建一个可灵活传递参数函数入口。

  1. <?php
  2. /**
  3. * spawn one semicoroutine
  4. *
  5. * @internal param callable|\Generator|mixed $task
  6. * @internal param callable $continuation function($r = null, $ex = null) {}
  7. * @internal param AsyncTask $parent
  8. * @internal param array $ctx Context也可以附加在 \Generator 对象的属性上
  9. *
  10. * 第一个参数为task
  11. * 剩余参数(优先检查callable)
  12. * 如果参数类型 callable 则参数被设置为 Continuation
  13. * 如果参数类型 AsyncTask 则参数被设置为 ParentTask
  14. * 如果参数类型 array 则参数被设置为 Context
  15. */
  16. function spawn()
  17. {
  18. $n = func_num_args();
  19. if ($n === 0) {
  20. return;
  21. }
  22. $task = func_get_arg(0);
  23. $continuation = function() {};
  24. $parent = null;
  25. $ctx = [];
  26. for ($i = 1; $i < $n; $i++) {
  27. $arg = func_get_arg($i);
  28. if (is_callable($arg)) {
  29. $continuation = $arg;
  30. } else if ($arg instanceof AsyncTask) {
  31. $parent = $arg;
  32. } else if (is_array($arg)) {
  33. $ctx = $arg;
  34. }
  35. }
  36. if (is_callable($task)) {
  37. try {
  38. $task = $task();
  39. } catch (\Exception $ex) {
  40. $continuation(null, $ex);
  41. return;
  42. }
  43. }
  44. if ($task instanceof \Generator) {
  45. foreach ($ctx as $k => $v) {
  46. $task->$k = $v;
  47. }
  48. (new AsyncTask($task, $parent))->begin($continuation);
  49. } else {
  50. $continuation($task, null);
  51. }
  52. }