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,XPRIO autolearn=no autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 103376,6f69b1cf0f02b9ac,start X-Google-Attributes: gid103376,public X-Google-ArrivalTime: 2001-01-13 08:20:07 PST Path: supernews.google.com!sn-xit-03!supernews.com!logbridge.uoregon.edu!newsfeed.direct.ca!look.ca!newshub2.rdc1.sfba.home.com!news.home.com!news1.sttls1.wa.home.com.POSTED!not-for-mail Reply-To: "DuckE" From: "DuckE" Newsgroups: comp.lang.ada Subject: 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: Sat, 13 Jan 2001 16:18:16 GMT NNTP-Posting-Host: 24.6.221.63 X-Complaints-To: abuse@home.net X-Trace: news1.sttls1.wa.home.com 979402696 24.6.221.63 (Sat, 13 Jan 2001 08:18:16 PST) NNTP-Posting-Date: Sat, 13 Jan 2001 08:18:16 PST Organization: Excite@Home - The Leader in Broadband http://home.com/faster Xref: supernews.google.com comp.lang.ada:3987 Date: 2001-01-13T16:18:16+00:00 List-Id: I have an application that receives a streams of data from TCP/IP sockets. The stream of data is separated into "packets" each beginning with a 32 bit length value. For each of these sockets I have a task that receives the length, then gets a pre-allocated data buffer that is large enough to hold the data, receives the data into the data buffer, and then puts a reference to the buffer into a queue for processing by other tasks. Pseudo code for the main loop for the receive task is something like: Loop Receive 4 bytes of data from the socket Convert the 4 bytes to an integer value Get a buffer from available buffers that is large enough to hold remaining data in message Receive remaining part of message into buffer Queue the message for processing by other tasks End Loop 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 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 This technique has proven reliable in production code, but I don't find it to be very "clean". Suggestions? Here is a subset of my packet implementation: package NPUnetworkPacketUtil is type aPacketNPU is private; private protected type aRefCounterNPU is procedure PlaseHoldNPU; procedure ReleaseHoldNPU( lastHoldNPU : out boolean ); private referenceCountNPU : Natural := 0; end aRefCounterNPU; type aPacketBufNPU( bufSizeNPU : Positive ); type aPacketBUfPtrNPU is accesss all aPacketBufNPU; type aPacketNPU is new Ada.Finalization.Controlled with record packetBufPtrNPU : aPacketBufPtrNPU; end record; procedure Initialize( object : in out aPacketNPU ); procedure Adjust( object : in out aPacketNPU ); procedure Finalize( object : in out aPacketNPU ); type aPacketBufNPU( bufSizeNPU : Positive ) is limited record dataBufferNPU : aliased aDataArrayNPU( 1 .. bufSizeNPU ); holdLockNPU : aRefCounterNPU; end record; end NPUnetworkPacketUtil ; package body NPUnetworkPacketUtil is protected body aRefCounterNPU is procedure PlaceHoldNPU is begin referenceCountNPU := referenceCountNPU + 1; end PlaceHoldNPU; procedure ReleaseHoldNPU( lastHoldNPU : out boolean ) is begin referenceCountNPU := referenceCountNPU - 1; lastHoldNPU := referenceCountNPU = 0; end ReleaseHoldNPU; end aRefCounterNPU; procedure Initialize( object : in out aPacketNPU ) is begin object.packetBufPtrNPU := null; end Initialize; procedure Adjust( object : in out aPacketNPU ) is begin if object.packetBufPtrNPU /= null then packetBufPtrNPU.holdLockNPU.PlaceHoldNPU; end if; end Adjust; procedure Finalize( object : in out aPacketNPU ) is lastHold : boolean; begin if object.packetBufPtrNPU /= null then packetBufNPU.holdLockNPU.ReleaseHoldNPU( lastHold ); if lastHold then -- Take action to put buffer in the free pool end if; end if; end Finalize; end NPUnetworkPacketUtil; Thank's in advance, SteveD