Skip to content

Commit

Permalink
libdeng2|FileSystem: Improving basic thread-safety
Browse files Browse the repository at this point in the history
The methods of File and Folder automatically lock the object. FileSystem
uses locking internally to protect access to the file indices.
  • Loading branch information
skyjake committed May 1, 2013
1 parent c192b27 commit 30c4e04
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 3 deletions.
22 changes: 22 additions & 0 deletions doomsday/libdeng2/src/filesys/file.cpp
Expand Up @@ -43,6 +43,8 @@ File::File(String const &fileName)

File::~File()
{
DENG2_GUARD(this);

DENG2_FOR_AUDIENCE(Deletion, i) i->fileBeingDeleted(*this);

flush();
Expand Down Expand Up @@ -80,6 +82,8 @@ FileSystem &File::fileSystem()

String File::description() const
{
DENG2_GUARD(this);

String desc = describe();
if(parent())
{
Expand Down Expand Up @@ -107,11 +111,15 @@ String File::describe() const

void File::setOriginFeed(Feed *feed)
{
DENG2_GUARD(this);

_originFeed = feed;
}

String const File::path() const
{
DENG2_GUARD(this);

String thePath = name();
for(Folder *i = _parent; i; i = i->_parent)
{
Expand All @@ -122,6 +130,8 @@ String const File::path() const

void File::setSource(File *source)
{
DENG2_GUARD(this);

if(_source != this)
{
// Delete the old source.
Expand All @@ -132,6 +142,8 @@ void File::setSource(File *source)

File const *File::source() const
{
DENG2_GUARD(this);

if(_source != this)
{
return _source->source();
Expand All @@ -141,6 +153,8 @@ File const *File::source() const

File *File::source()
{
DENG2_GUARD(this);

if(_source != this)
{
return _source->source();
Expand All @@ -150,6 +164,8 @@ File *File::source()

void File::setStatus(Status const &status)
{
DENG2_GUARD(this);

// The source file status is the official one.
if(this != _source)
{
Expand All @@ -163,6 +179,8 @@ void File::setStatus(Status const &status)

File::Status const &File::status() const
{
DENG2_GUARD(this);

if(this != _source)
{
return _source->status();
Expand All @@ -172,6 +190,8 @@ File::Status const &File::status() const

void File::setMode(Flags const &newMode)
{
DENG2_GUARD(this);

if(this != _source)
{
_source->setMode(newMode);
Expand All @@ -184,6 +204,8 @@ void File::setMode(Flags const &newMode)

File::Flags const &File::mode() const
{
DENG2_GUARD(this);

if(this != _source)
{
return _source->mode();
Expand Down
18 changes: 17 additions & 1 deletion doomsday/libdeng2/src/filesys/filesystem.cpp
Expand Up @@ -26,12 +26,14 @@
#include "de/PackageFolder"
#include "de/ZipArchive"
#include "de/Log"
#include "de/Lockable"
#include "de/Guard"

namespace de {

static FileSystem::Index const emptyIndex;

DENG2_PIMPL_NOREF(FileSystem)
DENG2_PIMPL_NOREF(FileSystem), public Lockable
{
/// The main index to all files in the file system.
FileSystem::Index index;
Expand Down Expand Up @@ -131,8 +133,12 @@ File *FileSystem::interpret(File *sourceData)
return sourceData;
}

#define DENG2_FS_GUARD_INDEX() DENG2_GUARD_FOR(*d, indexAccessGuard)

FileSystem::Index const &FileSystem::nameIndex() const
{
DENG2_FS_GUARD_INDEX();

return d->index;
}

Expand All @@ -149,6 +155,8 @@ int FileSystem::findAll(String const &path, FoundFiles &found) const
dir = "/" + dir;
}

DENG2_FS_GUARD_INDEX();

ConstIndexRange range = d->index.equal_range(baseName);
for(Index::const_iterator i = range.first; i != range.second; ++i)
{
Expand All @@ -168,6 +176,8 @@ File &FileSystem::find(String const &path) const

void FileSystem::index(File &file)
{
DENG2_FS_GUARD_INDEX();

String const lowercaseName = file.name().lower();

d->index.insert(IndexEntry(lowercaseName, &file));
Expand Down Expand Up @@ -200,6 +210,8 @@ static void removeFromIndex(FileSystem::Index &idx, File &file)

void FileSystem::deindex(File &file)
{
DENG2_FS_GUARD_INDEX();

removeFromIndex(d->index, file);
removeFromIndex(d->typeIndex[DENG2_TYPE_NAME(file)], file);
}
Expand All @@ -211,6 +223,8 @@ void FileSystem::timeChanged(Clock const &)

FileSystem::Index const &FileSystem::indexFor(String const &typeName) const
{
DENG2_FS_GUARD_INDEX();

Instance::TypeIndex::const_iterator found = d->typeIndex.find(typeName);
if(found != d->typeIndex.end())
{
Expand All @@ -225,6 +239,8 @@ FileSystem::Index const &FileSystem::indexFor(String const &typeName) const

void FileSystem::printIndex()
{
DENG2_FS_GUARD_INDEX();

LOG_DEBUG("Main FS index has %i entries") << d->index.size();

for(Index::iterator i = d->index.begin(); i != d->index.end(); ++i)
Expand Down
35 changes: 33 additions & 2 deletions doomsday/libdeng2/src/filesys/folder.cpp
Expand Up @@ -22,6 +22,7 @@
#include "de/FS"
#include "de/NumberValue"
#include "de/Log"
#include "de/Guard"

using namespace de;

Expand All @@ -30,12 +31,15 @@ Folder::Folder(String const &name) : File(name)
setStatus(Status::FOLDER);

// Standard info.
info().add(new Variable("contentSize", new Accessor(*this, Accessor::CONTENT_SIZE),
Accessor::VARIABLE_MODE));
info().add(new Variable("contentSize",
new Accessor(*this, Accessor::CONTENT_SIZE),
Accessor::VARIABLE_MODE));
}

Folder::~Folder()
{
DENG2_GUARD(this);

DENG2_FOR_AUDIENCE(Deletion, i) i->fileBeingDeleted(*this);
audienceForDeletion.clear();

Expand All @@ -53,6 +57,8 @@ Folder::~Folder()

String Folder::describe() const
{
DENG2_GUARD(this);

String desc = String("folder \"%1\" (with %2 items from %3 feeds")
.arg(name()).arg(_contents.size()).arg(_feeds.size());

Expand All @@ -69,6 +75,8 @@ String Folder::describe() const

void Folder::clear()
{
DENG2_GUARD(this);

if(_contents.empty()) return;

// Destroy all the file objects.
Expand All @@ -82,6 +90,8 @@ void Folder::clear()

void Folder::populate(PopulationBehavior behavior)
{
DENG2_GUARD(this);

LOG_AS("Folder");

// Prune the existing files first.
Expand Down Expand Up @@ -150,11 +160,15 @@ void Folder::populate(PopulationBehavior behavior)

Folder::Contents const &Folder::contents() const
{
DENG2_GUARD(this);

return _contents;
}

File &Folder::newFile(String const &newPath, FileCreationBehavior behavior)
{
DENG2_GUARD(this);

String path = newPath.fileNamePath();
if(!path.empty())
{
Expand Down Expand Up @@ -204,6 +218,8 @@ File &Folder::replaceFile(String const &newPath)

void Folder::removeFile(String const &removePath)
{
DENG2_GUARD(this);

String path = removePath.fileNamePath();
if(!path.empty())
{
Expand All @@ -229,12 +245,17 @@ void Folder::removeFile(String const &removePath)

bool Folder::has(String const &name) const
{
DENG2_GUARD(this);

return (_contents.find(name.lower()) != _contents.end());
}

File &Folder::add(File *file)
{
DENG2_GUARD(this);

DENG2_ASSERT(file != 0);

if(has(file->name()))
{
/// @throw DuplicateNameError All file names in a folder must be unique.
Expand All @@ -248,6 +269,8 @@ File &Folder::add(File *file)

File *Folder::remove(File &file)
{
DENG2_GUARD(this);

for(Contents::iterator i = _contents.begin(); i != _contents.end(); ++i)
{
if(i->second == &file)
Expand All @@ -273,6 +296,8 @@ File *Folder::tryLocateFile(String const &path) const
return fileSystem().root().tryLocateFile(path.substr(1));
}

DENG2_GUARD(this);

// Extract the next component.
String::size_type end = path.indexOf('/');
if(end == String::npos)
Expand Down Expand Up @@ -322,11 +347,15 @@ File *Folder::tryLocateFile(String const &path) const

void Folder::attach(Feed *feed)
{
DENG2_GUARD(this);

_feeds.push_back(feed);
}

Feed *Folder::detach(Feed &feed)
{
DENG2_GUARD(this);

_feeds.remove(&feed);
return &feed;
}
Expand All @@ -336,6 +365,8 @@ Folder::Accessor::Accessor(Folder &owner, Property prop) : _owner(owner), _prop(

void Folder::Accessor::update() const
{
DENG2_GUARD(_owner);

// We need to alter the value content.
Accessor *nonConst = const_cast<Accessor *>(this);

Expand Down

0 comments on commit 30c4e04

Please sign in to comment.