Static constructors?

Steven Schveighoffer schveiguy at yahoo.com
Fri Jul 23 05:14:31 PDT 2010


On Fri, 23 Jul 2010 05:56:18 -0400, Dave <ddionisio at renegadeware.com>  
wrote:

> On 7/22/2010 7:40 AM, Steven Schveighoffer wrote:
>> On Wed, 21 Jul 2010 22:27:10 -0400, awishformore
>> <awishformore at nospam.plz> wrote:
>>
>>> On 22/07/2010 03:36, Sean Kelly wrote:
>>>> Make the ctors "shared static this()" -- those are only constructed
>>>> once when the process starts up. The non-shared static ctors are
>>>> thread-local.
>>>
>>> That concept is really weird, though. So this applies to anything
>>> static, not just variables?
>>
>> The puzzle is, let's say you have thread local static variables and
>> shared static variables. Which should be initialized when?
>>
>> The end result we came to is that there should be a way for thread-local
>> variables to be initialized on thread creation, and shared variables to
>> be initialized on program instantiation.
>>
>> So we need a syntax for this. Various things were suggested, and the
>> current behavior was chosen for its consistency with current  
>> terminology:
>>
>> shared int x;
>> shared static this() { x = 5; }
>>
>> or:
>>
>> shared
>> {
>> int x;
>> static this() { x = 5; }
>> }
>>
>> int x2;
>> static this() { x2 = 5; }
>>
>> It looks pretty good to me. You just have to start thinking that
>> thread-local is the norm :)
>>
>> -Steve
>
> While we're on the topic, I've been using dcollections lib for some time  
> now and came across a problem when implementing shared classes, this  
> being an example:
>
> import dcollections.ArrayList;
>
> shared:
>
> class Resource {
> }
>
> synchronized class ResourceManager {
>      void add(Resource res) {
>          bool added;
>          resources.add(res, added);
>      }
>
>      void remove(Resource res) {
>          foreach(ref doRemove, v; &resources.purge) {
>              doRemove = v is res;
>          }
>      }
>
> private:
>      ArrayList!(Resource) resources;
> }
>
> I'm getting the following compile errors:
>
> threadTest.d|13|Error: function  
> dcollections.ArrayList.ArrayList!(shared(Resource)).ArrayList.add  
> (shared(Resource) v, out bool wasAdded) is not callable using argument  
> types (shared(Resource),bool) shared|
> threadTest.d|13|Error: cannot implicitly convert expression (res) of  
> type shared(Resource) to shared(Resource)[]|
> threadTest.d|13|Error: cast(uint)added is not an lvalue|
> threadTest.d|17|Error: function  
> dcollections.ArrayList.ArrayList!(shared(Resource)).ArrayList.purge  
> (scope int delegate(ref bool doPurge, ref shared(Resource) v) dg) is not  
> callable using argument types (int delegate(ref bool doPurge, ref  
> shared(Resource) v)) shared|
> ||=== Build finished: 4 errors, 0 warnings ===|
>
> I'm not quite sure I understand the errors. Is there something I'm  
> missing?

Yes, ArrayList is not meant to be a shared class.  There are no shared  
methods on it.  The clue is here:

dcollections.ArrayList.ArrayList!(shared(Resource)).ArrayList.add
(shared(Resource) v, out bool wasAdded) is not callable using argument
types (shared(Resource),bool) >>>>>shared<<<<<

Emphasis added by me.

The problem here is that the compiler says everything must be shared  
transitively.  So even though you are locking the ResourceManager object,  
you have to treat its 'resources' member as if something outside the  
ResourceManager object also has a reference to it.

I'm not exactly sure how to solve this, without duplicating all methods  
and marking them shared.  You can try casting, it should be safe in this  
context since the array list is private.

Sean, Walter, Andrei?  What is the correct method to say "don't mark this  
member as shared because it's always protected by a lock"?  Or if that's  
impossible, what's the right way to solve this kind of problem?

Also, resources.add(res) should work I think (you don't need the added  
part).  The documentation is severely out of date, I apologize for that.

-Steve


More information about the Digitalmars-d-learn mailing list