]> pd.if.org Git - liblfds/blob - liblfds/liblfds7.1.0/liblfds710/src/lfds710_queue_bounded_manyproducer_manyconsumer/lfds710_queue_bounded_manyproducer_manyconsumer_dequeue.c
Initial import (all versions, including the new 7.1.0)
[liblfds] / liblfds / liblfds7.1.0 / liblfds710 / src / lfds710_queue_bounded_manyproducer_manyconsumer / lfds710_queue_bounded_manyproducer_manyconsumer_dequeue.c
1 /***** includes *****/
2 #include "lfds710_queue_bounded_manyproducer_manyconsumer_internal.h"
3
4
5
6
7
8 /****************************************************************************/
9 int lfds710_queue_bmm_dequeue( struct lfds710_queue_bmm_state *qbmms,
10                                void **key,
11                                void **value )
12 {
13   char unsigned
14     result;
15
16   enum lfds710_misc_flag
17     finished_flag = LFDS710_MISC_FLAG_LOWERED;
18
19   int
20     rv = 1;
21
22   lfds710_pal_uint_t
23     read_index,
24     sequence_number;
25
26   lfds710_pal_int_t
27     difference;
28
29   lfds710_pal_uint_t
30     backoff_iteration = LFDS710_BACKOFF_INITIAL_VALUE;
31
32   struct lfds710_queue_bmm_element
33     *qbmme = NULL;
34
35   LFDS710_PAL_ASSERT( qbmms != NULL );
36   // TRD : key can be NULL
37   // TRD : value can be NULL
38
39   LFDS710_MISC_BARRIER_LOAD;
40
41   read_index = qbmms->read_index;
42
43   while( finished_flag == LFDS710_MISC_FLAG_LOWERED )
44   {
45     qbmme = &qbmms->element_array[ read_index & qbmms->mask ];
46     LFDS710_MISC_BARRIER_LOAD;
47     sequence_number = qbmme->sequence_number;
48     difference = (lfds710_pal_int_t) sequence_number - (lfds710_pal_int_t) (read_index + 1);
49
50     if( difference == 0 )
51     {
52       LFDS710_PAL_ATOMIC_CAS( &qbmms->read_index, &read_index, read_index + 1, LFDS710_MISC_CAS_STRENGTH_WEAK, result );
53       if( result == 0 )
54         LFDS710_BACKOFF_EXPONENTIAL_BACKOFF( qbmms->dequeue_backoff, backoff_iteration );
55       if( result == 1 )
56         finished_flag = LFDS710_MISC_FLAG_RAISED;
57     }
58
59     if( difference < 0 )
60     {
61       rv = 0;
62       finished_flag = LFDS710_MISC_FLAG_RAISED;
63     }
64
65     if( difference > 0 )
66     {
67       LFDS710_MISC_BARRIER_LOAD;
68       read_index = qbmms->read_index;
69     }
70   }
71
72   if( rv == 1 )
73   {
74     if( key != NULL )
75       *key = qbmme->key;
76     if( value != NULL )
77       *value = qbmme->value;
78     LFDS710_MISC_BARRIER_STORE;
79     qbmme->sequence_number = read_index + qbmms->mask + 1;
80   }
81
82   LFDS710_BACKOFF_AUTOTUNE( qbmms->dequeue_backoff, backoff_iteration );
83
84   return rv;
85 }
86