ForkingIterator   A
last analyzed

Complexity

Total Complexity 22

Size/Duplication

Total Lines 93
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 1

Importance

Changes 0
Metric Value
wmc 22
lcom 1
cbo 1
dl 0
loc 93
rs 10
c 0
b 0
f 0

8 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 3
A supportsFork() 0 4 1
A isForkingEnabled() 0 4 2
A fork() 0 12 3
A wait() 0 6 1
B rewind() 0 25 7
A valid() 0 10 3
A next() 0 7 2
1
<?php
2
3
namespace itertools;
4
5
use UnexpectedValueException;
6
use IteratorIterator;
7
use ArrayIterator;
8
9
10
class ForkingIterator extends IteratorIterator
11
{
12
	const IS_CHILD = 0;
13
	const ENABLED = true;
14
	const DISABLED = false;
15
16
	protected $isChild = false;
17
	protected $childCount = 0;
18
	protected $forkingEnabled;
19
	protected $maxChildren;
20
21
	public function __construct($innerIterator, $options = array())
22
	{
23
		parent::__construct(IterUtil::asTraversable($innerIterator));
24
		$this->forkingEnabled = array_key_exists('forkingEnabled', $options) ? $options['forkingEnabled'] : self::ENABLED;
25
		$this->maxChildren = array_key_exists('maxChildren', $options) ? $options['maxChildren'] : 8;
26
	}
27
28
	public static function supportsFork()
29
	{
30
		return function_exists('pcntl_fork');
31
	}
32
33
	public function isForkingEnabled()
34
	{
35
		return $this->forkingEnabled && self::supportsFork();
36
	}
37
38
	protected function fork()
39
	{
40
		$pid = pcntl_fork();
41
		if($pid == -1) {
42
			throw new UnexpectedValueException('Could not fork');
43
		}
44
		if($pid == self::IS_CHILD) {
45
			$this->isChild = true;
46
		}
47
		$this->childCount += 1;
48
		return $pid;
49
	}
50
51
	protected function wait()
52
	{
53
		pcntl_wait($status);
0 ignored issues
show
Bug introduced by
The variable $status does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
54
		$this->childCount -= 1;
55
		return $status;
56
	}
57
58
	public function rewind()
59
	{
60
		if(!$this->isForkingEnabled()) {
61
			return parent::rewind();
62
		}
63
64
		parent::rewind();
65
		$status = 0;
66
		do {
67
			if($this->fork() == self::IS_CHILD) {
68
				return;
69
			}
70
			while($this->childCount >= $this->maxChildren) {
71
				$status |= $this->wait();
72
			}
73
			parent::next();
0 ignored issues
show
Comprehensibility Bug introduced by
It seems like you call parent on a different method (next() instead of rewind()). Are you sure this is correct? If so, you might want to change this to $this->next().

This check looks for a call to a parent method whose name is different than the method from which it is called.

Consider the following code:

class Daddy
{
    protected function getFirstName()
    {
        return "Eidur";
    }

    protected function getSurName()
    {
        return "Gudjohnsen";
    }
}

class Son
{
    public function getFirstName()
    {
        return parent::getSurname();
    }
}

The getFirstName() method in the Son calls the wrong method in the parent class.

Loading history...
74
		} while(parent::valid());
0 ignored issues
show
Comprehensibility Bug introduced by
It seems like you call parent on a different method (valid() instead of rewind()). Are you sure this is correct? If so, you might want to change this to $this->valid().

This check looks for a call to a parent method whose name is different than the method from which it is called.

Consider the following code:

class Daddy
{
    protected function getFirstName()
    {
        return "Eidur";
    }

    protected function getSurName()
    {
        return "Gudjohnsen";
    }
}

class Son
{
    public function getFirstName()
    {
        return parent::getSurname();
    }
}

The getFirstName() method in the Son calls the wrong method in the parent class.

Loading history...
75
76
		while($this->childCount > 0) {
77
			$status |= $this->wait();
78
		}
79
		if($status !== 0) {
80
			throw new UnexpectedValueException('Child exited with non zero status');
81
		}
82
	}
83
84
	public function valid()
85
	{
86
		if(!$this->isForkingEnabled()) {
87
			return parent::valid();
88
		}
89
		if(!$this->isChild) {
90
			return false;
91
		}
92
		return parent::valid();
93
	}
94
95
	public function next()
96
	{
97
		if(!$this->isForkingEnabled()) {
98
			return parent::next();
99
		}
100
		exit;
101
	}
102
}
103
104