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.9 required=5.0 tests=BAYES_00 autolearn=ham autolearn_force=no version=3.4.4 X-Google-Thread: 103376,ed3a51e96a1c868b X-Google-NewGroupId: yes X-Google-Attributes: gida07f3367d7,domainid0,public,usenet X-Google-Language: ENGLISH,ASCII-7-bit Path: g2news2.google.com!news3.google.com!feeder.news-service.com!feeder.news-service.com!85.214.198.2.MISMATCH!eternal-september.org!feeder.eternal-september.org!.POSTED!not-for-mail From: Ludovic Brenta Newsgroups: comp.lang.ada Subject: Re: Using local storage pools... Date: Wed, 23 Feb 2011 21:51:20 +0100 Organization: A noiseless patient Spider Message-ID: <87ipwawk3b.fsf@ludovic-brenta.org> References: <7elam6trrv39c3p9iop4fiduqa1jrat4r4@4ax.com> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Injection-Info: mx02.eternal-september.org; posting-host="/gVKoTO8TR4XDYkiHTxC+A"; logging-data="8880"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1+hbx3rMscBo6zEsvwuOjE8" User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.2 (gnu/linux) Cancel-Lock: sha1:0t4shsZ+duqR54xOZVRN67gC2EA= sha1:D8IqjoKD805/gZsvOHA+/moo95c= Xref: g2news2.google.com comp.lang.ada:18535 Date: 2011-02-23T21:51:20+01:00 List-Id: Brian Drummond writes: > I am trying to learn a little about storage pools, with a view to > (hopefully) using local pools to improve the Binary_Trees benchmark in > the same way as some of the faster C benchmarks. > > Arguably they cheat : they do not explicitly free each tree node (the > "free" call has been deleted!) but free the entire pool at the end of > the loop. But if that's valid, Ada should be able to do the same. > > http://gcc.gnu.org/onlinedocs/gcc-4.1.2/gnat_ugn_unw/Some-Useful-Memory-Pools.html > suggests System.Pool_Local offers a way to do likewise - a pool that > is automatically reclaimed when it goes out of scope. > > This turns out to have its own performance problem, but that is > another story... > > The question(or four) for now is ... should the following really raise > Storage_Error, i.e. am I doing something silly, and if so, what? Or > is this a bug in Gnat? > > NOTE - using System.Pool_Global.Unbounded_No_Reclaim_Pool (commented > out) instead of the pool shown, works as expected. > > (Tested on GCC4.5.0 and Libre 2010) > > - Brian > > ------------------------------------------------------------------------------------ > with System.Pool_Local; > with System.Pool_Global; > with Ada.Unchecked_Deallocation; > > procedure pooltest is > > type Node; > type Treenode is access Node; > type Node is record > Left : Treenode := null; > Right : Treenode := null; > Item : Integer := 0; > end record; > > P : System.Pool_Local.Unbounded_Reclaim_Pool; > --P : System.Pool_Global.Unbounded_No_Reclaim_Pool; > for Treenode'Storage_Pool use P; > > procedure free is new Ada.Unchecked_Deallocation(Node, Treenode); > > TestNode : Treenode; > > begin > Testnode := new Node'(null, null, 1); > free(Testnode); > end pooltest; > ------------------------------------------------------------------------------------ This looks like a genuine bug at s-pooloc.adb:114. To trigger the bug, two conditions must hold simultaneously: * the pool contains exactly one allocated object. * the user calls Unchecked_Deallocation on this object. The buggy code is: procedure Deallocate (Pool : in out Unbounded_Reclaim_Pool; Address : System.Address; Storage_Size : SSE.Storage_Count; Alignment : SSE.Storage_Count) is pragma Warnings (Off, Storage_Size); pragma Warnings (Off, Alignment); Allocated : constant System.Address := Address - Pointers_Size; begin if Prev (Allocated).all = Null_Address then Pool.First := Next (Allocated).all; Prev (Pool.First).all := Null_Address; ------- <- Storage_Error else Next (Prev (Allocated).all).all := Next (Allocated).all; end if; if Next (Allocated).all /= Null_Address then Prev (Next (Allocated).all).all := Prev (Allocated).all; end if; Memory.Free (Allocated); end Deallocate; This procedure is *not* called by the finalization of the pool, which simply walks the linked list of nodes and deallocates each one, but does not modify any nodes. Because this pool is intended for use without any explicit Unchecked_Deallocation, I would qualify this bug as minor. The workaround, in your case, is to simply not do any Unchecked_Deallocation and let the finalization of the storage pool do the deallocation. -- Ludovic Brenta.