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