valid uses of shared

Artur Skawina art.08.09 at gmail.com
Mon Jun 11 04:51:37 PDT 2012


On 06/11/12 12:26, Steven Schveighoffer wrote:
> On Sat, 09 Jun 2012 08:31:01 -0400, Mike Wey <mike-wey at example.com> wrote:
> 
>> On 06/09/2012 04:01 AM, mta`chrono wrote:
>>> Would this be legal?
>>>
>>> class A
>>> {
>>>       private static shared int counter; // shared across all instances
>>>
>>>       this()
>>>       {
>>>            auto i = ++counter;
>>>            pragma(msg, typeof(i)); // prints int
>>>       }
>>> }
>>>
>>
>> Would it also be legal if the variable wasn't static?
> 
> No.

Why? What if this class would like to launch a few threads to do some work,
export the address of the counter and have them report back by updating it?

Unlike the shared-on-stack case, this wouldn't even be unsafe (the memory
won't be freed until all threads stop using it.) The alternative is to have
to split the class into two, more heap allocations etc.


>> int opApply(int delegate(ref Pixels) dg)
>> {
>>      shared(int) progress;
>>
>>      foreach ( row; taskPool.parallel(iota(extent.y, extent.y + extent.height)) )
>>      {
>>          int result = dg(Pixels(image, extent.x, row, extent.width, 1));
>>
>>          if ( result )
>>               return result;
>>
>>          if ( image.monitor !is null )
>>          {
>>              atomicOp!"+="(progress, 1);
>>              image.monitor()("ImageView/" ~ image.filename, progress, extent.height);
>>          }
>>      }
>>      return 0;
>> }
> 
> AFAIK, if you removed shared from progress, it would work.  I don't think std.parallel is as strict as std.concurrency (and for pretty good reason).
> 
> I think a better way to mark progress is to make it an atomic integer type (like Artur has developed).

Yes. The problem with that however is that I never managed to make this
do the right thing:

   Atomic!int a; // somewhere in a shared struct/class.
   ...
   int x = s.a;  // OK, access via getter.
   auto y = s.a; // Oops, we just copied the whole struct.
   void f(T)(T arg);
   f(s.a);       // Ditto.

Which may happen to work for properly aligned small structs because
accessing those are atomic anyway, but is wrong.

artur


More information about the Digitalmars-d mailing list