www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - cas and pointers

reply Stanislav Blinov <stanislav.blinov gmail.com> writes:
I've been looking into cas recently and I came to wonder why it doesn't 
provide actual support for pointers.

The current declaration of cas looks roughly like this:

bool cas(shared(T)* here, const V1 ifThis, const V2 writeThis) if 
(__traits(compiles,mixin("*here = writeThis")))

which, with transitive const, means that if T, V1 and V2 are, say, X*, 
then this declaration would be equivalent to

bool cas(shared(X*)* here, const(X*) ifThis, const(X*) writeThis) if 
(__traits(compiles,mixin("*here = writeThis")))

and as such, __traits(compiles) here will obviously return false, as you 
cannot assign const pointer to a non-const one. For example, you would 
not be able to compile even examples from Andrei's book.

I wonder if there is some overwhelming reason why this is so, or is it 
just that current implementation lacks specialization for pointers?
Oct 31 2011
parent reply Sean Kelly <sean invisibleduck.org> writes:
writeThis really shouldn't be const, it should be shared.  The problem was t=
hat making writeThis a shared pass by value param implied a synchronized loa=
d for writeThis, which is undesirable for cas. So I left the declaration of c=
as as specified in TDPL and thought I'd figure this out later.=20

Sent from my iPhone

On Oct 31, 2011, at 9:06 AM, Stanislav Blinov <stanislav.blinov gmail.com> w=
rote:

 I've been looking into cas recently and I came to wonder why it doesn't pr=
ovide actual support for pointers.
=20
 The current declaration of cas looks roughly like this:
=20
 bool cas(shared(T)* here, const V1 ifThis, const V2 writeThis) if (__trait=
s(compiles,mixin("*here =3D writeThis")))
=20
 which, with transitive const, means that if T, V1 and V2 are, say, X*, the=
n this declaration would be equivalent to
=20
 bool cas(shared(X*)* here, const(X*) ifThis, const(X*) writeThis) if (__tr=
aits(compiles,mixin("*here =3D writeThis")))
=20
 and as such, __traits(compiles) here will obviously return false, as you c=
annot assign const pointer to a non-const one. For example, you would not be= able to compile even examples from Andrei's book.
=20
 I wonder if there is some overwhelming reason why this is so, or is it jus=
t that current implementation lacks specialization for pointers?
Oct 31 2011
parent reply Michel Fortin <michel.fortin michelf.com> writes:
On 2011-10-31 17:07:31 +0000, Sean Kelly <sean invisibleduck.org> said:

 writeThis really shouldn't be const, it should be shared.  The problem was t
 hat making writeThis a shared pass by value param implied a synchronized loa
 d for writeThis, which is undesirable for cas. So I left the declaration of c
 as as specified in TDPL and thought I'd figure this out later.
Perhaps it should be Unqual!(shared(V2)). That way if V2 is a pointer it'll be tail-shared. That won't work for class references though. For that you'd need my "const(Object)ref" patch rusting in DMD's pull requests. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Oct 31 2011
next sibling parent "Martin Nowak" <dawg dawgfoto.de> writes:
On Mon, 31 Oct 2011 19:13:57 +0100, Michel Fortin  
<michel.fortin michelf.com> wrote:

 On 2011-10-31 17:07:31 +0000, Sean Kelly <sean invisibleduck.org> said:

 writeThis really shouldn't be const, it should be shared.  The problem  
 was t
 hat making writeThis a shared pass by value param implied a  
 synchronized loa
 d for writeThis, which is undesirable for cas. So I left the  
 declaration of c
 as as specified in TDPL and thought I'd figure this out later.
Perhaps it should be Unqual!(shared(V2)). That way if V2 is a pointer it'll be tail-shared. That won't work for class references though. For that you'd need my "const(Object)ref" patch rusting in DMD's pull requests.
It's a pitty that cas doesn't work with classes.
Oct 31 2011
prev sibling next sibling parent Stanislav Blinov <stanislav.blinov gmail.com> writes:
On 10/31/2011 10:13 PM, Michel Fortin wrote:
 On 2011-10-31 17:07:31 +0000, Sean Kelly <sean invisibleduck.org> said:

 writeThis really shouldn't be const, it should be shared. The problem
 was t
 hat making writeThis a shared pass by value param implied a
 synchronized loa
 d for writeThis, which is undesirable for cas. So I left the
 declaration of c
 as as specified in TDPL and thought I'd figure this out later.
Perhaps it should be Unqual!(shared(V2)). That way if V2 is a pointer it'll be tail-shared. That won't work for class references though. For that you'd need my "const(Object)ref" patch rusting in DMD's pull requests.
Something tells me that currently this is unachievable without casting away shared on the caller side, which is kind of awkward. I mean, we can either have a signature that demands writeThis be shared (which it should be), but then we've got a synchronized parameter load, or a signature in which writeThis is not shared, which is (a) not safe and (b) would demand callers to cast away shared and implementation to cast it in again for an assignment...
Oct 31 2011
prev sibling parent "Martin Nowak" <dawg dawgfoto.de> writes:
On Tue, 01 Nov 2011 02:42:16 +0100, Martin Nowak <dawg dawgfoto.de> wrote:

 On Mon, 31 Oct 2011 19:13:57 +0100, Michel Fortin  
 <michel.fortin michelf.com> wrote:

 On 2011-10-31 17:07:31 +0000, Sean Kelly <sean invisibleduck.org> said:

 writeThis really shouldn't be const, it should be shared.  The problem  
 was t
 hat making writeThis a shared pass by value param implied a  
 synchronized loa
 d for writeThis, which is undesirable for cas. So I left the  
 declaration of c
 as as specified in TDPL and thought I'd figure this out later.
Perhaps it should be Unqual!(shared(V2)). That way if V2 is a pointer it'll be tail-shared. That won't work for class references though. For that you'd need my "const(Object)ref" patch rusting in DMD's pull requests.
It's a pitty that cas doesn't work with classes.
Does anybody have a good idiom for lazy initialization of shared classes then? I used to use this one, which doesn't compile any longer. ---------- class Library { void init() {} } private shared Library _library; shared(Library) library() { if (_library is null) { auto instance = new shared(Library)(); synchronized(instance) { if (cas(&_library, cast(Library)null, instance) instance.init(); } } return _library; }
Nov 02 2011