comp.lang.ada
 help / color / mirror / Atom feed
From: "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de>
Subject: Re: Protected Adjust?
Date: Fri, 17 Apr 2009 10:40:42 +0200
Date: 2009-04-17T10:40:43+02:00	[thread overview]
Message-ID: <egdju2dfwpir$.4w6msv3ok42p$.dlg@40tude.net> (raw)
In-Reply-To: tzWFl.14725$hc1.6142@flpi150.ffdc.sbc.com

On Fri, 17 Apr 2009 07:52:57 GMT, Dimonax wrote:

> How does one encapsulate a Controlled type inside a Protected type such 
> that Initialize, Finalize, and Ajust can be done concurrently?

Hmm, you cannot copy protected objects, they are limited.

> Basically I'm locking a Variable into a Cache, and I don't want that 
> variable being copied in and out of the Cache. i.e. Each Task has to be 
> able to operate on the variable in-place.

OK. So the model is that a variable is processed in-place while other
participants are blocked?

A full list of alternatives might look like:

1. Safe copying in/out and dealing concurrently with a copy (non-blocking)
2. Dealing with the object from a protected action (non-blocking)
3. Locking, dealing with the object outside protected action, unlocking
(blocking)

(all alternatives are exposed to various problems, so the choice really
depends on what you are doing)

> I'm using the low level mlock()/munlock() system calls to create the 
> cache.(Locks the memory to RAM and prevents paging/swapping).

I cannot tell how this is related to protected objects.

> So far, I'm thinking this...
> 
> Pragma Profile(Ravenscar);
> with Ada.Finalization;  --Yeah, this works even with Ravenscar profile. --
> package mutators is
> 
> 	type Item_Type is tagged null record;
> 
> 	type Mutable is new Ada.Finalization.Controlled with private;
> 
> private
> 
> 	type Item_Pointer is access Item_Type;
> 
> 	type Mutable is new Ada.Finalization.Controlled with record
> 		Mutable_Item : Item_Pointer;
> 	end record;
> 
> 	-- Catchy type name eh? ;-> --
> 	Protected Type Mutual_Excluder is
> 		-- This procedure is called by Initialize --
> 		procedure Create(Item : in Item_Type); 
> 		
> 		-- This procedure is called by Adjust. --
> 		procedure Update(Item : in out Item_Pointer);
> 
> 		-- This procedure is called by Finalize --
> 		procedure Destroy(Item : in out Item_Pointer);
> 
> 	private
> 
> 		Item_Holder : Item_Type;
> 		Item_Location : Item_Pointer := Item_Holder'Access;
> 
> 	end Mutual_Excluder;
> 
> 	procedure Initialize(Mutable_Object : in out Mutable);
> 	procedure Adjust(Mutable_Object : in out Mutable);
> 	procedure Finalize(Mutable_Object : in out Mutable);
> 
> end mutators;

This looks like 2.

> Should I have the seperate Item_Type and handle that seperately? Or 
> should I just pass the entire Mutable Object in and out of the protected 
> procedures?

Tagged types are by-reference ones. That means you can safely pass Mutable
or Mutable'Class to a procedure, that would not copy it.

> The goal of this excercise is to be able to use the Adjust procedure from 
> different tasks exclusively.
>
> Tips, advice?

The problem with your approach is that Adjust is not an assignment, it is
only a part of. So, whatever you put into Adjust in order to interlock it,
that will be executed after a bitwise copy of a representation of Mutable
has been *concurrently* made.

There are many solutions. If you are aiming at 2 or 3, you could add one
more level of indirection. E.g. smart pointers:

   type Mutable is private; -- Pointer to an implementation
private
   type Mutable_Implementation is new Ada.Finalization.Controlled with ...;

   type Mutable is new Ada.Finalization.Controlled with record
       Ptr : access Mutable_Implementation'Class;
   end record;
   overriding procedure Adjust (Object : in out Mutable);
   ...

package body

   protected Mutex is
      procedure Do_Adjust (Ref : in out Mutable'Class);
   end Mutex;

   procedure Adjust (Object : in out Mutable) is
   begin
      Mutex.Do_Adjust (Object);
   end Adjust;
   
   protected body Mutex is
      procedure Do_Adjust (Ref : in out Mutable'Class) is
      begin  -- Deep copy semantics
         if Ref.Ptr /= null then
            Ref.Ptr := new Mutable_Implementation'Class'(Ref.Ptr.all);
         end if;
      end Do_Adjust;
   end Mutex;

The drawback of this solution, which is 2, is that potentially lengthy
operations like allocation of new Mutable_Implementation in the heap and
then copying it, are performed on the context of a protected action. If
that is too long, you should consider 3.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



  reply	other threads:[~2009-04-17  8:40 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-04-17  7:52 Protected Adjust? Dimonax
2009-04-17  8:40 ` Dmitry A. Kazakov [this message]
2009-04-17 18:21 ` sjw
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox