Title
directory_entry::status is not allowed to be cached as a quality-of-implementation issue
Status
resolved
Section
[fs.dir.entry.obs]
Submitter
Billy O'Neal

Created on 2016-03-03.00:00:00 last changed 101 months ago

Messages

Date: 2016-08-06.20:44:18

[ 2016-08, Beman comments ]

This will be resolved by P0317R1, Directory Entry Caching for Filesystem.

Fri AM: Moved to Tentatively Resolved

Date: 2016-04-16.04:21:53

[ 2016-04, Issues Telecon ]

Beman is working on a paper to address this.

Date: 2016-03-03.00:00:00

To fix multi-threading problems in directory_entry, caching behavior was removed from the type. This is bad for performance reasons, because the values can no longer be cached from the result of readdir on POSIX platforms, or from FindFirstFile/FindNextFile on Windows.

It appears that the intent was to allow implementers to fill in the values for directory_entry::status inside directory_iterator, but as currently specified:

Returns: status(path()[, ec]).

This is not allowed to be cached, because the target of the path can change. For example, consider the following program:

#include <stdio.h>
#include <stdlib.h>
#include <filesystem>
#include <fstream>

using namespace std;
namespace fs = ::std::filesystem;

void verify(const bool b, const char * const msg) {
    if (!b) {
        printf("fail: %s\n", msg);
        exit(1);
    }
}

void touch_file(const char * const filename) {
    ofstream f(filename);
    f << '\n' << endl;
    verify(f.good(), "File write failed");
}

int main() {
    fs::remove_all("subDir");
    fs::create_directory("subDir");
    fs::create_directory("subDir/child");
    touch_file("subDir/child/child");
    fs::current_path("./subDir");
    fs::directory_iterator dir(".");
    ++dir;
    fs::directory_entry entry = *dir;

    verify(entry == "./child",
      "unexpected subdirectory"); //enumerating "subDir" returned the directory "child"

    fs::file_status status = entry.status();
    verify(status.type() == fs::file_type::directory,
        "subDir/child was not a directory");
    fs::current_path("./child");
    status = entry.status(); // REQUIRED to re-stat() on POSIX,
                             // GetFileAttributes() on Windows
    verify(status.type() == fs::file_type::regular,
        "subDir/child/child was not a regular file");
    return 0;
}

directory_entry should be re-specified to allow implementers to cache the value of status(path) at the time irectory_iterator was incremented to avoid repeated stat() / GetFileAttributes calls. (This may mean additional constructors are necessary for directory_entry as well)

History
Date User Action Args
2016-08-06 20:44:18adminsetstatus: new -> resolved
2016-08-01 17:17:36adminsetmessages: + msg8273
2016-04-16 04:21:53adminsetmessages: + msg8054
2016-03-03 00:00:00admincreate