]> pd.if.org Git - liblfds/blob - liblfds/liblfds7.1.0/liblfds710/src/lfds710_queue_bounded_manyproducer_manyconsumer/lfds710_queue_bounded_manyproducer_manyconsumer_enqueue.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_enqueue.c
1 /***** includes *****/
2 #include "lfds710_queue_bounded_manyproducer_manyconsumer_internal.h"
3
4
5
6
7
8 /****************************************************************************/
9 int lfds710_queue_bmm_enqueue( 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     sequence_number,
24     write_index;
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   write_index = qbmms->write_index;
42
43   while( finished_flag == LFDS710_MISC_FLAG_LOWERED )
44   {
45     qbmme = &qbmms->element_array[ write_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) write_index;
49
50     if( difference == 0 )
51     {
52       LFDS710_PAL_ATOMIC_CAS( &qbmms->write_index, &write_index, write_index + 1, LFDS710_MISC_CAS_STRENGTH_WEAK, result );
53       if( result == 0 )
54         LFDS710_BACKOFF_EXPONENTIAL_BACKOFF( qbmms->enqueue_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       write_index = qbmms->write_index;
69     }
70   }
71
72   if( rv == 1 )
73   {
74     qbmme->key = key;
75     qbmme->value = value;
76     LFDS710_MISC_BARRIER_STORE;
77     qbmme->sequence_number = write_index + 1;
78   }
79
80   LFDS710_BACKOFF_AUTOTUNE( qbmms->enqueue_backoff, backoff_iteration );
81
82   return rv;
83 }
84