From 7117e1a798f396f288635f93a66d30bf8a387784 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Deruss=C3=A9?= Date: Sat, 30 Jan 2021 17:17:32 +0100 Subject: [PATCH] Use a lazyintertor to close files descriptors when no longer used --- src/Symfony/Component/Finder/Finder.php | 5 +- .../Finder/Iterator/LazyIterator.php | 30 +++++++++++ .../Tests/Iterator/LazyIteratorTest.php | 53 +++++++++++++++++++ 3 files changed, 87 insertions(+), 1 deletion(-) create mode 100644 src/Symfony/Component/Finder/Iterator/LazyIterator.php create mode 100644 src/Symfony/Component/Finder/Tests/Iterator/LazyIteratorTest.php diff --git a/src/Symfony/Component/Finder/Finder.php b/src/Symfony/Component/Finder/Finder.php index 82c2ec78dc..87fc187b2f 100644 --- a/src/Symfony/Component/Finder/Finder.php +++ b/src/Symfony/Component/Finder/Finder.php @@ -20,6 +20,7 @@ use Symfony\Component\Finder\Iterator\DepthRangeFilterIterator; use Symfony\Component\Finder\Iterator\ExcludeDirectoryFilterIterator; use Symfony\Component\Finder\Iterator\FilecontentFilterIterator; use Symfony\Component\Finder\Iterator\FilenameFilterIterator; +use Symfony\Component\Finder\Iterator\LazyIterator; use Symfony\Component\Finder\Iterator\SizeRangeFilterIterator; use Symfony\Component\Finder\Iterator\SortableIterator; @@ -635,7 +636,9 @@ class Finder implements \IteratorAggregate, \Countable $iterator = new \AppendIterator(); foreach ($this->dirs as $dir) { - $iterator->append($this->searchInDirectory($dir)); + $iterator->append(new \IteratorIterator(new LazyIterator(function () use ($dir) { + return $this->searchInDirectory($dir); + }))); } foreach ($this->iterators as $it) { diff --git a/src/Symfony/Component/Finder/Iterator/LazyIterator.php b/src/Symfony/Component/Finder/Iterator/LazyIterator.php new file mode 100644 index 0000000000..4388f4f3fd --- /dev/null +++ b/src/Symfony/Component/Finder/Iterator/LazyIterator.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Finder\Iterator; + +/** + * @author Jérémy Derussé + */ +class LazyIterator implements \IteratorAggregate +{ + private $iteratorFactory; + + public function __construct(callable $iteratorFactory) + { + $this->iteratorFactory = $iteratorFactory; + } + + public function getIterator() + { + yield from ($this->iteratorFactory)(); + } +} diff --git a/src/Symfony/Component/Finder/Tests/Iterator/LazyIteratorTest.php b/src/Symfony/Component/Finder/Tests/Iterator/LazyIteratorTest.php new file mode 100644 index 0000000000..1a96c32d0b --- /dev/null +++ b/src/Symfony/Component/Finder/Tests/Iterator/LazyIteratorTest.php @@ -0,0 +1,53 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Finder\Tests\Iterator; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Finder\Iterator\LazyIterator; + +class LazyIteratorTest extends TestCase +{ + public function testLazy() + { + new LazyIterator(function () { + $this->markTestFailed('lazyIterator should not be called'); + }); + + $this->expectNotToPerformAssertions(); + } + + public function testDelegate() + { + $iterator = new LazyIterator(function () { + return new Iterator(['foo', 'bar']); + }); + + $this->assertCount(2, $iterator); + } + + public function testInnerDestructedAtTheEnd() + { + $count = 0; + $iterator = new LazyIterator(function () use (&$count) { + ++$count; + + return new Iterator(['foo', 'bar']); + }); + + foreach ($iterator as $x) { + } + $this->assertSame(1, $count); + foreach ($iterator as $x) { + } + $this->assertSame(2, $count); + } +}