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-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 103376,6f69b1cf0f02b9ac X-Google-Attributes: gid103376,public X-Google-ArrivalTime: 2001-01-22 22:02:54 PST Path: supernews.google.com!sn-xit-02!supernews.com!nntp-relay.ihug.net!ihug.co.nz!newsfeed.mesh.ad.jp!newshub2.rdc1.sfba.home.com!news.home.com!news1.sttls1.wa.home.com.POSTED!not-for-mail From: "DuckE" Newsgroups: comp.lang.ada References: <94hoeu$puk$1@nnrp1.deja.com> Subject: Re: How can I avoid Using a Semaphore? (long) X-Priority: 3 X-MSMail-Priority: Normal X-Newsreader: Microsoft Outlook Express 5.50.4133.2400 X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4133.2400 Message-ID: Date: Tue, 23 Jan 2001 06:02:47 GMT NNTP-Posting-Host: 24.6.221.63 X-Complaints-To: abuse@home.net X-Trace: news1.sttls1.wa.home.com 980229767 24.6.221.63 (Mon, 22 Jan 2001 22:02:47 PST) NNTP-Posting-Date: Mon, 22 Jan 2001 22:02:47 PST Organization: Excite@Home - The Leader in Broadband http://home.com/faster Xref: supernews.google.com comp.lang.ada:4351 Date: 2001-01-23T06:02:47+00:00 List-Id: > > To avoid memory leaks I am using a controlled type with reference counting > > to implement my data buffer. Since multiple threads may simultaneously have > > access to the buffer, I use a protected type for reference counting. > > > > Since I am using a protected type for reference counting, I cannot assign > > packets within a protected type (to implement queue's of packets for > > instance) since these assignments would be attempting to do a protected > > operation within a protected type. > > I don't get it! Can you explain that? Are you talking about > the "potentially blocking" rule? I don't see how the scenario you > described would run afoul of that rule, and I couldn't find anything in > your example code to help me understand what you meant... This is exactly the rule I'm talking about. I have defined my protected type for reference counting (aRefCounterNPU) contained in the packet buffer (aPacketBufNPU). I put my reference counter inside of a protected type since different tasks may concurrently have references to the same packet buffer and may release them asynchronously. aPacketNPU is a controlled type containing a reference to a packet buffer (aPacketBufNPU) that invokes the "PlaceHoldNPU" and "ReleaseHoldNPU" procedures durning the "Adjust" and "Finalize" routines as packets are assigned and finalized. If it were permitted, I would use a protected object to contain my pool of available packets. Something like: PROTECTED TYPE Buffer_Manager IS FUNCTION New_Packet( packetSize : Positive ) RETURN aPacketNPU; PROCEDURE Free_Packet( packet : in out aPacketNPU ); END Buffer_Manager; But in implementing this buffer manager I would be performing assignments of packet buffers inside the protected type, and thus violate the potentially blocking rule. Am I missing something here? > > > > > I have worked around this using a semaphore (the semaphore is created using > > a protected type) around the assignment of packets: > > > > lock semaphore > > assign packet > > unlock semaphore > > I didn't see anything like that in your example -- it looked like you > were using your Mutex type (or aMutex or whatever) to protect your free > block lists. > In my example the routine NewPacketNPU may be called on by different tasks in order to obtain new packets, so access to the free list must be protected. But since assignment of entries from the list requires placing a hold on the entries taken from the list, I run into the potentially blocking rule. That was my reasoning when I wrote the code. But now I'm starting to think that I may be able to re-arrange things such that the reference count is adjusted outside of accessing the free lists, which would solve my problem. I'll have to look at this some more... I didn't include it in my example, but I run into a similar difficulty when I go to put packets into a queue. It seems that introducing that reference counter in the controlled type makes things tricky all around. > So help me understand more about this semaphore problem... > > In the meantime, a couple of notes: > > 1) You've said you want to avoid heap allocation -- is that for > performance reasons? If so, do you know for sure that heap allocation > is going to cause you to miss deadlines or cause a performance > bottleneck? If you don't know for sure, you might just go ahead and > write it using heap allocation and without all this extra complexity. > Then, if that turns out to be not good enough, you can always implement > your own allocation scheme (and the right way to encapsulate that is > probably with your own Storage_Pool type -- it's easy and direct, > no "magic" to worry about). This code is in a library module that is common to several pieces of software. It is one of those cases where adding a small degree of complexity may benefit the performance of several applications. > > 2) Also if you care about performance, implementing a mutex as a > protected record is generally a case of "abstraction inversion" with an > attendant performance penalty -- my guess is that that's going to hit > you harder than heap allocation would. The Ada runtime is implementing > protected records on top of mutexes and condition variables and stuff > provided by the OS, and it's probably doing all kinds of checks for > pending aborts and other stuff that it has to do, and all you want is a > mutex! You might look into using the OS-supplied mutexes directly, > *if* it turns out that's what you really need (needing locking to be > primitive is often a red flag that some part of the design is "inside > out"). That's why I posted this inquiry in the first place. > > 3) You have an array of free block lists, and a "parallel" array of > mutexes associated with the free block lists. Doesn't that mean that > you really want a mutex to be part of a free block list? > Perhaps, but as you'll notice I initialize my free block lists using: availablePacketTable : anAvailablePacketTable := ( 1 => ( NULL, 2**5, 0, 64 ), -- 32 2 => ( NULL, 2**6, 0, 32 ), -- 64 3 => ( NULL, 2**7, 0, 32 ), -- 128 4 => ( NULL, 2**8, 0, 16 ), -- 256 5 => ( NULL, 2**9, 0, 16 ), -- 512 6 => ( NULL, 2**10, 0, 16 ), -- 1024 7 => ( NULL, 2**11, 0, 16 ), -- 2048 8 => ( NULL, 2**12, 0, 16 ), -- 4096 9 => ( NULL, 2**13, 0, 16 ), -- 8192 10 => ( NULL, 2**14, 0, 16 ), -- 16384 11 => ( NULL, 2**15, 0, 16 ), -- 32768 12 => ( NULL, 2**16, 0, 16 ), -- 65536 13 => ( NULL, 2**17, 0, 16 ), -- 131072 14 => ( NULL, 2**18, 0, 16 ), -- 262144 15 => ( NULL, 2**19, 0, 16 ), -- 524288 16 => ( NULL, 2**20, 0, 16 ) -- 1048576 ); If I made the "mutex" a part of the record, how would it appear in this initializer? > 4) Just a style point here, but to me using Interfaces.C.Char to > represent a byte or octet or whatever you want to call it, seems a > little weird. I like to think that Interfaces.C is for interfacing to > C. A better choice might be Interfaces.Unsigned_8. As I recall this is just mating with the types used by the Win32Ada bindings. > > Anyway, hope you give some more detail about the semaphore issue... > > Best Regards, > Mark Lundquist > > P.S. Your identifier style sucks. (Why mince words? :-) :-) :-) Any style of code with which you are unfamiliar "sucks". Every time someone new comes to our group we hear the same comment. Usually it takes less than 2 weeks and they never know how they did without it. Thanks for your response. SteveD > > > Sent via Deja.com > http://www.deja.com/