Re: why can't I call const methods on shared objects?

2014-05-12 Thread Vlad Levenfeld via Digitalmars-d-learn

@FreeSlave & John Colvin

Yes, I see your point. I could still get tearing on a read. So, 
in the case of methods that I believe are safe (e.g. 1-line 
@property getters) I'll just write a shared variadic function 
template that uses (cast()this).foo(args) to forward to the 
non-shared method... and in less-safe cases, I can just add some 
synchronization code to the shared version.
Or maybe its safer to do it the other way around, i.e. 
(cast(shared)this) and forward from non-shared to shared? There's 
not yet any established best practices for this, are there?


Re: why can't I call const methods on shared objects?

2014-05-11 Thread monarch_dodra via Digitalmars-d-learn

On Friday, 9 May 2014 at 21:58:41 UTC, Steven Schveighoffer wrote:
On Fri, 09 May 2014 17:45:37 -0400, Vlad Levenfeld 
 wrote:


Is there any way to declare a method as "safe regardless of 
shared/mutability/etc" (or some other way to avoid 
cast(Type)object.property every time I want to check a 
property which won't affect any state)?


Not really for shared. For everything else, there's const for 
value properties, and inout for reference properties.


Shared is quite different, because the method has to be 
cognizant of race conditions. It has to be implemented 
differently.


Casting away shared is somewhat dangerous, but OK if you 
logically know there is no race condition.


-Steve


You could just declare the function as "immutable".

But then, it'll only work on immutable types.

But then again, that would be the only way to actually statically 
and safely guarantee there are no race conditions.


Re: why can't I call const methods on shared objects?

2014-05-11 Thread John Colvin via Digitalmars-d-learn

On Friday, 9 May 2014 at 21:37:37 UTC, Vlad Levenfeld wrote:
Error: non-shared const method is not callable using a shared 
mutable object


Why not? If the method is const, it can't modify the object 
anyway.


Because thread-safety isn't only a problem when writing to 
memory, reads must also be carefully dealt with.


Re: why can't I call const methods on shared objects?

2014-05-11 Thread FreeSlave via Digitalmars-d-learn

On Sunday, 11 May 2014 at 07:31:10 UTC, FreeSlave wrote:

On Friday, 9 May 2014 at 21:42:14 UTC, Vlad Levenfeld wrote:

Is this still the case if the method is const or pure?


Const methods still require synchronization, because other 
threads may change some data, needed by const method while 
method is executed, and then you may get wrong results.


Consider:

class Point
{
public:
float x;
float y;


}


I send before I end(

class Point
{
public:
float x;
float y;

Tuple!(float, float) getLengthAndAngle() const
{
float l = sqrt(x*x+y*y);
//other thread change x or y
float a = atan2(x, y);
return tuple(l, a);
}
}



Re: why can't I call const methods on shared objects?

2014-05-11 Thread FreeSlave via Digitalmars-d-learn

On Friday, 9 May 2014 at 21:42:14 UTC, Vlad Levenfeld wrote:

Is this still the case if the method is const or pure?


Const methods still require synchronization, because other 
threads may change some data, needed by const method while method 
is executed, and then you may get wrong results.


Consider:

class Point
{
public:
float x;
float y;


}


Re: why can't I call const methods on shared objects?

2014-05-09 Thread Vlad Levenfeld via Digitalmars-d-learn
aaand on further experimentation it turns out I don't need a 
template at all, I can just overload it... strange, I seem to 
remember not being able to do that before.


Re: why can't I call const methods on shared objects?

2014-05-09 Thread Vlad Levenfeld via Digitalmars-d-learn
PS After reading your post I experimented with overloading 
shared/unshared methods in my code and came up with this solution:


shared Id!Service id ()() const if (is (typeof(this) == shared)) {
  return (cast(Service)this).id;
}
Id!Service id () const {
  return service_id;
}

I like this better than casting at the callsite (though it would 
be nice to roll those two into one method using a static if 
somehow, but I can't think of any way to do this).


Re: why can't I call const methods on shared objects?

2014-05-09 Thread Vlad Levenfeld via Digitalmars-d-learn
Let me see if I understand this right... let's say I have some 
(unshared) class that launches threads to do its real work in.


class Foo {
  this () {thread = spawn (&work);}
  shared void work () {...};
  void send_message (T) (T msg) {thread.send (msg);}
  Tid thread;
}

It has an unshared method to pass messages to the worker thread, 
and everything is copacetic, but what is the best practice for 
when I want another thread to interact with one of these 
instances?


class Bar {
  this () {thread = spawn (&pass);}
  shared void pass () {
receive (
   (shared Foo F) {this.F = F;}  // (1)
   (T msg) {(cast(Foo)F).send_message (msg);},   // (2)
);
  void send_message (T) (T msg) {thread.send (msg);}
  Tid thread;
  Foo F;
}

void main () {
  auto F = new Foo;
  auto B = new Bar;
  B.send_message (cast(shared)F);// (3)
  // sleep
}

When I interact with F from at (1), this.F is automatically 
shared (because Bar is shared) so this compiles. Here, this.F 
refers to the same F I would refer to if I accessed this.F from 
the main method, it just gets automatically shared whenever Bar 
is shared. So when I spawn a worker thread, the worker thread 
sees a shared Bar (and shared F), while the main thread sees a 
Bar that it owns, but they are both looking at the same Bar (just 
with different access rules, like a const and non-const reference 
to the same object).
At (2), I have to cast F to unshared in order to send it a 
message. But this is ok, because I am only sending messages, and 
am not risking a race condition. Basically I am announcing "I 
know that multiple threads can see this, but I am taking 
ownership of it and taking responsiblity for preventing races."
And when I cast to shared at (3), I am announcing "I am 
explicitly recognizing that multiple threads may now access this, 
and that there is a potential for races."


Is this the right way to handle this situation?

And on a more general note, the shared keyword, as I understand 
it, is intended to be a sort of compiler-reinforced tag that I 
can use to prevent races the same way const helps prevent 
unintended side-effects, and  to aid my reasoning when I do need 
to debug a race?


Re: why can't I call const methods on shared objects?

2014-05-09 Thread Steven Schveighoffer via Digitalmars-d-learn
On Fri, 09 May 2014 17:45:37 -0400, Vlad Levenfeld   
wrote:


Is there any way to declare a method as "safe regardless of  
shared/mutability/etc" (or some other way to avoid  
cast(Type)object.property every time I want to check a property which  
won't affect any state)?


Not really for shared. For everything else, there's const for value  
properties, and inout for reference properties.


Shared is quite different, because the method has to be cognizant of race  
conditions. It has to be implemented differently.


Casting away shared is somewhat dangerous, but OK if you logically know  
there is no race condition.


-Steve


Re: why can't I call const methods on shared objects?

2014-05-09 Thread Vlad Levenfeld via Digitalmars-d-learn
I mean I thought that's what "pure" was for but the compiler 
complains all the same.


Re: why can't I call const methods on shared objects?

2014-05-09 Thread Vlad Levenfeld via Digitalmars-d-learn
Is there any way to declare a method as "safe regardless of 
shared/mutability/etc" (or some other way to avoid 
cast(Type)object.property every time I want to check a property 
which won't affect any state)?


Re: why can't I call const methods on shared objects?

2014-05-09 Thread Vlad Levenfeld via Digitalmars-d-learn

Is this still the case if the method is const or pure?


Re: why can't I call const methods on shared objects?

2014-05-09 Thread Steven Schveighoffer via Digitalmars-d-learn
On Fri, 09 May 2014 17:37:35 -0400, Vlad Levenfeld   
wrote:


Error: non-shared const method is not callable using a shared mutable  
object


Why not? If the method is const, it can't modify the object anyway.


Non-shared methods cannot be called on shared objects. Otherwise, you  
could have unintended race conditions.


-Steve


why can't I call const methods on shared objects?

2014-05-09 Thread Vlad Levenfeld via Digitalmars-d-learn
Error: non-shared const method is not callable using a shared 
mutable object


Why not? If the method is const, it can't modify the object 
anyway.