]> pd.if.org Git - liblfds/blob - liblfds/liblfds7.1.0/liblfds710/src/lfds710_queue_bounded_manyproducer_manyconsumer/lfds710_queue_bounded_manyproducer_manyconsumer_query.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_query.c
1 /***** includes *****/
2 #include "lfds710_queue_bounded_manyproducer_manyconsumer_internal.h"
3
4 /***** private prototypes *****/
5 static void lfds710_queue_bmm_internal_validate( struct lfds710_queue_bmm_state *qbmms,
6                                                  struct lfds710_misc_validation_info *vi,
7                                                  enum lfds710_misc_validity *lfds710_validity );
8
9
10
11
12
13 /****************************************************************************/
14 void lfds710_queue_bmm_query( struct lfds710_queue_bmm_state *qbmms,
15                               enum lfds710_queue_bmm_query query_type,
16                               void *query_input,
17                               void *query_output )
18 {
19   LFDS710_PAL_ASSERT( qbmms != NULL );
20   // TRD : query_type can be any value in its range
21
22   switch( query_type )
23   {
24     case LFDS710_QUEUE_BMM_QUERY_GET_POTENTIALLY_INACCURATE_COUNT:
25     {
26       lfds710_pal_uint_t
27         local_read_index,
28         local_write_index;
29
30       LFDS710_PAL_ASSERT( query_input == NULL );
31       LFDS710_PAL_ASSERT( query_output != NULL );
32
33       LFDS710_MISC_BARRIER_LOAD;
34
35       local_read_index = qbmms->read_index;
36       local_write_index = qbmms->write_index;
37
38       *(lfds710_pal_uint_t *) query_output = +( local_write_index - local_read_index );
39
40       if( local_read_index > local_write_index )
41         *(lfds710_pal_uint_t *) query_output = ((lfds710_pal_uint_t) -1) - *(lfds710_pal_uint_t *) query_output;
42     }
43     break;
44
45     case LFDS710_QUEUE_BMM_QUERY_SINGLETHREADED_VALIDATE:
46       // TRD : query_input can be NULL
47       LFDS710_PAL_ASSERT( query_output != NULL );
48
49       lfds710_queue_bmm_internal_validate( qbmms, (struct lfds710_misc_validation_info *) query_input, (enum lfds710_misc_validity *) query_output );
50     break;
51   }
52
53   return;
54 }
55
56
57
58
59
60 /****************************************************************************/
61 static void lfds710_queue_bmm_internal_validate( struct lfds710_queue_bmm_state *qbmms,
62                                                  struct lfds710_misc_validation_info *vi,
63                                                  enum lfds710_misc_validity *lfds710_validity )
64 {
65   lfds710_pal_uint_t
66     expected_sequence_number,
67     loop,
68     number_elements,
69     sequence_number;
70
71   LFDS710_PAL_ASSERT( qbmms != NULL );
72   // TRD : vi can be NULL
73   LFDS710_PAL_ASSERT( lfds710_validity != NULL );
74
75   *lfds710_validity = LFDS710_MISC_VALIDITY_VALID;
76
77   /* TRD : starting from the read_index, we should find number_elements of incrementing sequence numbers
78            we then perform a second scan from the write_index onwards, which should have (max elements in queue - number_elements) incrementing sequence numbers
79   */
80
81   lfds710_queue_bmm_query( qbmms, LFDS710_QUEUE_BMM_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void *) &number_elements );
82
83   expected_sequence_number = qbmms->element_array[ qbmms->read_index & qbmms->mask ].sequence_number;
84
85   for( loop = 0 ; loop < number_elements ; loop++ )
86   {
87     sequence_number = qbmms->element_array[ (qbmms->read_index + loop) & qbmms->mask ].sequence_number;
88
89     if( sequence_number != expected_sequence_number )
90       *lfds710_validity = LFDS710_MISC_VALIDITY_INVALID_ORDER;
91
92     if( sequence_number == expected_sequence_number )
93       expected_sequence_number = sequence_number + 1;
94   }
95
96   // TRD : now the write_index onwards
97
98   expected_sequence_number = qbmms->element_array[ qbmms->write_index & qbmms->mask ].sequence_number;
99
100   for( loop = 0 ; loop < qbmms->number_elements - number_elements ; loop++ )
101   {
102     sequence_number = qbmms->element_array[ (qbmms->write_index + loop) & qbmms->mask ].sequence_number;
103
104     if( sequence_number != expected_sequence_number )
105       *lfds710_validity = LFDS710_MISC_VALIDITY_INVALID_ORDER;
106
107     if( sequence_number == expected_sequence_number )
108       expected_sequence_number = sequence_number + 1;
109   }
110
111   // TRD : now check against the expected number of elements
112
113   if( *lfds710_validity == LFDS710_MISC_VALIDITY_VALID and vi != NULL )
114   {
115     lfds710_pal_uint_t
116       number_elements;
117
118     lfds710_queue_bmm_query( qbmms, LFDS710_QUEUE_BMM_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void *) &number_elements );
119
120     if( number_elements < vi->min_elements )
121       *lfds710_validity = LFDS710_MISC_VALIDITY_INVALID_MISSING_ELEMENTS;
122
123     if( number_elements > vi->max_elements )
124       *lfds710_validity = LFDS710_MISC_VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
125   }
126
127   return;
128 }
129