ASPN ActiveState Programmer Network
ActiveState
/ Home / Perl / PHP / Python / Tcl / XSLT /
/ Safari / My ASPN /
Cookbooks | Documentation | Mailing Lists | Modules | News Feeds | Products | User Groups


Recent Messages
List Archives
About the List
List Leaders
Subscription Options

View Subscriptions
Help

View by Topic
ActiveState
.NET Framework
Open Source
Perl
PHP
Python
Tcl
Web Services
XML & XSLT

View by Category
Database
General
SOAP
System Administration
Tools
User Interfaces
Web Programming
XML Programming


MyASPN >> Mail Archive >> boost
boost
RE: [boost] Re: Re: Mini-review request: aligned_storage.hpp
by Anthony Williams other posts by this author
Aug 9 2002 11:12AM messages near this date
Re: [boost] Re: Re: Re: Threads & Exceptions | Re: [boost] Re: Re: Mini-review request: aligned_storage.hpp
From: Itay Maman [mailto:itay_maman@[...].com]
Sent: 09 August 2002 12:31
>  Anthony Williams wrote in a message:
>  >
>  >I've just had a thought about how to implement the strong 
>  guarantee for
>  variant, at the expense of larger space requirements --- have 
>  *two* copies
>  of >the internals, with a flag to indicate which is valid. Then, when
>  swapping or assigning, copy construct the value from the 
>  other variant into
>  the unused >space, and destruct the original and switch the flag when
>  everything is done.
>  
>  I don't think it is possible - in the general case - to 
>  create two identical
>  instances of a class.

Sorry, that's not what I meant. The variant would have _storage_ for two
instances, but only contain one at a time. When swapping the variants, you
can copy-construct the other variant into the unused space in this variant,
then copy-construct this variant into the unused space in the other one. If
everything has succeeded, destruct the originals, and change the flags. If
anything failed, destruct the new copies (if any) and leave the flags alone.

Simple example, with a known type (untested):

class X{};

class Y
{
	char buf1[sizeof(X)]; // ignoring alignment
	char buf2[sizeof(X)];
	bool useBuf1;
	
	X& getVal()
	{
		if(useBuf1)
		{
			return *reinterpret_cast<X*> (buf1);
		}
		else
		{
			return *reinterpret_cast<X*> (buf2);
		}
	}
public:
	Y(const X& val):useBuf1(true)
	{
		new (buf1) X(val);
	}

	~Y()
	{
		getVal().~X();
	}

	void swap(Y& other)
	{
		// copy the other into this one
		if(useBuf1)
		{
			new (buf2) X(other.getVal());
		}
		else
		{
			new (buf1) X(other.getVal());
		}

		// now copy this into the other
		try
		{
			if(other.useBuf1)
			{	
				new (other.buf2) X(getVal());
			}
			else
			{
				new (other.buf1) X(getVal());
			}
		}
		catch(...)
		{
			// destroy already-created copy
			useBuf1=!useBuf1;
			getVal().~X();
			useBuf1=!useBuf1;
			throw;
		}

		// OK, both copies succeeded, so destroy originals
		// and change flags
		getVal().~X();
		useBuf1=!useBuf1;
		other.getVal().~X();
		other.useBuf1=!other.useBuf1;
	}

	Y& operator=(const Y& other)
	{
		// create a copy
		if(useBuf1)
		{
			new (buf2) (other.getVal());
		}	
		else
		{
			new (buf1) X(other.getVal());
		}

		// if that succeeded, destroy our original, and flip flag.
		getVal().~X();
		useBuf1=!useBuf1;		

		return *this;
	}
};


Obviously, you need to account for alignment, and with variant it is a bit
more complex in the implementation due to the multiple types, but the idea
is the same.

Also, if you want assignment to actually perform assignment on the
underlying type, rather than just transfer the value into the variant, then
things are more complicated.

Anthony
Attachments:
unknown1

Thread:
Anthony Williams
Peter Dimov
Douglas Gregor

Privacy Policy | Email Opt-out | Feedback | Syndication
© ActiveState Software Inc. All rights reserved