Skip to content

Commit c1b3e9b

Browse files
committed
Use a lazyintertor to close files descriptors when no longer used
1 parent 945c7c5 commit c1b3e9b

File tree

3 files changed

+116
-1
lines changed

3 files changed

+116
-1
lines changed

src/Symfony/Component/Finder/Finder.php

+4-1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
use Symfony\Component\Finder\Iterator\ExcludeDirectoryFilterIterator;
2121
use Symfony\Component\Finder\Iterator\FilecontentFilterIterator;
2222
use Symfony\Component\Finder\Iterator\FilenameFilterIterator;
23+
use Symfony\Component\Finder\Iterator\LazyIterator;
2324
use Symfony\Component\Finder\Iterator\SizeRangeFilterIterator;
2425
use Symfony\Component\Finder\Iterator\SortableIterator;
2526

@@ -635,7 +636,9 @@ public function getIterator()
635636

636637
$iterator = new \AppendIterator();
637638
foreach ($this->dirs as $dir) {
638-
$iterator->append($this->searchInDirectory($dir));
639+
$iterator->append(new LazyIterator(function () use ($dir) {
640+
return $this->searchInDirectory($dir);
641+
}));
639642
}
640643

641644
foreach ($this->iterators as $it) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Finder\Iterator;
13+
14+
/**
15+
* @author Jérémy Derussé <jeremy@derusse.com>
16+
*/
17+
class LazyIterator implements \Iterator
18+
{
19+
/** @var callable */
20+
private $iteratorFactory;
21+
/** @var \Iterator */
22+
private $iterator;
23+
24+
public function __construct(callable $iteratorFactory)
25+
{
26+
$this->iteratorFactory = $iteratorFactory;
27+
}
28+
29+
public function current()
30+
{
31+
return ($this->iterator ?? $this->iterator = ($this->iteratorFactory)())->current();
32+
}
33+
34+
public function next()
35+
{
36+
($this->iterator ?? $this->iterator = ($this->iteratorFactory)())->next();
37+
}
38+
39+
public function key()
40+
{
41+
return ($this->iterator ?? $this->iterator = ($this->iteratorFactory)())->key();
42+
}
43+
44+
public function valid()
45+
{
46+
if (($this->iterator ?? $this->iterator = ($this->iteratorFactory)())->valid()) {
47+
return true;
48+
}
49+
50+
$this->iterator = null;
51+
52+
return false;
53+
}
54+
55+
public function rewind()
56+
{
57+
($this->iterator = ($this->iteratorFactory)())->rewind();
58+
}
59+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Finder\Tests\Iterator;
13+
14+
use PHPUnit\Framework\TestCase;
15+
use Symfony\Component\Finder\Iterator\LazyIterator;
16+
17+
class LazyIteratorTest extends TestCase
18+
{
19+
public function testLazy()
20+
{
21+
new LazyIterator(function () {
22+
$this->markTestFailed('lazyIterator should not be called');
23+
});
24+
25+
$this->expectNotToPerformAssertions();
26+
}
27+
28+
public function testDelegate()
29+
{
30+
$iterator = new LazyIterator(function () {
31+
return new Iterator(['foo', 'bar']);
32+
});
33+
34+
$this->assertCount(2, $iterator);
35+
}
36+
37+
public function testInnerDestructedAtTheEnd()
38+
{
39+
$count = 0;
40+
$iterator = new LazyIterator(function () use (&$count) {
41+
++$count;
42+
43+
return new Iterator(['foo', 'bar']);
44+
});
45+
46+
foreach ($iterator as $x) {
47+
}
48+
$this->assertSame(1, $count);
49+
foreach ($iterator as $x) {
50+
}
51+
$this->assertSame(2, $count);
52+
}
53+
}

0 commit comments

Comments
 (0)