Skip to content
Snippets Groups Projects
Commit 29627fd5 authored by Axel Naumann's avatar Axel Naumann
Browse files

Mostly-clang-format io/io/v7.

parent 3ca97e61
No related branches found
No related tags found
No related merge requests found
......@@ -2,7 +2,8 @@
/// \ingroup Base ROOT7
/// \author Axel Naumann <axel@cern.ch>
/// \date 2015-07-31
/// \warning This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback is welcome!
/// \warning This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback
/// is welcome!
/*************************************************************************
* Copyright (C) 1995-2016, Rene Brun and Fons Rademakers. *
......@@ -31,7 +32,7 @@ class TFilePtr;
namespace Internal {
class TFileStorageInterface;
class TFileSharedPtrCtor;
}
} // namespace Internal
/** \class ROOT::Experimental::TFile
A ROOT file.
......@@ -43,135 +44,133 @@ class TFileSharedPtrCtor;
*/
class TFile: public TDirectory {
private:
std::unique_ptr<Internal::TFileStorageInterface> fStorage; ///< Storage backend.
std::unique_ptr<Internal::TFileStorageInterface> fStorage; ///< Storage backend.
TFile(std::unique_ptr<Internal::TFileStorageInterface>&& storage);
TFile(std::unique_ptr<Internal::TFileStorageInterface> &&storage);
/// Serialize the object at address, using the object's TClass.
//FIXME: what about `cl` "pointing" to a base class?
void WriteMemoryWithType(std::string_view name, const void *address,
TClass *cl);
/// Serialize the object at address, using the object's TClass.
// FIXME: what about `cl` "pointing" to a base class?
void WriteMemoryWithType(std::string_view name, const void *address, TClass *cl);
friend Internal::TFileSharedPtrCtor;
friend Internal::TFileSharedPtrCtor;
public:
/// Options for TFile construction.
struct Options_t {
/// Default constructor needed for member inits.
Options_t() { }
/// Whether the file should be opened asynchronously, if available.
bool fAsynchronousOpen = false;
/// Timeout for asynchronous opening.
int fAsyncTimeout = 0;
/// Whether the file should be cached before reading. Only available for
/// "remote" file protocols. If the download fails, the file will be opened
/// remotely.
bool fCachedRead = false;
/// Where to cache the file. If empty, defaults to TFilePtr::GetCacheDir().
std::string fCacheDir;
};
///\name Generator functions
///\{
/// Open a file with `name` for reading.
///
/// \note: Synchronizes multi-threaded accesses through locks.
static TFilePtr Open(std::string_view name,
const Options_t &opts = Options_t());
/// Open an existing file with `name` for reading and writing. If a file with
/// that name does not exist, an invalid TFilePtr will be returned.
///
/// \note: Synchronizes multi-threaded accesses through locks.
static TFilePtr OpenForUpdate(std::string_view name,
const Options_t &opts = Options_t());
/// Open a file with `name` for reading and writing. Fail (return an invalid
/// `TFilePtr`) if a file with this name already exists.
///
/// \note: Synchronizes multi-threaded accesses through locks.
static TFilePtr Create(std::string_view name,
const Options_t &opts = Options_t());
/// Open a file with `name` for reading and writing. If a file with this name
/// already exists, delete it and create a new one. Else simply create a new file.
///
/// \note: Synchronizes multi-threaded accesses through locks.
static TFilePtr Recreate(std::string_view name,
const Options_t &opts = Options_t());
///\}
/// Set the new directory used for cached reads, returns the old directory.
///
/// \note: Synchronizes multi-threaded accesses through locks.
static std::string SetCacheDir(std::string_view path);
/// Get the directory used for cached reads.
static std::string GetCacheDir();
/// Must not call Write() of all attached objects:
/// some might not be needed to be written or writing might be aborted due to
/// an exception; require explicit Write().
~TFile();
/// Save all objects associated with this directory (including file header) to
/// the storage medium.
void Flush();
/// Flush() and make the file non-writable: close it.
void Close();
/// Read the object for a key. `T` must be the object's type.
/// This will re-read the object for each call, returning a new copy; whether
/// the `TDirectory` is managing an object attached to this key or not.
/// \returns a `unique_ptr` to the object.
/// \throws TDirectoryUnknownKey if no object is stored under this name.
/// \throws TDirectoryTypeMismatch if the object stored under this name is of
/// a type different from `T`.
template<class T>
std::unique_ptr<T> Read(std::string_view name) {
// FIXME: need separate collections for a TDirectory's key/value and registered objects. Here, we want to emit a read and must look through the key/values without attaching an object to the TDirectory.
/// Options for TFile construction.
struct Options_t {
/// Default constructor needed for member inits.
Options_t() {}
/// Whether the file should be opened asynchronously, if available.
bool fAsynchronousOpen = false;
/// Timeout for asynchronous opening.
int fAsyncTimeout = 0;
/// Whether the file should be cached before reading. Only available for
/// "remote" file protocols. If the download fails, the file will be opened
/// remotely.
bool fCachedRead = false;
/// Where to cache the file. If empty, defaults to TFilePtr::GetCacheDir().
std::string fCacheDir;
};
///\name Generator functions
///\{
/// Open a file with `name` for reading.
///
/// \note: Synchronizes multi-threaded accesses through locks.
static TFilePtr Open(std::string_view name, const Options_t &opts = Options_t());
/// Open an existing file with `name` for reading and writing. If a file with
/// that name does not exist, an invalid TFilePtr will be returned.
///
/// \note: Synchronizes multi-threaded accesses through locks.
static TFilePtr OpenForUpdate(std::string_view name, const Options_t &opts = Options_t());
/// Open a file with `name` for reading and writing. Fail (return an invalid
/// `TFilePtr`) if a file with this name already exists.
///
/// \note: Synchronizes multi-threaded accesses through locks.
static TFilePtr Create(std::string_view name, const Options_t &opts = Options_t());
/// Open a file with `name` for reading and writing. If a file with this name
/// already exists, delete it and create a new one. Else simply create a new file.
///
/// \note: Synchronizes multi-threaded accesses through locks.
static TFilePtr Recreate(std::string_view name, const Options_t &opts = Options_t());
///\}
/// Set the new directory used for cached reads, returns the old directory.
///
/// \note: Synchronizes multi-threaded accesses through locks.
static std::string SetCacheDir(std::string_view path);
/// Get the directory used for cached reads.
static std::string GetCacheDir();
/// Must not call Write() of all attached objects:
/// some might not be needed to be written or writing might be aborted due to
/// an exception; require explicit Write().
~TFile();
/// Save all objects associated with this directory (including file header) to
/// the storage medium.
void Flush();
/// Flush() and make the file non-writable: close it.
void Close();
/// Read the object for a key. `T` must be the object's type.
/// This will re-read the object for each call, returning a new copy; whether
/// the `TDirectory` is managing an object attached to this key or not.
/// \returns a `unique_ptr` to the object.
/// \throws TDirectoryUnknownKey if no object is stored under this name.
/// \throws TDirectoryTypeMismatch if the object stored under this name is of
/// a type different from `T`.
template <class T>
std::unique_ptr<T> Read(std::string_view name)
{
// FIXME: need separate collections for a TDirectory's key/value and registered objects. Here, we want to emit a
// read and must look through the key/values without attaching an object to the TDirectory.
// FIXME: do not register read object in TDirectory
// FIXME: implement actual read
//FIXME: for now, copy out of whatever the TDirectory manages.
return std::make_unique<T>(*Get<T>(name));
}
/// Write an object that is not lifetime managed by this TFileImplBase.
template<class T>
void Write(std::string_view name, const T &obj) {
WriteMemoryWithType(name, &obj, TClass::GetClass(typeid(T)));
}
/// Write an object that is not lifetime managed by this TFileImplBase.
template<class T>
void Write(std::string_view name, const T *obj) {
WriteMemoryWithType(name, obj, TClass::GetClass(typeid(T)));
}
/// Write an object that is already lifetime managed by this TFileImplBase.
void Write(std::string_view name) {
auto dep = Find(name.to_string());
WriteMemoryWithType(name, dep.GetPointer().get(), dep.GetType());
}
/// Hand over lifetime management of an object to this TFileImplBase, and
/// write it.
template<class T>
void Write(std::string_view name, std::shared_ptr <T> &&obj) {
Add(name, obj);
// FIXME: use an iterator from the insertion to write instead of a second name lookup.
Write(name);
}
// FIXME: for now, copy out of whatever the TDirectory manages.
return std::make_unique<T>(*Get<T>(name));
}
/// Write an object that is not lifetime managed by this TFileImplBase.
template <class T>
void Write(std::string_view name, const T &obj)
{
WriteMemoryWithType(name, &obj, TClass::GetClass(typeid(T)));
}
/// Write an object that is not lifetime managed by this TFileImplBase.
template <class T>
void Write(std::string_view name, const T *obj)
{
WriteMemoryWithType(name, obj, TClass::GetClass(typeid(T)));
}
/// Write an object that is already lifetime managed by this TFileImplBase.
void Write(std::string_view name)
{
auto dep = Find(name.to_string());
WriteMemoryWithType(name, dep.GetPointer().get(), dep.GetType());
}
/// Hand over lifetime management of an object to this TFileImplBase, and
/// write it.
template <class T>
void Write(std::string_view name, std::shared_ptr<T> &&obj)
{
Add(name, obj);
// FIXME: use an iterator from the insertion to write instead of a second name lookup.
Write(name);
}
};
/**
......@@ -186,23 +185,23 @@ public:
class TFilePtr {
private:
std::shared_ptr<TFile> fFile;
std::shared_ptr<TFile> fFile;
/// Constructed by Open etc.
TFilePtr(std::shared_ptr<TFile>&&);
/// Constructed by Open etc.
TFilePtr(std::shared_ptr<TFile> &&);
friend class TFile;
friend class TFile;
public:
/// Dereference the file pointer, giving access to the TFileImplBase object.
TFile* operator ->() { return fFile.get(); }
/// Dereference the file pointer, giving access to the TFileImplBase object.
TFile *operator->() { return fFile.get(); }
/// Dereference the file pointer, giving access to the TFileImplBase object.
/// const overload.
const TFile* operator ->() const { return fFile.get(); }
/// Dereference the file pointer, giving access to the TFileImplBase object.
/// const overload.
const TFile *operator->() const { return fFile.get(); }
/// Check the validity of the file pointer.
operator bool() const { return fFile.get(); }
/// Check the validity of the file pointer.
operator bool() const { return fFile.get(); }
};
} // namespace Experimental
......
......@@ -2,7 +2,8 @@
/// \ingroup Base ROOT7
/// \author Axel Naumann <axel@cern.ch>
/// \date 2015-07-31
/// \warning This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback is welcome!
/// \warning This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback
/// is welcome!
/*************************************************************************
* Copyright (C) 1995-2016, Rene Brun and Fons Rademakers. *
......@@ -19,9 +20,10 @@
#include <mutex>
#include <string>
ROOT::Experimental::TDirectory& ROOT::Experimental::TDirectory::Heap() {
static TDirectory heapDir;
return heapDir;
ROOT::Experimental::TDirectory &ROOT::Experimental::TDirectory::Heap()
{
static TDirectory heapDir;
return heapDir;
}
namespace ROOT {
......@@ -33,186 +35,191 @@ namespace Internal {
*/
class TFileStorageInterface {
public:
virtual void Flush() = 0;
virtual void Close() = 0;
virtual ~TFileStorageInterface() = default;
virtual void WriteMemoryWithType(std::string_view name, const void *address,
TClass *cl) = 0;
virtual void Flush() = 0;
virtual void Close() = 0;
virtual ~TFileStorageInterface() = default;
virtual void WriteMemoryWithType(std::string_view name, const void *address, TClass *cl) = 0;
};
// make_shared<TFile> doesn't work, as TFile() is private. Take detour
// through a friend instead.
class TFileSharedPtrCtor: public ROOT::Experimental::TFile {
public:
TFileSharedPtrCtor(std::unique_ptr<TFileStorageInterface>&& storage):
TFile(std::move(storage)) {}
TFileSharedPtrCtor(std::unique_ptr<TFileStorageInterface> &&storage): TFile(std::move(storage)) {}
};
} // namespace Internal
} // namespace Experimenal
} // namespace Experimental
} // namespace ROOT
namespace {
/// We cannot afford users not closing their files. Yes, we return a unique_ptr -
/// but that might be stored in an object that itself leaks. That would leave
/// the TFile unclosed and data corrupted / not written. Instead, keep a
/// collection of all opened writable TFiles and close them at destruction time,
/// explicitly.
static void AddFilesToClose(std::weak_ptr<ROOT::Experimental::TFile> pFile) {
struct CloseFiles_t {
std::vector<std::weak_ptr<ROOT::Experimental::TFile>> fFiles;
std::mutex fMutex;
~CloseFiles_t() {
for (auto& wFile: fFiles) {
if (auto sFile = wFile.lock()) {
sFile->Flush(); // or Close()? but what if there's still a Write()?
}
static void AddFilesToClose(std::weak_ptr<ROOT::Experimental::TFile> pFile)
{
struct CloseFiles_t {
std::vector<std::weak_ptr<ROOT::Experimental::TFile>> fFiles;
std::mutex fMutex;
~CloseFiles_t()
{
for (auto &wFile: fFiles) {
if (auto sFile = wFile.lock()) {
sFile->Flush(); // or Close()? but what if there's still a Write()?
}
}
}
}
};
static CloseFiles_t closer;
};
static CloseFiles_t closer;
std::lock_guard<std::mutex> lock(closer.fMutex);
closer.fFiles.emplace_back(pFile);
std::lock_guard<std::mutex> lock(closer.fMutex);
closer.fFiles.emplace_back(pFile);
}
/** \class TV6Storage
TFile for a ROOT v6 storage backend.
*/
class TV6Storage: public ROOT::Experimental::Internal::TFileStorageInterface {
::TFile* fOldFile;
::TFile *fOldFile;
public:
TV6Storage(const std::string& name, const std::string& mode):
fOldFile(::TFile::Open(name.c_str(), mode.c_str())) {
}
TV6Storage(const std::string &name, const std::string &mode): fOldFile(::TFile::Open(name.c_str(), mode.c_str())) {}
void Flush() final { fOldFile->Flush(); }
void Flush() final { fOldFile->Flush(); }
void Close() final { fOldFile->Close(); }
void Close() final { fOldFile->Close(); }
~TV6Storage() {
delete fOldFile;
}
~TV6Storage() { delete fOldFile; }
void WriteMemoryWithType(std::string_view name, const void* address, TClass* cl) final {
fOldFile->WriteObjectAny(address, cl, name.to_string().c_str());
}
void WriteMemoryWithType(std::string_view name, const void *address, TClass *cl) final
{
fOldFile->WriteObjectAny(address, cl, name.to_string().c_str());
}
};
}
} // namespace
ROOT::Experimental::TFilePtr::TFilePtr(std::shared_ptr<ROOT::Experimental::TFile>&& file):
fFile(std::move(file))
ROOT::Experimental::TFilePtr::TFilePtr(std::shared_ptr<ROOT::Experimental::TFile> &&file): fFile(std::move(file))
{
AddFilesToClose(fFile);
AddFilesToClose(fFile);
}
namespace {
static std::string GetV6TFileOpts(const char* mode,
const ROOT::Experimental::TFile::Options_t& opts) {
std::string ret(mode);
if (opts.fCachedRead)
ret += " CACHEREAD ";
if (opts.fAsynchronousOpen && opts.fAsyncTimeout > 0)
ret += " TIMEOUT=" + std::to_string(opts.fAsyncTimeout) + " ";
return ret;
static std::string GetV6TFileOpts(const char *mode, const ROOT::Experimental::TFile::Options_t &opts)
{
std::string ret(mode);
if (opts.fCachedRead)
ret += " CACHEREAD ";
if (opts.fAsynchronousOpen && opts.fAsyncTimeout > 0)
ret += " TIMEOUT=" + std::to_string(opts.fAsyncTimeout) + " ";
return ret;
}
static std::mutex& GetCacheDirMutex() {
static std::mutex sMutex;
return sMutex;
static std::mutex &GetCacheDirMutex()
{
static std::mutex sMutex;
return sMutex;
}
static std::unique_ptr<ROOT::Experimental::Internal::TFileStorageInterface>
OpenV6TFile(std::string_view name, const char* mode,
const ROOT::Experimental::TFile::Options_t& opts) {
// Set and re-set the cache dir.
// FIXME: do not modify a static here, pass this to the underlying Open.
struct SetCacheDirRAII_t {
std::string fOldCacheDir;
std::lock_guard<std::mutex> fLock;
SetCacheDirRAII_t(bool need): fLock(GetCacheDirMutex()) {
if (need)
fOldCacheDir = TFile::GetCacheFileDir();
}
~SetCacheDirRAII_t() {
if (!fOldCacheDir.empty())
TFile::SetCacheFileDir(fOldCacheDir.c_str());
}
} setCacheDirRAII(opts.fCachedRead);
auto v6storage = std::make_unique<TV6Storage>(name.to_string(), GetV6TFileOpts(mode, opts));
using namespace ROOT::Experimental::Internal;
return std::unique_ptr<TFileStorageInterface>{std::move(v6storage)};
}
OpenV6TFile(std::string_view name, const char *mode, const ROOT::Experimental::TFile::Options_t &opts)
{
// Set and re-set the cache dir.
// FIXME: do not modify a static here, pass this to the underlying Open.
struct SetCacheDirRAII_t {
std::string fOldCacheDir;
std::lock_guard<std::mutex> fLock;
SetCacheDirRAII_t(bool need): fLock(GetCacheDirMutex())
{
if (need)
fOldCacheDir = TFile::GetCacheFileDir();
}
~SetCacheDirRAII_t()
{
if (!fOldCacheDir.empty())
TFile::SetCacheFileDir(fOldCacheDir.c_str());
}
} setCacheDirRAII(opts.fCachedRead);
auto v6storage = std::make_unique<TV6Storage>(name.to_string(), GetV6TFileOpts(mode, opts));
using namespace ROOT::Experimental::Internal;
return std::unique_ptr<TFileStorageInterface>{std::move(v6storage)};
}
} // namespace
ROOT::Experimental::TFilePtr
ROOT::Experimental::TFile::Open(std::string_view name,
const Options_t& opts /*= Options_t()*/) {
// will become delegation to TFileSystemFile, TWebFile etc.
using namespace Internal;
auto file = std::make_shared<TFileSharedPtrCtor>(OpenV6TFile(name, "READ", opts));
return ROOT::Experimental::TFilePtr(std::move(file));
ROOT::Experimental::TFilePtr ROOT::Experimental::TFile::Open(std::string_view name,
const Options_t &opts /*= Options_t()*/)
{
// will become delegation to TFileSystemFile, TWebFile etc.
using namespace Internal;
auto file = std::make_shared<TFileSharedPtrCtor>(OpenV6TFile(name, "READ", opts));
return ROOT::Experimental::TFilePtr(std::move(file));
}
ROOT::Experimental::TFilePtr
ROOT::Experimental::TFile::Create(std::string_view name,
const Options_t& opts /*= Options_t()*/) {
// will become delegation to TFileSystemFile, TWebFile etc.
using namespace Internal;
auto file = std::make_shared<TFileSharedPtrCtor>(OpenV6TFile(name, "CREATE", opts));
return ROOT::Experimental::TFilePtr(std::move(file));
ROOT::Experimental::TFilePtr ROOT::Experimental::TFile::Create(std::string_view name,
const Options_t &opts /*= Options_t()*/)
{
// will become delegation to TFileSystemFile, TWebFile etc.
using namespace Internal;
auto file = std::make_shared<TFileSharedPtrCtor>(OpenV6TFile(name, "CREATE", opts));
return ROOT::Experimental::TFilePtr(std::move(file));
}
ROOT::Experimental::TFilePtr
ROOT::Experimental::TFile::Recreate(std::string_view name,
const Options_t& opts /*= Options_t()*/) {
// will become delegation to TFileSystemFile, TWebFile etc.
using namespace Internal;
auto file = std::make_shared<TFileSharedPtrCtor>(OpenV6TFile(name, "RECREATE", opts));
return ROOT::Experimental::TFilePtr(std::move(file));
ROOT::Experimental::TFilePtr ROOT::Experimental::TFile::Recreate(std::string_view name,
const Options_t &opts /*= Options_t()*/)
{
// will become delegation to TFileSystemFile, TWebFile etc.
using namespace Internal;
auto file = std::make_shared<TFileSharedPtrCtor>(OpenV6TFile(name, "RECREATE", opts));
return ROOT::Experimental::TFilePtr(std::move(file));
}
ROOT::Experimental::TFilePtr
ROOT::Experimental::TFile::OpenForUpdate(std::string_view name,
const Options_t& opts /*= Options_t()*/) {
// will become delegation to TFileSystemFile, TWebFile etc.
using namespace Internal;
auto file = std::make_shared<TFileSharedPtrCtor>(OpenV6TFile(name, "UPDATE", opts));
return ROOT::Experimental::TFilePtr(std::move(file));
ROOT::Experimental::TFilePtr ROOT::Experimental::TFile::OpenForUpdate(std::string_view name,
const Options_t &opts /*= Options_t()*/)
{
// will become delegation to TFileSystemFile, TWebFile etc.
using namespace Internal;
auto file = std::make_shared<TFileSharedPtrCtor>(OpenV6TFile(name, "UPDATE", opts));
return ROOT::Experimental::TFilePtr(std::move(file));
}
std::string ROOT::Experimental::TFile::SetCacheDir(std::string_view path) {
std::lock_guard<std::mutex> lock(GetCacheDirMutex());
std::string ROOT::Experimental::TFile::SetCacheDir(std::string_view path)
{
std::lock_guard<std::mutex> lock(GetCacheDirMutex());
std::string ret = ::TFile::GetCacheFileDir();
::TFile::SetCacheFileDir(path.to_string().c_str());
return ret;
std::string ret = ::TFile::GetCacheFileDir();
::TFile::SetCacheFileDir(path.to_string().c_str());
return ret;
}
std::string ROOT::Experimental::TFile::GetCacheDir() {
std::lock_guard<std::mutex> lock(GetCacheDirMutex());
return ::TFile::GetCacheFileDir();
std::string ROOT::Experimental::TFile::GetCacheDir()
{
std::lock_guard<std::mutex> lock(GetCacheDirMutex());
return ::TFile::GetCacheFileDir();
}
// Implement outlined, to hide implementation of TFileStorageInterface from
// header.
ROOT::Experimental::TFile::TFile(std::unique_ptr<ROOT::Experimental::Internal::TFileStorageInterface>&& storage):
fStorage(std::move(storage)) {}
ROOT::Experimental::TFile::TFile(std::unique_ptr<ROOT::Experimental::Internal::TFileStorageInterface> &&storage)
: fStorage(std::move(storage))
{}
// Implement outlined, to hide implementation of TFileStorageInterface from
// header.
ROOT::Experimental::TFile::~TFile() = default;
void ROOT::Experimental::TFile::Flush() { fStorage->Flush(); }
void ROOT::Experimental::TFile::Close() { fStorage->Close(); }
void ROOT::Experimental::TFile::WriteMemoryWithType(std::string_view name,
const void *address,
TClass *cl) {
fStorage->WriteMemoryWithType(name, address, cl);
void ROOT::Experimental::TFile::Flush()
{
fStorage->Flush();
}
void ROOT::Experimental::TFile::Close()
{
fStorage->Close();
}
void ROOT::Experimental::TFile::WriteMemoryWithType(std::string_view name, const void *address, TClass *cl)
{
fStorage->WriteMemoryWithType(name, address, cl);
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment