dafc9467e437a9cd30585c2aec02a7514a27d367
[ric-plt/lib/rmr.git] / src / rmr / common / src / ring_static.c
1 // :vi sw=4 ts=4 noet:
2 /*
3 ==================================================================================
4         Copyright (c) 2019 Nokia
5         Copyright (c) 2018-2019 AT&T Intellectual Property.
6
7    Licensed under the Apache License, Version 2.0 (the "License");
8    you may not use this file except in compliance with the License.
9    You may obtain a copy of the License at
10
11            http://www.apache.org/licenses/LICENSE-2.0
12
13    Unless required by applicable law or agreed to in writing, software
14    distributed under the License is distributed on an "AS IS" BASIS,
15    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16    See the License for the specific language governing permissions and
17    limitations under the License.
18 ==================================================================================
19 */
20 /*
21         Mnemonic:       ring_static.c
22         Abstract:       Implements a ring of information (probably to act as a
23                                 message queue).
24         Author:         E. Scott Daniels
25         Date:           31 August 2017
26 */
27
28 #ifndef _ring_static_c
29 #define _ring_static_c
30
31 #include <unistd.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <strings.h>
35 #include <errno.h>
36 #include <string.h>
37 #include <stdint.h>
38
39 #define RING_FAST 1                     // when set we skip nil pointer checks on the ring pointer
40
41 /*
42         Make a new ring.
43 */
44 static void* uta_mk_ring( int size ) {
45         ring_t* r;
46         uint16_t max;
47
48         if( size <= 0 || (r = (ring_t *) malloc( sizeof( *r ) )) == NULL ) {
49                 return NULL;
50         }
51
52         r->head = r->tail = 0;
53
54         max = (r->head - 1);
55         if( size >= max ) {
56                 size--;
57         }
58
59         r->nelements = size;            // because we always have an empty element when full
60         if( (r->data = (void **) malloc( sizeof( void** ) * (r->nelements + 1) )) == NULL ) {
61                 free( r );
62                 return NULL;
63         }
64
65         memset( r->data, 0, sizeof( void** ) * r->nelements );
66         return (void *) r;
67 }
68
69 /*
70         Ditch the ring. The caller is responsible for extracting any remaining
71         pointers and freeing them as needed.
72 */
73 static void uta_ring_free( void* vr ) {
74         ring_t* r;
75
76         if( (r = (ring_t*) vr) == NULL ) {
77                 return;
78         }
79
80         free( r );
81 }
82
83
84 /*
85         Pull the next data pointer from the ring; null if there isn't
86         anything to be pulled.
87 */
88 static inline void* uta_ring_extract( void* vr ) {
89         ring_t*         r;
90         uint16_t        ti;             // real index in data
91
92         if( !RING_FAST ) {                                                              // compiler should drop the conditional when always false
93                 if( (r = (ring_t*) vr) == NULL ) {
94                         return 0;
95                 }
96         } else {
97                 r = (ring_t*) vr;
98         }
99
100         if( r->tail == r->head ) {                      // empty ring
101                 return NULL;
102         }
103
104         ti = r->tail;
105         r->tail++;
106         if( r->tail >= r->nelements ) {
107                 r->tail = 0;
108         }
109
110         return r->data[ti];
111 }
112
113 /*
114         Insert the pointer at the next open space in the ring.
115         Returns 1 if the inert was ok, and 0 if the ring is full.
116 */
117 static inline int uta_ring_insert( void* vr, void* new_data ) {
118         ring_t*         r;
119
120         if( !RING_FAST ) {                                                              // compiler should drop the conditional when always false
121                 if( (r = (ring_t*) vr) == NULL ) {
122                         return 0;
123                 }
124         } else {
125                 r = (ring_t*) vr;
126         }
127
128         if( r->head+1 == r->tail || (r->head+1 >= r->nelements && !r->tail) ) {         // ring is full
129                 return 0;
130         }
131
132         r->data[r->head] = new_data;
133         r->head++;
134         if( r->head >= r->nelements ) {
135                 r->head = 0;
136         }
137
138         return 1;
139 }
140
141
142
143 #endif