From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on ip-172-31-74-118.ec2.internal X-Spam-Level: X-Spam-Status: No, score=-1.9 required=3.0 tests=BAYES_00 autolearn=ham autolearn_force=no version=3.4.6 Path: eternal-september.org!reader02.eternal-september.org!aioe.org!RKN7TKnHC01q0gdg6EhkbQ.user.46.165.242.75.POSTED!not-for-mail From: Simon Wright Newsgroups: comp.lang.ada Subject: Re: Custom Storage Pool questions Date: Wed, 15 Sep 2021 17:43:57 +0100 Organization: Aioe.org NNTP Server Message-ID: References: Mime-Version: 1.0 Content-Type: text/plain Injection-Info: gioia.aioe.org; logging-data="26662"; posting-host="RKN7TKnHC01q0gdg6EhkbQ.user.gioia.aioe.org"; mail-complaints-to="abuse@aioe.org"; User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/27.2 (darwin) Cancel-Lock: sha1:NWesgLrxYwRv5Lz7vejus3LXCjk= X-Notice: Filtered by postfilter v. 0.9.2 Xref: reader02.eternal-september.org comp.lang.ada:62747 List-Id: Jere writes: > But after reading the following AdaCore article, my assumption is now > called into question: > https://blog.adacore.com/header-storage-pools > > In particular, the blog there advocates for separately counting for > things like unconstrained array First/Last indices or the Prev/Next > pointers used for Controlled objects. Normally I would have assumed > that the Size_In_Storage_Elements parameter in Allocate would account > for that, but the blog clearly shows that it doesn't Well, I may well have missed the point somewhere, and maybe things have changed since 2015, but as far as I can see, with FSF GCC 11.1.0, the technique described in the blog is completely unnecessary. To save having to recompile the runtime with debug symbols, I wrote a tiny pool which delegates to GNAT's System.Pool_Global.Global_Pool_Object (the default pool), e.g. overriding procedure Allocate (Pool : in out My_Pool.Pool; Storage_Address : out Address; Size_In_Storage_Elements : in Storage_Elements.Storage_Count; Alignment : in Storage_Elements.Storage_Count) is pragma Unreferenced (Pool); begin Global_Pool_Object.Allocate (Address => Storage_Address, Storage_Size => Size_In_Storage_Elements, Alignment => Alignment); end Allocate; and I find with Pool : My_Pool.Pool; type C is new Ada.Finalization.Controlled with null record; type Cs is array (Natural range <>) of C; type Csp is access Cs with Storage_Pool => Pool; procedure Free is new Ada.Unchecked_Deallocation (Cs, Csp); Pcs : Csp; begin Pcs := new Cs (0 .. 5); Free (Pcs); that * the alignment requested is 8 (was 4 for an array of Boolean); * the size requested is 72, which is 24 bytes more than required for the 6 minimal POs; * the value returned by Allocate is 24 bytes more than the address of the array object Pcs (which is the same as that of Pcs(0)); * the value passed to Deallocate is the same as that returned by Allocate. I think it's more than likely (!) that the extra allocation of 24 bytes is made up of 2 pointers at 8 bytes each, used to implement the finalization chain, and two integers at 4 bytes each, holding the array bounds. So I'd say that to create a pool with extra header information, you'd need to allocate space for your header + padding to ensure that the compiler's object is properly aligned + the compiler-requested size, aligned to the max of your header's alignment and the compiler-requested alignment. Mind, I don't quite see how to actually access the header info for a particular allocation ...