comp.lang.ada
 help / color / mirror / Atom feed
From: "DuckE" <nospam_steved94@home.com>
Subject: Re: How can I avoid Using a Semaphore? (long)
Date: Tue, 23 Jan 2001 06:02:47 GMT
Date: 2001-01-23T06:02:47+00:00	[thread overview]
Message-ID: <b89b6.298508$U46.9559869@news1.sttls1.wa.home.com> (raw)
In-Reply-To: 94hoeu$puk$1@nnrp1.deja.com

> > 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/





  reply	other threads:[~2001-01-23  6:02 UTC|newest]

Thread overview: 36+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2001-01-13 16:18 How can I avoid Using a Semaphore? (long) DuckE
2001-01-15  1:06 ` How can I avoid Using a Semaphore? Nick Roberts
2001-01-15  3:17   ` Robert Dewar
2001-01-16  3:53   ` DuckE
2001-01-17 15:42     ` Nick Roberts
2001-01-20 18:16       ` DuckE
2001-01-20 19:16         ` Robert Dewar
2001-01-21  1:28           ` DuckE
2001-01-21 16:04             ` Robert Dewar
2001-01-21 23:23               ` DuckE
2001-01-22  0:28                 ` mark_lundquist
2001-01-22  1:51                 ` Robert Dewar
2001-01-23  2:36                   ` DuckE
2001-01-22  0:35               ` Built-in types (was " mark_lundquist
2001-01-22  1:54                 ` Robert Dewar
2001-01-22 16:18                   ` mark_lundquist
2001-01-22 17:20                     ` Robert Dewar
2001-01-22 23:17                       ` Mark Lundquist
     [not found]                         ` <m33deaaeks.fsf@ns40.infomatch.bc.ca>
2001-02-02 22:01                           ` Mark Lundquist
     [not found]                         ` <94km00$bv8$1@nnrp1.deja.com>
2001-02-02 22:03                           ` Mark Lundquist
2001-01-21 16:53           ` Nick Roberts
2001-01-21 18:24             ` Robert Dewar
2001-01-23  0:21               ` Nick Roberts
2001-01-22  0:16         ` mark_lundquist
2001-01-22 16:51 ` How can I avoid Using a Semaphore? (long) mark_lundquist
2001-01-23  6:02   ` DuckE [this message]
2001-02-02 22:00     ` Sucking (was Re: How can I avoid Using a Semaphore? (long)) Mark Lundquist
2001-02-03  1:44       ` Jeffrey Carter
2001-02-03  3:21       ` DuckE
2001-02-05 20:07         ` Mark Lundquist
2001-02-06  7:16           ` Sven Nilsson
2001-02-02 22:18     ` How can I avoid Using a Semaphore? (long) Mark Lundquist
2001-02-03  3:01       ` DuckE
2001-02-02 21:38 ` Niklas Holsti
  -- strict thread matches above, loose matches on Subject: below --
2001-02-07 21:55 Beard, Frank
2001-02-08 23:42 Beard, Frank
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox