3 ==================================================================================
4 Copyright (c) 2019 Nokia
5 Copyright (c) 2018-2019 AT&T Intellectual Property.
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
11 http://www.apache.org/licenses/LICENSE-2.0
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 ==================================================================================
21 Mnemonic: ring_static.c
22 Abstract: Implements a ring of information (probably to act as a
24 Author: E. Scott Daniels
28 #ifndef _ring_static_c
29 #define _ring_static_c
38 #include <sys/eventfd.h>
40 #define RING_FAST 1 // when set we skip nil pointer checks on the ring pointer
43 This returns the ring's pollable file descriptor. If one does not exist, then
46 static int uta_ring_getpfd( void* vr ) {
49 if( !RING_FAST ) { // compiler should drop the conditional when always false
50 if( (r = (ring_t*) vr) == NULL ) {
58 r->pfd = eventfd( 0, EFD_SEMAPHORE | EFD_NONBLOCK );
67 static void* uta_mk_ring( int size ) {
71 if( size <= 0 || (r = (ring_t *) malloc( sizeof( *r ) )) == NULL ) {
75 r->head = r->tail = 0;
82 r->nelements = size; // because we always have an empty element when full
83 if( (r->data = (void **) malloc( sizeof( void** ) * (r->nelements + 1) )) == NULL ) {
88 memset( r->data, 0, sizeof( void** ) * r->nelements );
89 r->pfd = eventfd( 0, EFD_SEMAPHORE | EFD_NONBLOCK ); // in semaphore mode counter is maintained with each insert/extract
94 Ditch the ring. The caller is responsible for extracting any remaining
95 pointers and freeing them as needed.
97 static void uta_ring_free( void* vr ) {
100 if( (r = (ring_t*) vr) == NULL ) {
109 Pull the next data pointer from the ring; null if there isn't
110 anything to be pulled.
112 static inline void* uta_ring_extract( void* vr ) {
114 uint16_t ti; // real index in data
115 int64_t ctr; // pfd counter
117 if( !RING_FAST ) { // compiler should drop the conditional when always false
118 if( (r = (ring_t*) vr) == NULL ) {
125 if( r->tail == r->head ) { // empty ring
131 if( r->tail >= r->nelements ) {
135 read( r->pfd, &ctr, sizeof( ctr ) ); // when not in semaphore, this zeros the counter and value is meaningless
137 future -- investigate if it's possible only to set/clear when empty or going to empty
138 if( r->tail == r->head ) { // if this emptied the ring, turn off ready
145 Insert the pointer at the next open space in the ring.
146 Returns 1 if the inert was ok, and 0 if the ring is full.
148 static inline int uta_ring_insert( void* vr, void* new_data ) {
150 int64_t inc = 1; // used to set the counter in the pfd
152 if( !RING_FAST ) { // compiler should drop the conditional when always false
153 if( (r = (ring_t*) vr) == NULL ) {
160 if( r->head+1 == r->tail || (r->head+1 >= r->nelements && !r->tail) ) { // ring is full
164 write( r->pfd, &inc, sizeof( inc ) );
166 future -- investigate if it's possible only to set/clear when empty or going to empty
167 if( r->tail == r->head ) { // turn on ready if ring was empty
171 r->data[r->head] = new_data;
173 if( r->head >= r->nelements ) {