[M3devel] Implementing the "Singleton pattern" in Modula-3

Tony Hosking hosking at cs.purdue.edu
Tue Apr 7 04:07:19 CEST 2009


On 7 Apr 2009, at 11:18, Mika Nystrom wrote:

> Well I think the problem is with this "is known to be an object  
> type"...

But if the opaque type T is T<:REFANY and the only revelation is  
branded and private to a module (not exported by its interfaces) then  
no-one can determine that it is an object type without forging the  
BRAND.

> You may in fact want to override the methods of the singleton, but
> ensure that only one ever gets instantiated.
>
> It's a minor problem, but it does sometimes bother me that it is
> difficult to prevent clients from NEWing pretty much anything they
> like.
>
> By the way, the "Modula-3 Type System" paper also talks about a
> nifty way to do narrowing very quickly (page 10, last paragraph).
> I remember this is occasionally problematic.  (RTType.IsSubtype
> isn't great.)  They speak of keeping an array of supertypes
> for each type, and recording the "depth" (distance from REFANY)
> of every type in, I guess, RT0.TypeDefn.   This seems moderately
> space-efficient (better than a 2D array of all the typecodes),
> and very fast.
>
>     Mika
>
> Tony Hosking writes:
>> I would exploit opaque types and branding.  If T is opaque then you
>> cannot instantiate T except in scopes where T's concrete type has  
>> been
>> revealed or is known to be an object type.  Thus, you could define an
>> interface:
>>
>> GENERIC INTERFACE Singleton(Rep);
>> TYPE T <: REFANY;
>> VAR t: T;
>> END Singleton.
>>
>> GENERIC MODULE Singleton(Rep);
>> REVEAL T = BRANDED REF Rep.T;
>> BEGIN
>>  t := NEW(T);
>> END Singleton.
>>
>> where Rep defines the type T.  You could do similar for object types.
>>
>>
>> On 7 Apr 2009, at 06:31, Mika Nystrom wrote:
>>
>>>
>>> Tony, Jay, you two seem to be most knowledgeable about this.
>>>
>>> Let's say I wanted to implement the "singleton pattern" in
>>> Modula-3.  At present there seems to be no way of doing this.
>>>
>>> What about changing RTAllocator.callback as follows (or adding
>>> another callback):
>>>
>>> VAR callback : PROCEDURE(r : REFANY) : REFANY := NIL;
>>>
>>> (* If non-NIL, the allocator calls "callback(r)" just before  
>>> returning
>>>  a new traced reference "r" and instead returns the result of
>>> callback(r).
>>>  See "RTAllocStats" for an example client.  It is a checked runtime
>>> error
>>>  for the typecode of r to differ from the typecode of the return
>>> value of
>>>  callback(r).  *)
>>>
>>>     Mika
>>>
>>>
>>>




More information about the M3devel mailing list