10000 bug #40040 [Finder] Use a lazyIterator to close files descriptors whe… · symfony/symfony@dc20a31 · GitHub
[go: up one dir, main page]

Skip to content

Commit dc20a31

Browse files
committed
bug #40040 [Finder] Use a lazyIterator to close files descriptors when no longer used (jderusse)
This PR was merged into the 4.4 branch. Discussion ---------- [Finder] Use a lazyIterator to close files descriptors when no longer used | Q | A | ------------- | --- | Branch? | 4.4 | Bug fix? | yes | New feature? | no | Deprecations? | no | Tickets | fix #35508 | License | MIT | Doc PR | - The `RecursiveDirectoryIterator` class open the file on `__construct`. Because we Inject an instance of `RecursiveDirectoryIterator` inside the \AppendIterator` class, php opens a lot of file even before iterating on it. This PR adds a new `LazyIterator` class that instantiate the decorated class only when something starts iterating on it. When the iteration is over, it unset the variable to close let the decorated class clean things (ie. close the files) Commits ------- 7117e1a Use a lazyintertor to close files descriptors when no longer used
2 parents 79ccf88 + 7117e1a commit dc20a31

File tree

3 files changed

+87
-1
lines changed

3 files changed

+87
-1
lines changed

src/Symfony/Component/Finder/Finder.php

Lines changed: 4 additions & 1 deletion
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 \IteratorIterator(new LazyIterator(function () use ($dir) {
640+
return $this->searchInDirectory($dir);
641+
})));
639642
}
640643

641644
foreach ($this->iterators as $it) {
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
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 \IteratorAggregate
18+
{
19+
private $iteratorFactory;
20+
21+
public function __construct(callable $iteratorFactory)
22+
{
23+
$this->iteratorFactory = $iteratorFactory;
24+
}
25+
26+
public function getIterator()
27+
{
28+
yield from ($this->iteratorFactory)();
29+
}
30+
}
Lines changed: 53 additions & 0 deletions
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)
0