Skip to content

Conversation

@liampwll
Copy link

This is a copy of Shared_Pointers except Set takes an anonymous function pointer instead of a value directly. This allows for the generic element type to be a limited type.

This is a copy of Shared_Pointers except Set takes an anonymous function
pointer instead of a value directly. This allows for the generic element
type to be a limited type.
@CLAassistant
Copy link

CLAassistant commented Nov 29, 2025

CLA assistant check
All committers have signed the CLA.

@liampwll
Copy link
Author

It might make sense to have Shared_Pointers wrap Limited_Shared_Pointers if GNAT can inline well enough to do so without any performance cost.

@Jicquel
Copy link
Collaborator

Jicquel commented Dec 4, 2025

Hi @liampwll, thanks for your contribution!

The current PR duplicates too much code to remain maintainable. Your suggestion of having Shared_Pointers built on top of Limited_Shared_Pointers would be a great improvement.

Could you also add tests to your PR, especially one that attempts to copy a limited version of the shared element?

As for the inlining performance issue, we can run benchmarks afterwards.

If that may help you, here is the main I used to test your MR:

with GNATCOLL.Refcount; use GNATCOLL.Refcount;
with Ada.Text_IO;       use Ada.Text_IO;

procedure Main is

   type Limited_Integer is limited record
      Value : Integer;
   end record;

   function Create return Limited_Integer is
   begin
      return (Value => 5000);
   end;

   package Integer_Pointers is new
     GNATCOLL.Refcount.Limited_Shared_Pointers
       (Element_Type => Limited_Integer);

   use Integer_Pointers;

   -- Declare shared pointer variables
   Ptr1, Ptr2, Ptr3 : Ref;

begin
   -- Set the shared pointer to contain the access type
   Set (Ptr1, Create'access);
   Put_Line
     ("After creating Ptr1, ref count: "
      & Natural'Image (Get_Refcount (Ptr1)));

   -- Copy the reference - this increments the reference count
   Ptr2 := Ptr1;
   Put_Line
     ("After creating Ptr2, ref count: "
      & Natural'Image (Get_Refcount (Ptr1)));

   -- Create another reference
   Ptr3 := Ptr1;
   Put_Line
     ("After creating Ptr3, ref count: "
      & Natural'Image (Get_Refcount (Ptr1)));

   -- Access and modify the string through different pointers
   Put_Line ("Original content: " & Integer'Image (Get (Ptr1).Value));

   -- Modify through Ptr2
   Get (Ptr2).Value := 2;

   declare
      B : Limited_Integer := Get (Ptr1);
      --  A : Limited_Integer := B; -- Uncommenting this line raises an error
   begin
      null;
   end;
   -- The change is visible through all pointers (they share the same data)
   Put_Line ("Content via Ptr1: " & Integer'Image (Get (Ptr1).Value));
   Put_Line ("Content via Ptr3: " & Integer'Image (Get (Ptr3).Value));

   -- Reset one pointer - decreases reference count
   Ptr1 := Null_Ref;
   Put_Line
     ("After resetting Ptr1, ref count via Ptr2: "
      & Natural'Image (Get_Refcount (Ptr2)));

   -- Reset another pointer
   Ptr2 := Null_Ref;
   Put_Line
     ("After resetting Ptr2, ref count via Ptr3: "
      & Natural'Image (Get_Refcount (Ptr3)));

   -- Modify through the last remaining pointer
   Get (Ptr3).Value := 3;
   Put_Line ("Final content: " & Integer'Image (Get (Ptr3).Value));
end Main;

@mr-tec96
Copy link

Hi, I currently have a Problem also requiring a "Limited Holder" for my solution i used something like:

generic
   type Element_Type (<>) is limited private;
   type Constructor_Type is private;
   with function Construct (C : Constructor_Type) return Element_Type;
package ...
   procedure Set (Ref : in out Ref_Type; C : Constructor_Type)

A litle more flexible version might be something like this:

generic
   type Element_Type (<>) is limited private;
package ...
   type Constructor_Interface is limited interface;
   function Construct (C : Constructor_Interface) return Element_Type is abstract;
   procedure Set (Ref : in out Ref_Type; C : Constructor_Interface'Class)

Both of these aproches offer the additional benefit of initializing the element with some data.
I have so far avoided working with access to subprogramms so if your aproach offers other advanteges im not aware of pleas let me know.
If this PR is accepted I am looking forward to changig away from my current ramshackle implementation to something more standardized.

@liampwll
Copy link
Author

Both of these aproches offer the additional benefit of initializing the element with some data.

I'm not really sure what you mean by this.

The approaches above feel like an extra level of OO that might fit in to the style of a specific project but don't have any universal benefit, so it seems like it would be better for them to be implemented by a given user of GNATCOLL while leaving the underlying implementation as simple as possible.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants