This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of TS status.
Section: 12 [filesys.ts::class.directory_entry] Status: TS Submitter: Stephan T. Lavavej Opened: 2014-02-03 Last modified: 2017-07-30
Priority: Not Prioritized
View all other issues in [filesys.ts::class.directory_entry].
View all issues with TS status.
Discussion:
Addresses: filesys.ts
12 [class.directory_entry] depicts directory_entry as having mutable m_status and m_symlink_status data members. This is problematic because of C++11's multithreading guarantees, which say that const member functions are simultaneously callable. As a result, mutable data members must be protected with synchronization, which was probably not considered during this design. The complexity and expense may be acceptable in directory_entry (since it can save filesystem queries, apparently) but it would be very very nice to have a note about this.
[2014-02-13 LWG/SG-3 discussed in Issaquah: Beman and STL will work together to better understand the concerns, and to formulate a solution. This is not a blocking issue for finishing the TS, but is a blocking issue for merging into the IS]
[2014-04-17 Beman provides proposed wording]
[2014-06-19 Rapperswil LWG decides to remove mutable private members. Beman provides wording.]
Proposed resolution:
Change 12 [class.directory_entry] as indicated:
namespace std { namespace experimental { namespace filesystem { inline namespace v1 {
class directory_entry
{
public:
// constructors and destructor
directory_entry() = default;
directory_entry(const directory_entry&) = default;
directory_entry(directory_entry&&) noexcept = default;
explicit directory_entry(const path& p);
explicit directory_entry(const path& p, file_status st=file_status(),
file_status symlink_st=file_status());
~directory_entry();
// modifiers
directory_entry& operator=(const directory_entry&) = default;
directory_entry& operator=(directory_entry&&) noexcept = default;
void assign(const path& p);
void assign(const path& p, file_status st=file_status(),
file_status symlink_st=file_status());
void replace_filename(const path& p);
void replace_filename(const path& p, file_status st=file_status(),
file_status symlink_st=file_status());
// observers
const path& path() const noexcept;
file_status status() const;
file_status status(error_code& ec) const noexcept;
file_status symlink_status() const;
file_status symlink_status(error_code& ec) const noexcept;
bool operator< (const directory_entry& rhs) const noexcept;
bool operator==(const directory_entry& rhs) const noexcept;
bool operator!=(const directory_entry& rhs) const noexcept;
bool operator<=(const directory_entry& rhs) const noexcept;
bool operator> (const directory_entry& rhs) const noexcept;
bool operator>=(const directory_entry& rhs) const noexcept;
private:
path m_path; // for exposition only
mutable file_status m_status; // for exposition only; stat()-like
mutable file_status m_symlink_status; // for exposition only; lstat()-like
};
} } } } // namespaces std::experimental::filesystem::v1
A directory_entry object stores a path object,
a .
file_status object for non-symbolic link status, and a file_status object for symbolic link status
The
file_status objects act as value caches.
[Note: Becausestatus()on a pathname may be a relatively expensive operation, some operating systems provide status information as a byproduct of directory iteration. Caching such status information can result in significant time savings. Cached and non-cached results may differ in the presence of file system races. —end note]
directory_entry constructors
[directory_entry.cons]
Add the description of this constructor in its entirety:
explicit directory_entry(const path& p);
Effects: Constructs an object of typedirectory_entryPostcondition:
path() == p.
explicit directory_entry(const path& p, file_status st=file_status(),file_status symlink_st=file_status());
Strike the description
directory_entry modifiers
[directory_entry.mods]
Add the description of this function in its entirety:
void assign(const path& p);
Postcondition:
path() == p.
void assign(const path& p, file_status st=file_status(),file_status symlink_st=file_status());
Strike the description
Add the description of this function in its entirety:
void replace_filename(const path& p);
Postcondition:
path() == x.parent_path() / pwherexis the value ofpath()before the function is called.
void replace_filename(const path& p, file_status st=file_status(),file_status symlink_st=file_status());
Strike the description
directory_entry observers
[directory_entry.obs]
const path& path() const noexcept;
Returns:
m_path
file_status status() const; file_status status(error_code& ec) const noexcept;
Effects: As if,if (!status_known(m_status)) { if (status_known(m_symlink_status) && !is_symlink(m_symlink_status)) { m_status = m_symlink_status; } else { m_status = status(m_path[, ec]); } }Returns:
.m_statusstatus(path()[, ec])Throws: As specified in Error reporting (7).
file_status symlink_status() const; file_status symlink_status(error_code& ec) const noexcept;
Effects: As if,if (!status_known(m_symlink_status)) { m_symlink_status = symlink_status(m_path[, ec]); }Returns:
.m_symlink_statussymlink_status(path()[, ec])Throws: As specified in Error reporting (7).
bool operator==(const directory_entry& rhs) const noexcept;
Returns:
m_path == rhs.m_path.
[Note: Status members do not participate in determining equality. — end note]
bool operator!=(const directory_entry& rhs) const noexcept;
Returns:
m_path != rhs.m_path.
bool operator< (const directory_entry& rhs) const noexcept;
Returns:
m_path < rhs.m_path.
bool operator<=(const directory_entry& rhs) const noexcept;
Returns:
m_path <= rhs.m_path.
bool operator> (const directory_entry& rhs) const noexcept;
Returns:
m_path > rhs.m_path.
bool operator>=(const directory_entry& rhs) const noexcept;
Returns:
m_path >= rhs.m_path.