fix bugs in optional implementation

This commit is contained in:
Daniel Larimer 2013-07-05 19:48:59 -04:00
parent 58d950b56f
commit 7e61059806
3 changed files with 94 additions and 87 deletions

View file

@ -160,13 +160,13 @@ namespace fc {
/** /**
* Class which creates a temporary directory inside an existing temporary directory. * Class which creates a temporary directory inside an existing temporary directory.
*/ */
class temp_directory : public temp_file_base class temp_directory : public temp_file_base
{ {
public: public:
temp_directory(temp_directory&& other); temp_directory(temp_directory&& other);
temp_directory& operator=(temp_directory&& other); temp_directory& operator=(temp_directory&& other);
temp_directory(const fc::path& tempFolder = fc::temp_directory_path()); temp_directory(const fc::path& tempFolder = fc::temp_directory_path());
}; };
} }

View file

@ -2,6 +2,8 @@
#include <fc/utility.hpp> #include <fc/utility.hpp>
#include <assert.h> #include <assert.h>
#include <stdio.h>
namespace fc { namespace fc {
#ifdef _MSC_VER #ifdef _MSC_VER
# pragma warning(push) # pragma warning(push)
@ -45,17 +47,18 @@ namespace fc {
template<typename U> template<typename U>
optional( U&& u ) optional( U&& u )
:_valid(false) :_valid(true)
{ {
new (ptr()) T( fc::forward<U>(u) ); new ((char*)ptr()) T( fc::forward<U>(u) );
_valid = true;
} }
template<typename U> template<typename U>
optional& operator=( U&& u ) optional& operator=( U&& u )
{ {
reset(); reset();
fprintf( stderr, "optional==(U&&)...\n" );
new (ptr()) T( fc::forward<U>(u) ); new (ptr()) T( fc::forward<U>(u) );
_valid = true;
return *this; return *this;
} }
@ -77,8 +80,10 @@ namespace fc {
{ {
if (this != &o) if (this != &o)
{ {
if( _valid && o._valid ) { if( _valid && o._valid )
{
ref() = fc::move(*o); ref() = fc::move(*o);
o.reset();
} else if ( !_valid && o._valid ) { } else if ( !_valid && o._valid ) {
*this = fc::move(*o); *this = fc::move(*o);
} else if (_valid) { } else if (_valid) {
@ -110,8 +115,10 @@ namespace fc {
{ {
if( _valid ) if( _valid )
{ {
fprintf( stderr, "optiona::reset %p\n", this );
ref().~T(); // cal destructor ref().~T(); // cal destructor
} }
_valid = false;
} }
T& ref() { return *ptr(); } T& ref() { return *ptr(); }
const T& ref()const { return *ptr(); } const T& ref()const { return *ptr(); }

View file

@ -218,84 +218,84 @@ namespace fc {
return ret; return ret;
} }
temp_file::temp_file(const fc::path& p, bool create) temp_file::temp_file(const fc::path& p, bool create)
: temp_file_base(p / fc::unique_path()) : temp_file_base(p / fc::unique_path())
{ {
if (fc::exists(*_path)) if (fc::exists(*_path))
{ {
FC_THROW( "Name collision: ${path}", ("path", _path->string()) ); FC_THROW( "Name collision: ${path}", ("path", _path->string()) );
} }
if (create) if (create)
{ {
fc::ofstream ofs(*_path, fc::ofstream::out | fc::ofstream::binary); fc::ofstream ofs(*_path, fc::ofstream::out | fc::ofstream::binary);
ofs.close(); ofs.close();
} }
}
temp_file::temp_file(temp_file&& other)
: temp_file_base(std::move(other._path))
{
}
temp_file& temp_file::operator=(temp_file&& other)
{
if (this != &other)
{
remove();
_path = std::move(other._path);
}
return *this;
} }
temp_directory::temp_directory(const fc::path& p) temp_file::temp_file(temp_file&& other)
: temp_file_base(p / fc::unique_path()) : temp_file_base(std::move(other._path))
{ {
if (fc::exists(*_path)) }
{
FC_THROW( "Name collision: ${path}", ("path", _path->string()) ); temp_file& temp_file::operator=(temp_file&& other)
} {
fc::create_directories(*_path); if (this != &other)
} {
remove();
temp_directory::temp_directory(temp_directory&& other) _path = std::move(other._path);
: temp_file_base(std::move(other._path)) }
{ return *this;
} }
temp_directory& temp_directory::operator=(temp_directory&& other) temp_directory::temp_directory(const fc::path& p)
{ : temp_file_base(p / fc::unique_path())
if (this != &other) {
{ if (fc::exists(*_path))
remove(); {
_path = std::move(other._path); FC_THROW( "Name collision: ${path}", ("path", _path->string()) );
} }
return *this; fc::create_directories(*_path);
} }
const fc::path& temp_file_base::path() const temp_directory::temp_directory(temp_directory&& other)
{ : temp_file_base(std::move(other._path))
if (!_path) {
{ }
FC_THROW( "Temporary directory has been released." );
} temp_directory& temp_directory::operator=(temp_directory&& other)
return *_path; {
} if (this != &other)
{
void temp_file_base::remove() remove();
{ _path = std::move(other._path);
if (_path) }
{ return *this;
try }
{
fc::remove_all(*_path); const fc::path& temp_file_base::path() const
} {
catch (...) if (!_path)
{ {
// eat errors on cleanup FC_THROW( "Temporary directory has been released." );
} }
release(); return *_path;
} }
}
void temp_file_base::remove()
{
if (_path)
{
try
{
fc::remove_all(*_path);
}
catch (...)
{
// eat errors on cleanup
}
release();
}
}
void temp_file_base::release() void temp_file_base::release()
{ {