1    /* 
     2     * Copyright (c) 2010, Texas Instruments Incorporated
     3     * All rights reserved.
     4     *
     5     * Redistribution and use in source and binary forms, with or without
     6     * modification, are permitted provided that the following conditions
     7     * are met:
     8     *
     9     * *  Redistributions of source code must retain the above copyright
    10     *    notice, this list of conditions and the following disclaimer.
    11     *
    12     * *  Redistributions in binary form must reproduce the above copyright
    13     *    notice, this list of conditions and the following disclaimer in the
    14     *    documentation and/or other materials provided with the distribution.
    15     *
    16     * *  Neither the name of Texas Instruments Incorporated nor the names of
    17     *    its contributors may be used to endorse or promote products derived
    18     *    from this software without specific prior written permission.
    19     *
    20     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    21     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
    22     * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
    23     * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
    24     * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
    25     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
    26     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
    27     * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
    28     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
    29     * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
    30     * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    31     * */
    32    /*
    33     *  ======== List.xdc ========
    34     *
    35     */
    36    
    37    import xdc.rov.ViewInfo;
    38    
    39    /*!
    40     *  ======== List ========
    41     *  Doubly Linked List Manager
    42     *
    43     *  The List module makes available a set of functions that manipulate
    44     *  List objects accessed through handles of type List_Handle.
    45     *  Each List contains a linked sequence of zero or more elements
    46     *  referenced through variables of type List_Elem, which are typically
    47     *  embedded as the first field within a structure.
    48     *
    49     *  All List function are atomic unless noted otherwise in the API
    50     *  descriptions. An atomic API means that the API completes in core 
    51     *  functionality without being interrupted. Therefore, atomic APIs are
    52     *  thread-safe. An example is {@link #put}. Multiple threads can call
    53     *  {@link #put} at the same time. The threads do not have to manage the
    54     *  synchronization.
    55     *
    56     *  The {@link xdc.runtime.Gate#enterSystem}/{@link xdc.runtime.Gate#leaveSystem}
    57     *  calls are used to make the APIs atomic. This Gate calls internally use 
    58     *  {@link xdc.runtime.System}'s gate.
    59     *
    60     *  The List module can be used both as a queue (i.e. First In First Out),
    61     *  as a stack (i.e. Last In First Out), or as a general purpose linked list.
    62     *
    63     *  Lists are represented as doubly-linked lists, so calls to {@link #next}
    64     *  or {@link #prev} can loop continuously over the List. 
    65     *  Refer to {@link #next} and {@link #prev} for examples.
    66     *
    67     *  @a(List as a Queue)
    68     *
    69     *  To treat the list object as a queue:
    70     *  @p(blist)
    71     *  -Use {@link #put} to put at the tail of the queue
    72     *  -Use {@link #get} to get from the head of the queue
    73     *  @p
    74     *
    75     *  Here is sample code that acts on a List instance (listHandle) as a queue
    76     *  in a FIFO manner.
    77     *
    78     *  @p(code)
    79     *  List_Elem  elem[4];
    80     *  List_Elem *tmpElem;
    81     *
    82     *  // place at the tail of the queue
    83     *  for (i = 0; i < 4; i++) {
    84     *      List_put(listHandle, &(elem[i]));  
    85     *  }
    86     *
    87     *  // remove the buffers from the head
    88     *  while((tmpElem = List_get(listHandle)) != NULL) {
    89     *      // process tmpElem
    90     *  }
    91     *  @p
    92     *
    93     *  @a(List as a Stack)
    94     *
    95     *  To treat the list object as a stack:
    96     *  @p(blist)
    97     *  -Use {@link #putHead} to put at the top of the stack
    98     *  -Use {@link #get} to get from the top of the stack
    99     *  @p
   100     *
   101     *  Here is sample code that acts on a List instance (listHandle) as a stack
   102     *  in a LIFO manner.
   103     *
   104     *  @p(code)
   105     *  List_Elem  elem[4];
   106     *  List_Elem *tmpElem;
   107     *
   108     *  // push onto the top (i.e. head)
   109     *  for (i = 0; i < 4; i++) {
   110     *      List_putHead(listHandle, &(elem[i]));
   111     *  }
   112     *
   113     *  // remove the buffers in FIFO order.
   114     *  while((tmpElem = List_get(listHandle)) != NULL) {
   115     *      // process tmpElem
   116     *  }
   117     *  @p
   118     */
   119    
   120    module List
   121    {
   122        metaonly struct BasicView {
   123            String  label;
   124            Ptr     elems[];
   125        }
   126    
   127        @Facet
   128        metaonly config ViewInfo.Instance rovViewInfo = 
   129            ViewInfo.create({
   130                viewMap: [
   131                    ['Basic', {type: ViewInfo.INSTANCE, viewInitFxn: 'viewInitInstance', structName: 'BasicView'}]
   132                ]
   133            });
   134    
   135        /*!
   136         *  ======== Elem ========
   137         *  Opaque List element
   138         *
   139         *  A field of this type is placed at the head of client structs.
   140         */
   141        @Opaque struct Elem {
   142            Elem *volatile next;    /* must be volatile for whole_program */
   143            Elem *volatile prev;    /* must be volatile for whole_program */
   144        };
   145        
   146        /*!
   147         *  ======== elemClearMeta ========
   148         *  Clears a List element's pointers
   149         *
   150         *  This API is not for removing elements from a List, and
   151         *  should never be called on an element in a List--only on deListed
   152         *  elements.
   153         *
   154         *  @param(elem)            element to be cleared
   155         */
   156        metaonly Void elemClearMeta(Elem *elem);
   157        
   158        /*!
   159         *  ======== elemClear ========
   160         *  Clears a List element's pointers
   161         *
   162         *  This API does not removing elements from a List, and
   163         *  should never be called on an element in a List--only on deListed
   164         *  elements.
   165         *
   166         *  @param(elem)            element to be cleared
   167         */
   168        Void elemClear(Elem *elem);
   169    
   170    instance:
   171    
   172        /*!
   173         *  ======== metaList ========
   174         *  @_nodoc
   175         *  Used to store elem before the object is initialized.
   176         */
   177        metaonly config any metaList[];
   178    
   179        /*!
   180         *  ======== create ========
   181         *  Create a List object
   182         */
   183        create();
   184    
   185        /*!
   186         *  ======== empty ========
   187         *  Test for an empty List (atomic)
   188         *
   189         *  @b(returns)     TRUE if this List is empty
   190         */
   191        Bool empty();
   192    
   193        /*!
   194         *  ======== get ========
   195         *  Get element from front of List (atomic)
   196         *
   197         *  This function atomically removes the element from the front of a
   198         *  List and returns a pointer to it.
   199         *
   200         *  @b(returns)     pointer to former first element or NULL if empty
   201         */
   202        Ptr get();
   203    
   204        /*!
   205         *  ======== put ========
   206         *  Put element at end of List (atomic)
   207         *
   208         *  This function atomically places the element at the end of 
   209         *  List.     
   210         *
   211         *  @param(elem)    pointer to new List element
   212         */
   213        Void put(Elem *elem);
   214        
   215        /*!
   216         *  ======== putHead ========
   217         *  Put element at head of List (atomic)
   218         *
   219         *  This function atomically places the element at the front of 
   220         *  List.     
   221         *
   222         *  @param(elem)    pointer to new List element
   223         */
   224        Void putHead(Elem *elem);
   225    
   226        /*!
   227         *  ======== putMeta ========
   228         *  @_nodoc
   229         *  Put element at end of List.
   230         *
   231         *  This meta function can be used to place an element onto
   232         *  the end of a list during configuration. There currently 
   233         *  is no meta API to place the elem at the head of the list
   234         *  during configuration.
   235         *
   236         *  @param(elem)            pointer to new List element
   237         */
   238        metaonly Void putMeta(Elem* elem);
   239    
   240        /*!
   241         *  ======== next ========
   242         *  Return next element in List (non-atomic)
   243         *
   244         *  This function returns the next element on a list. It does not
   245         *  remove any items from the list. The caller should protect the 
   246         *  list from being changed while using this call since it is non-atomic.
   247         *
   248         *  To look at the first elem on the list, use NULL as the elem argument. 
   249         *
   250         *  This function is useful in searching a list. The following code shows
   251         *  an example. The scanning of a list should be protected against other
   252         *  threads that modify the list.
   253         *
   254         *  @p(code)
   255         *  List_Elem  *elem = NULL;
   256         *
   257         *  // Begin protection against modification of the list.
   258         *
   259         *  while ((elem = List_next(listHandle, elem)) != NULL) {
   260         *      //act elem as needed. For example call List_remove().
   261         *  }
   262         *
   263         *  // End protection against modification of the list.
   264         *  @p
   265         *
   266         *  @param(elem)    element in list or NULL to start at the head
   267         *
   268         *  @b(returns)     next element in list or NULL to denote end
   269         */
   270        Ptr next(Elem *elem);
   271    
   272        /*!
   273         *  ======== prev ========
   274         *  Return previous element in List (non-atomic)
   275         *
   276         *  This function returns the previous element on a list. It does not
   277         *  remove any items from the list. The caller should protect the 
   278         *  list from being changed while using this call since it is non-atomic.
   279         *
   280         *  To look at the last elem on the list, use NULL as the elem argument. 
   281         *
   282         *  This function is useful in searching a list in reverse order. The 
   283         *  following code shows an example. The scanning of a list should be 
   284         *  protected against other threads that modify the list.
   285         *
   286         *  @p(code)
   287         *  List_Elem  *elem = NULL;
   288         *
   289         *  // Begin protection against modification of the list.
   290         *
   291         *  while ((elem = List_prev(listHandle, elem)) != NULL) {
   292         *      //act elem as needed. For example call List_remove().
   293         *  }
   294         *
   295         *  // End protection against modification of the list.
   296         *  @p
   297         *
   298         *  @param(elem)    element in list or NULL to start at the end (i.e. tail)
   299         *
   300         *  @b(returns)     previous element in list or NULL to denote 
   301         *                  no previous elem
   302         */
   303        Ptr prev(Elem *elem);
   304    
   305        /*!
   306         *  ======== insert ========
   307         *  Insert element at into a List (non-atomic)
   308         *
   309         *  This function inserts `newElem` in the queue in 
   310         *  front of `curElem`. The caller should protect the 
   311         *  list from being changed while using this call since it is non-atomic.
   312         *
   313         *  To place an elem at the end of the list, use {@link #put}.
   314         *  To place a elem at the front of the list, use {@link #putHead}.
   315         *
   316         *  @param(newElem)         element to insert
   317         *
   318         *  @param(curElem)         element to insert in front of
   319         */
   320        Void insert(Elem *newElem, Elem *curElem);
   321    
   322        /*!
   323         *  ======== remove ========
   324         *  Remove elem from middle of list (non-atomic)
   325         *
   326         *  This function removes an elem from a list.
   327         *  The `elem` parameter is a pointer to an existing element to be removed
   328         *  from the List.  The caller should protect the 
   329         *  list from being changed while using this call since it is non-atomic.
   330         *
   331         *  @param(elem)            element in list
   332         */
   333        Void remove(Elem *elem);
   334        
   335        /*!
   336         *  ======== dequeue ========
   337         *  Get element from front of List (non-atomic)
   338         *
   339         *  This function atomically removes the element from the front of a
   340         *  List and returns a pointer to it.
   341         *
   342         *  @b(returns)     pointer to former first element or NULL if empty
   343         */
   344        Ptr dequeue();
   345    
   346        /*!
   347         *  ======== enqueue ========
   348         *  Put element at end of List (non-atomic)
   349         *
   350         *  This function atomically places the element at the end of 
   351         *  List.     
   352         *
   353         *  @param(elem)    pointer to new List element
   354         */
   355        Void enqueue(Elem *elem);
   356        
   357        /*!
   358         *  ======== enqueueHead ========
   359         *  Put element at head of List (non-atomic)
   360         *
   361         *  This function atomically places the element at the front of 
   362         *  List.     
   363         *
   364         *  @param(elem)    pointer to new List element
   365         */
   366        Void enqueueHead(Elem *elem);
   367    
   368    internal:   
   369    
   370        /* instance object */
   371        struct Instance_State {
   372            Elem elem;
   373        };
   374    }
   375    /*
   376     *  @(#) ti.sdo.utils; 1, 0, 0, 0,419; 8-10-2010 17:49:44; /db/vtree/library/trees/ipc/ipc-e23x/src/
   377     */
   378