From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-1.3 required=5.0 tests=BAYES_00,INVALID_MSGID autolearn=no autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 103376,28c043d47104f5d9 X-Google-Attributes: gid103376,public From: "Pat Rogers" Subject: Re: Controlled types for resource locking Date: 1999/09/09 Message-ID: #1/1 X-Deja-AN: 522953155 References: <936824686.950.0.nnrp-07.c2de848f@news.demon.co.uk> X-Priority: 3 X-Mimeole: Produced By Microsoft MimeOLE V5.00.2314.1300 X-Complaints-To: newsabuse@supernews.com Organization: Software Arts & Sciences X-MSMail-Priority: Normal Newsgroups: comp.lang.ada Date: 1999-09-09T00:00:00+00:00 List-Id: wrote in message news:iMAB3.157$QV.27052@typhoon-sf.pbi.net... > > I have some code in which I'm protecting a hardware resource using a > > protected type. It's getting quite a mess at the moment with lock/unlocks > > all over the place - especially where exception handlers get involved. I'm > > You can make a controlled type whose Initialize grabs the lock and > whose Finalize releases it, then declare an object of this controlled > type as the first thing in any subprogram (or block) that needs access > to the hardware. Thus you can't execute code inside the subprogram > till the Initialize has been called, and you own the resource. Any way > you leave the subprogram, you are guaranteed the Finalize will release > the resource. Further to Tom's suggestion, let me suggest you make it a limited controlled type and use an access discriminant to identify the object you wish to have automatically locked and unlocked. Here's how I would do it, for example: Here we create an interface for things that can be locked and unlocked: package Lockable is type Thing is abstract tagged limited null record; procedure Lock ( This : in out Thing ) is abstract; procedure Unlock( This : in out Thing ) is abstract; end Lockable; We also create a template to add the automatic locking/unlocking behaviour. Once instantiated, the generic package exports a type that will automatically lock and unlock objects designated by the discriminants of objects of type Managed_Resource. the generic formal parameter says that users can only instantiate this generic with types that are directly or indirectly lockable: with Ada.Finalization; with Lockable; generic type Unmanaged_Resource is new Lockable.Thing with private; package Locking_Manager is type Managed_Resource( Resource : access Unmanaged_Resource ) is tagged limited private; private type Managed_Resource( Resource : access Unmanaged_Resource ) is new Ada.Finalization.Limited_Controlled with null record; procedure Initialize( This : in out Managed_Resource ); procedure Finalize ( This : in out Managed_Resource ); end Locking_Manager; We know that the discriminant designates a lockable thing, so we dispatch to the operations within Initialize and Finalize, which are called when the object is elaborated and finalized (only, since it is a limited type): package body Locking_Manager is procedure Initialize( This : in out Managed_Resource ) is begin Lockable.Lock( Lockable.Thing'Class(This.Resource.all) ); end Initialize; procedure Finalize( This : in out Managed_Resource ) is begin Lockable.Unlock( Lockable.Thing'Class(This.Resource.all) ); end Finalize; end Locking_Manager; Here's an instance of a lockable app type, completely made up. (The package Blocking is available at the free code section of my web site.) with Lockable; with Blocking; package Database is type Homogeneous_View is new Lockable.Thing with private; -- primitive operations on Homogeneous_View objects procedure Lock( This : in out Homogeneous_View ); procedure Unlock( This : in out Homogeneous_View ); private type Homogeneous_View is new Lockable.Thing with record Mutex : Blocking.Mutual_Exclusion; -- components required for whatever this really is end record; end Database; package body Database is -- primitive ops bodies procedure Lock( This : in out Homogeneous_View ) is begin This.Mutex.Acquire; end Lock; procedure Unlock( This : in out Homogeneous_View ) is begin This.Mutex.Release; end Unlock; end Database; Here we instantiate the generic: with Database; with Locking_Manager; package Managed_Views is new Locking_Manager( Unmanaged_Resource => Database.Homogeneous_View ); And here's a demo. We just work with View, confident that Automatic_Lock handles the locking and unlocking for us: with Database; with Managed_Views; procedure Test is View : aliased Database.Homogeneous_View; Automatic_Lock : Managed_Views.Managed_Resource( View'Access ); begin -- operations on View ... end Test; Hope that helps, -- Pat Rogers Training and Consulting in: http://www.classwide.com Deadline Schedulability Analysis progers@classwide.com Software Fault Tolerance (281)648-3165 Real-Time/OO Languages