WIP: Implement Filesystem TS
Jonathan Wakely
jwakely@redhat.com
Tue Aug 5 13:42:00 GMT 2014
On 05/08/14 14:37 +0100, Jonathan Wakely wrote:
>On 05/08/14 09:24 -0400, Ed Smith-Rowland wrote:
>>On 08/04/2014 01:11 PM, Jonathan Wakely wrote:
>>>* directory_iterator holds a shared_ptr<_Dir> where _Dir is a pimpl
>>>class containing a DIR* returned by opendir(), a path object
>>>containing the path the dir was opened with, and a directory_entry
>>>object that gets returned by dereferencing the iterator. It also
>>>contained a file_type enumeration, which gets used on GNU and BSD
>>>platforms where the dirent struct contains the file type, which
>>>means no stat() system call is needed to find out whether the
>>>current entry is a directory and should be recursed into.
>>Why not unique_ptr?
>
>Copies of a directory_iterator should refer to the same underlying
>DIR, like istream_iterator.
>
>>>* recursive_directory_iterator holds a shared_ptr to a
>>>stack<pair<_Dir, directory_iterator>> representing each directory
>>>recursed into and the position within that directory. The
>>>shared_ptr<_Dir>s belong to the directory_iterator objects in the
>>>stack alias the shared_ptr held by the parent
>>>recursive_directory_iterator, so the reference counts are shared by
>>>the whole stack.
>>>
>>
>>Tidbit: Explicit return bool in create_directories (ec version)? I'm
>>not sure when true should be returned though.
>
>Yep, already fixed in my tree to do:
>
> return missing.empty();
Here's another patch, to be applied on top of yesterday's, although I
think I'm going to rework the whole _Dir_stack implementation to try
and simplify it to be just std::stack<_Dir>.
-------------- next part --------------
diff --git a/libstdc++-v3/include/experimental/fs_dir.h b/libstdc++-v3/include/experimental/fs_dir.h
index e4a245e..cb3d179 100644
--- a/libstdc++-v3/include/experimental/fs_dir.h
+++ b/libstdc++-v3/include/experimental/fs_dir.h
@@ -256,7 +256,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
recursive_directory_iterator(
recursive_directory_iterator&&) noexcept = default;
- ~recursive_directory_iterator() = default;
+ ~recursive_directory_iterator();
// observers
directory_options options() const { return _M_options; }
@@ -268,7 +268,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// modifiers
recursive_directory_iterator&
- operator=(const recursive_directory_iterator& rhs);
+ operator=(const recursive_directory_iterator& rhs) noexcept;
recursive_directory_iterator&
operator=(recursive_directory_iterator&& rhs) noexcept;
@@ -291,15 +291,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
const recursive_directory_iterator& __rhs)
{ return __lhs._M_dirs == __rhs._M_dirs; }
-
private:
recursive_directory_iterator(const path&, directory_options, error_code*);
void _M_push(_Dir&&, error_code*);
+ void _M_reset();
struct _Dir_stack;
- // using _Dir_iter = std::pair<_Dir, directory_iterator>;
- // using _Dir_stack = std::stack<_Dir_iter, std::vector<_Dir_iter>>;
std::shared_ptr<_Dir_stack> _M_dirs;
directory_options _M_options;
bool _M_pending;
diff --git a/libstdc++-v3/src/filesystem/dir.cc b/libstdc++-v3/src/filesystem/dir.cc
index e6009c4..392a677 100644
--- a/libstdc++-v3/src/filesystem/dir.cc
+++ b/libstdc++-v3/src/filesystem/dir.cc
@@ -246,6 +246,8 @@ struct fs::recursive_directory_iterator::_Dir_stack : std::stack<Dir_iter_pair>
{
// need to empty the stack first, to break reference cycles
~_Dir_stack() { c.clear(); }
+
+ void clear() { c.clear(); }
};
fs::recursive_directory_iterator::
@@ -258,7 +260,7 @@ recursive_directory_iterator(const path& p, directory_options options,
_M_dirs = std::make_shared<_Dir_stack>();
_M_push( _Dir{ dirp, p }, ec );
if (ec && ec->value())
- _M_dirs.reset();
+ _M_reset();
}
else
{
@@ -276,6 +278,11 @@ recursive_directory_iterator(const path& p, directory_options options,
}
}
+fs::recursive_directory_iterator::~recursive_directory_iterator()
+{
+ _M_reset();
+}
+
int
fs::recursive_directory_iterator::depth() const
{
@@ -289,6 +296,24 @@ fs::recursive_directory_iterator::operator*() const
}
fs::recursive_directory_iterator&
+fs::recursive_directory_iterator::
+operator=(const recursive_directory_iterator& other) noexcept
+{
+ _M_reset();
+ _M_dirs = other._M_dirs;
+ return *this;
+}
+
+fs::recursive_directory_iterator&
+fs::recursive_directory_iterator::
+operator=(recursive_directory_iterator&& other) noexcept
+{
+ _M_reset();
+ _M_dirs = std::move(other._M_dirs);
+ return *this;
+}
+
+fs::recursive_directory_iterator&
fs::recursive_directory_iterator::operator++()
{
error_code ec;
@@ -398,3 +423,13 @@ fs::recursive_directory_iterator::_M_push(_Dir&& dir, error_code* ec)
// N.B. This creates a reference cycle in _M_dirs
top.second = directory_iterator{ shared_ptr<_Dir>{_M_dirs, &top.first}, ec };
}
+
+void
+fs::recursive_directory_iterator::_M_reset()
+{
+ if (_M_dirs && (unsigned long)_M_dirs.use_count() == 2 + _M_dirs->size())
+ {
+ _M_dirs->clear();
+ _M_dirs.reset();
+ }
+}
More information about the Libstdc++
mailing list