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=-0.3 required=5.0 tests=BAYES_00, REPLYTO_WITHOUT_TO_CC autolearn=no autolearn_force=no version=3.4.4 Path: eternal-september.org!reader01.eternal-september.org!reader02.eternal-september.org!news.eternal-september.org!mx02.eternal-september.org!feeder.eternal-september.org!aioe.org!.POSTED!not-for-mail From: "Dmitry A. Kazakov" Newsgroups: comp.lang.ada Subject: Re: Should weak counted reference be able to be strengthened? Date: Sat, 22 Nov 2014 11:19:23 +0100 Organization: cbb software GmbH Message-ID: <169juip09gkti$.5p7jlls4ehjz.dlg@40tude.net> References: <7d9r3whe43z8$.1f2l3n5cz0zh0$.dlg@40tude.net> <1h5a33dishpky.8m2rngmy7e7x$.dlg@40tude.net> Reply-To: mailbox@dmitry-kazakov.de NNTP-Posting-Host: wfRpp7ltpEWhI2na6kgpfA.user.speranza.aioe.org Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit X-Complaints-To: abuse@aioe.org User-Agent: 40tude_Dialog/2.0.15.1 X-Notice: Filtered by postfilter v. 0.8.2 Xref: news.eternal-september.org comp.lang.ada:23641 Date: 2014-11-22T11:19:23+01:00 List-Id: On Sat, 22 Nov 2014 09:57:05 +0000 (UTC), Natasha Kerensikova wrote: > On 2014-11-21, Dmitry A. Kazakov wrote: >>>>>>> As a side note, I'm a bit surprised by how easy weak/strong reference >>>>>>> seem to be: I think I would only need to store two counters instead of >>>>>>> one, one for the strong references and one for all references, >>>>>>> deallocating the object when the strong reference counter reaches >>>>>>> zero, and freeing the counters when the total counter reaches zero -- as >>>>>>> if each weak reference was a strong reference to the counters. Then it's >>>>>>> only a matter of adding an atomic increase-if-not-zero to the strong >>>>>>> reference counter to build accessors from weak references. >>>>>>> Is there a subtle trap I'm missing? >>>>> >>>>> [...] >>> >>> In the example in the innermost quote, there is no direct notification, >>> in that there is no way to run arbitrary code when the referred object >>> disappear. However the information about object disappearance is >>> accessible to the weak reference: whenever the strong reference count is >>> zero, >> >> The reference count is a part of the object. When the object is gone, there >> is no reference count. >> >> Of course, you could add some levels of indirection to keep counters off >> the objects, but then you would have serious problems, e.g. like Ada tasks >> have when allocated and deallocated dynamically. > > Having the counters separate from the object is actually the defining > point of implementation, and the only reason it exists in the first > place: > > generic > type Held_Data (<>) is limited priavte; > package Natools.References is > [...] > private > type Data_Access is access Held_Data; This won't work. A pool-specific pointer should be the package's parameter, since the objects are allocated outside the package, aren't they? > type Counter_Access is access Counter; > > type Reference is new Ada.Finalization.Controlled with record > Count : Counter_Access := null; > Data : Data_Acess := null; > end record; > end Natools.References; > > As far as I understand, this makes it possible to instantiate with > literally any Ada type, except incomplete ones. If you want this, use a custom storage pool to allocate the objects and put the reference count before the object upon allocation. At least, it will guarantee that both will vanish together. [ There is some minor issue with Ada's design bug of X'Address when X is an unconstrained array, but nothing one could not work around ] > This makes it useful in > a niche not covered by any other implementation (that I know of). I don't think it is useful because reference-counted objects share some common interface. So there must be a base type anyway. > However, what are the serious problems I'm supposed to have? > I have used this implementation with task types, but I have yet to > encounter any. The problem is that when you deallocate a task that is not yet terminated. A typical code deallocating tasks looks like: T.Shut_Down; -- Go away! while not T'Terminated loop -- Still here? delay 0.01; end loop; Free (T); -- We are ready now This is basically the same issue as with your Reference type which may outlive the object. So are some internal things associated with the task, which may outlive the object deallocated when the access-to-task is freed. This is a complicated design with no reason (in case of tasks, there is a reason). Why should reference outlive the object? -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de