Google
 

Trailing-Edge - PDP-10 Archives - BB-P363B-SM_1985 - mcb/nml/nmuque.bli
There are 3 other files named nmuque.bli in the archive. Click here to see a list.
! NET:<VOBA.NML.DEVELOPMENT>NMUQUE.BLI.3 25-Mar-82 17:59:35, Edit by VOBA
!
! Ident 3.
! Add routine NMU$QUEUE_LENGTH to return the length (number of entries) of
! a queue.
!
! NET:<VOBA.NML.DEVELOPMENT>NMUQUE.BLI.5  4-Mar-82 14:19:09, Edit by VOBA
!
! Ident 2.
! Clean up code and update copyright date.
!
!NET:<DECNET20-V3P1.BASELEVEL-2.SOURCES>NMUQUE.BLI.4 12-Aug-81 10:47:34, Edit by JENNESS
!
!    Update copyright notice.
!    Clean up code, update to current coding conventions.
%title 'NMUQUE -- General Queue Management'
module NMUQUE (
               ident = 'X00.03'
               ) =
begin

!                    COPYRIGHT (c) 1980, 1981, 1982
!                    DIGITAL EQUIPMENT CORPORATION
!                        Maynard, Massachusetts
!
!     This software is furnished under a license and may  be  used
!     and copied only in accordance with the terms of such license
!     and with the inclusion of the above copyright notice.   This
!     software  or any other copies thereof may not be provided or
!     otherwise made available to any other person.  No  title  to
!     and ownership of the software is hereby transferred.
!
!     The information  in  this  software  is  subject  to  change
!     without  notice  and should not be construed as a commitment
!     by DIGITAL EQUIPMENT CORPORATION.
!
!     DIGITAL assumes no responsibility for the use or reliability
!     of  its  software  on  equipment  which  is  not supplied by
!     DIGITAL.
!

!++
! Facility: LSG DECnet Network Management
!
! Abstract:
!
!       This set of routines provides a primitives for
!       manipulating queues.  The only requirement for
!       using this set of routines is that the queue overhead
!       information must be defined at the very beginning
!       of any entry made to a queue.
!
! Environment: TOPS10 and TOPS20 user mode, MCB RSX task level
!
! Author: Steven M. Jenness, Creation date: 19 August 1980
!
!--
!
! INCLUDE FILES
!

library 'NMULIB';                       ! All needed definitions

!
! TABLE OF CONTENTS
!

forward routine
    NMU$QUEUE_MANAGER;                  ! Global entry definitions
%global_routine ('NMU$QUEUE_RESET', QUEUE: ref Q_HEADER) : novalue =

!++
! Functional description:
!
!       This routine resets a queue header to the null
!       state.
!
! Formal parameters:
!
!       .QUEUE   Address of queue header
!
! Routine value: none
! Side effects:
!
!       All pointers in the queue header point to
!       the header itself (empty queue).
!
!--

    begin

    QUEUE[Q_FORWARD] = .QUEUE;
    QUEUE[Q_REVERSE] = .QUEUE;
    UNLOCK (QUEUE[Q_SEMAPHORE]);

    end;                                ! End of NMU$QUEUE_RESET
%global_routine ('NMU$QUEUE_INSERT', QUEUE: ref Q_HEADER, ENTRY: ref Q_ENTRY) =

!++
! Functional description:
!
!       This routine inserts an entry to the end of
!       a queue.
!
! Formal parameters:
!
!       .QUEUE   Address of queue header
!       .ENTRY   Address of entry data.  The queueing information
!                is stored starting at this address.  A block
!                of length Q_ENTRY_SIZE must be reserved.
!
! Routine value:
!
!       $true   if queue becomes non-empty with this insert
!       $false  if queue was previously non-empty
!
! Side effects:
!
!       The forward pointer of the last item on the queue and
!       the reverse pointer of the queue header are changed to
!       point to the new entry.
!
!--

    begin

    local
	LAST_ENTRY : ref Q_ENTRY,
	RET_VAL;

!
! Lock the queue from concurrently running processes.
!

    while not LOCK (QUEUE[Q_SEMAPHORE])
    do 1;

!
! If the queue header is zero ... queue is empty.
! Initialize the queue header.
!

    if .(.QUEUE) eql 0
    then begin
         QUEUE[Q_FORWARD] = .QUEUE;
         QUEUE[Q_REVERSE] = .QUEUE;
         end;

!
! Check for queue empty and set empty transition
! flag.
!

    RET_VAL = (.QUEUE eql .QUEUE[Q_REVERSE]); ! Check for non-empty

!
! Insert entry onto end of queue and
! update pointers.
!

    LAST_ENTRY = .QUEUE[Q_REVERSE];
    ENTRY[Q_REVERSE] = .LAST_ENTRY;
    ENTRY[Q_FORWARD] = .QUEUE;
    QUEUE[Q_REVERSE] = .ENTRY;
    LAST_ENTRY[Q_FORWARD] = .ENTRY;

!
! Unlock the queue.
!

    UNLOCK (QUEUE[Q_SEMAPHORE]);

!
! Return empty to non-empty transition flag.
!

    return .RET_VAL;
    end;                                ! End of NMU$QUEUE_INSERT
%global_routine ('NMU$QUEUE_REMOVE', QUEUE: ref Q_HEADER) =

!++
! Functional description:
!
!       This routine removes the first entry on a queue.
!       If the queue is empty a zero (0) value is returned.
!
! Formal parameters:
!
!       .QUEUE   Address of queue header
!
! Routine value:
!
!       Non-empty queue    Address of entry (after queue information)
!       Empty queue        Zero (0)
!
! Side effects:
!
!       The forward pointer of the queue header and the
!       reverse pointer of the second entry (if any) are
!       changed to point to each other.
!--

    begin

    local
	ENTRY : ref Q_ENTRY,
	NEXT_ENTRY : ref Q_ENTRY;

!
! Lock the queue from concurrently running processes.
!

    while not LOCK (QUEUE[Q_SEMAPHORE])
    do 1;

!
! If the queue header is zero ... queue is empty.
! Initialize the queue header.
!

    if .(.QUEUE) eql 0
    then begin
         QUEUE[Q_FORWARD] = .QUEUE;
         QUEUE[Q_REVERSE] = .QUEUE;
         end;

!
! Get address of first entry on the queue.
!

    ENTRY = .QUEUE[Q_FORWARD];

!
! Check for empty queue, return zero if empty.
! If entry found...
!	unlink from queue
!	fixup queue around hole made by removal
!	clear queue linkage in removed entry.
!

    if .ENTRY eql .QUEUE
    then ENTRY = 0
    else begin
         NEXT_ENTRY = .ENTRY[Q_FORWARD];
         QUEUE[Q_FORWARD] = .NEXT_ENTRY;
         NEXT_ENTRY[Q_REVERSE] = .QUEUE;
         ENTRY[Q_FORWARD] = 0;
         ENTRY[Q_REVERSE] = 0;
         end;

    UNLOCK (QUEUE[Q_SEMAPHORE]);        ! Unlock the queue

    return .ENTRY;                      ! Return address of entry found, if any
    end;                                ! End of NMU$QUEUE_REMOVE
%global_routine ('NMU$QUEUE_EXTRACT', QUEUE: ref Q_HEADER, ENTRY: ref Q_ENTRY) =

!++
! Functional description:
!
!       This routine handles extraction of an entry from a place
!       in a queue other than the beginning.  This requires "knowing"
!       the address of the queue entry before calling this routine.
!
! Formal parameters:
!
!       .QUEUE   Address of queue header
!       .ENTRY   Address of entry (after queue information)
!
! Routine value:
!
!	$true	Entry was found on the queue and extracted
!	$false	Entry was not found on the queue
!
! Side effects:
!
!       The links of the queue entries before and after the
!       entry to be extracted are updated to point to each
!       other.
!
!--

    begin

    local
	NEXT_ENTRY : ref Q_ENTRY,
	PREVIOUS_ENTRY : ref Q_ENTRY,
	SEARCH : ref Q_ENTRY,
	RET_VAL;

!
! Lock the queue from concurrently running processes.
!

    while not LOCK (QUEUE[Q_SEMAPHORE])
    do 1;

!
! If the queue header is zero ... queue is empty.
! Initialize the queue header.
!

    if .(.QUEUE) eql 0
    then begin
         QUEUE[Q_FORWARD] = .QUEUE;
         QUEUE[Q_REVERSE] = .QUEUE;
         end;

!
! Loop until the entry is found.
!

    SEARCH = .QUEUE[Q_FORWARD];

    while (.SEARCH neq .ENTRY) and (.SEARCH neq .QUEUE)
    do SEARCH = .SEARCH[Q_FORWARD];

    if .SEARCH eql .ENTRY               ! Found entry ?
    then begin                          ! Yes, extract it and return true
         NEXT_ENTRY = .ENTRY[Q_FORWARD];
         PREVIOUS_ENTRY = .ENTRY[Q_REVERSE];
         NEXT_ENTRY[Q_REVERSE] = .PREVIOUS_ENTRY;
         PREVIOUS_ENTRY[Q_FORWARD] = .NEXT_ENTRY;
         RET_VAL = $TRUE;
         end
    else RET_VAL = $FALSE;              ! No, return false

    UNLOCK (QUEUE[Q_SEMAPHORE]);        ! Unlock queue

    return .RET_VAL;                    ! Return result of extraction
    end;                                ! End of NMU$QUEUE_EXTRACT
%global_routine ('NMU$QUEUE_LENGTH', QUEUE: ref Q_HEADER) =

!++
! Functional description:
!
!       This routine returns the length (number of entries) of a queue.
!
! Formal parameters:
!
!       .QUEUE   Address of queue header
!
! Routine value:
!
!       The length (number of entries) of the queue.
!
! Side effects: none
!
!--

    begin

    local
	ENTRY,
        RESULT,
	NEXT : ref Q_ENTRY;

!
! Lock the queue from concurrently running processes.
!

    while not LOCK (QUEUE[Q_SEMAPHORE])
    do 1;

!
! If the queue header is zero ... queue is empty.
! Return length of 0
!

    RESULT = 0;

    if .(.QUEUE) neq 0
    then begin
         NEXT = .QUEUE[Q_FORWARD];      ! Set first entry to the queue

         while (ENTRY = .NEXT) neq .QUEUE
         do begin                       ! Scan queue until end of queue
            RESULT = .RESULT + 1;
            NEXT = .NEXT[Q_FORWARD];
            end;
         end;

    UNLOCK (QUEUE[Q_SEMAPHORE]);        ! Unlock the queue

    return .RESULT;                     ! Return the result of scanning
    end;                                ! End of NMU$QUEUE_LENGTH
%global_routine ('NMU$QUEUE_SCAN', QUEUE: ref Q_HEADER, DATA, S_RTN) =

!++
! Functional description:
!
!       This routine facilitates scanning a queue.  The S_RTN
!       parameter specifies a routine that is to be called with
!       the DATA parameter and each ENTRY.  When the return
!       from the S_RTN is non-zero or the queue runs out, the
!       scanning stops.
!
! Formal parameters:
!
!       .QUEUE   Address of queue header
!       .DATA    Data to be passed to each S_RTN call
!       .S_RTN   Scanning routine to be called for each entry
!
! Routine value:
!
!       The value of S_RTN if it ever returns a non-zero value.
!       Zero if the queue runs out before non-zero from S_RTN.
!
! Side effects: none
!
!--

    begin

    bind routine
	SCAN_ROUTINE = .S_RTN;

    local
	ENTRY,
	RESULT,
	NEXT : ref Q_ENTRY;

!
! Lock the queue from concurrently running processes.
!

    while not LOCK (QUEUE[Q_SEMAPHORE])
    do 1;

!
! If the queue header is zero ... queue is empty.
! Initialize the queue header.
!

    if .(.QUEUE) eql 0
    then begin
         QUEUE[Q_FORWARD] = .QUEUE;
         QUEUE[Q_REVERSE] = .QUEUE;
         end;

!
! Clear the result value and point to the
! first entry on the queue.
!

    RESULT = 0;
    NEXT = .QUEUE[Q_FORWARD];

!
! Scan queue until end of queue or the scan
! routine returns a non zero value.
!

    while (ENTRY = .NEXT) neq .QUEUE
    do begin
       NEXT = .NEXT[Q_FORWARD];
       UNLOCK (QUEUE[Q_SEMAPHORE]);

       if (RESULT = SCAN_ROUTINE (.ENTRY, .DATA)) neq 0
       then exitloop;

       while not LOCK (QUEUE[Q_SEMAPHORE])
       do 1;
       end;

    UNLOCK (QUEUE[Q_SEMAPHORE]);        ! Unlock the queue

    return .RESULT;                     ! Return the result of scanning
    end;                                ! End of NMU$QUEUE_SCAN
%global_routine ('NMU$QUEUE_SCAN_EXTRACT', ENTRY: ref Q_ENTRY) : novalue =

!++
! Functional description:
!
!	This routine is used to extract a queue entry from
!	a queue while scanning the queue.  It is assumed
!	that the only queue being worked on is the one being
!	scanned.  It also is assumed that the entry being
!	extracted is the one currently being looked at by
!	the scanning routine.
!
!	ANY OTHER USE OF THIS ROUTINE CAN GIVE UNPREDICTABLE
!	RESULTS!
!
! Formal parameters:
!
!	.ENTRY	Address of queue entry to remove.
!
! Routine value: none
! Side effects: none
!
!--

    begin

    local
	NEXT_ENTRY : ref Q_ENTRY,
	PREVIOUS_ENTRY : ref Q_ENTRY;

    NEXT_ENTRY = .ENTRY[Q_FORWARD];
    PREVIOUS_ENTRY = .ENTRY[Q_REVERSE];
    NEXT_ENTRY[Q_REVERSE] = .PREVIOUS_ENTRY;
    PREVIOUS_ENTRY[Q_FORWARD] = .NEXT_ENTRY;

    end;					! End of NMU$QUEUE_SCAN_EXTRACT
end						! End of module NMUQUE
eludom
! Local Modes:
! Mode:BLISS
! Auto Save Mode:2
! Comment Column:40
! Comment Rounding:+1
! End: