1
1
/*
2
- * Copyright (c) 2015, 2019 , Oracle and/or its affiliates. All rights reserved.
2
+ * Copyright (c) 2015, 2020 , Oracle and/or its affiliates. All rights reserved.
3
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
4
*
5
5
* This code is free software; you can redistribute it and/or modify it
@@ -57,31 +57,23 @@ inline GenericTaskQueue<E, F, N>::~GenericTaskQueue() {
57
57
ArrayAllocator<E>::free (const_cast <E*>(_elems), N);
58
58
}
59
59
60
- template <class E , MEMFLAGS F, unsigned int N>
61
- bool GenericTaskQueue<E, F, N>::push_slow(E t, uint dirty_n_elems) {
62
- if (dirty_n_elems == N - 1 ) {
63
- // Actually means 0, so do the push.
64
- uint localBot = _bottom;
65
- // g++ complains if the volatile result of the assignment is
66
- // unused, so we cast the volatile away. We cannot cast directly
67
- // to void, because gcc treats that as not using the result of the
68
- // assignment. However, casting to E& means that we trigger an
69
- // unused-value warning. So, we cast the E& to void.
70
- (void )const_cast <E&>(_elems[localBot] = t);
71
- Atomic::release_store (&_bottom, increment_index (localBot));
72
- TASKQUEUE_STATS_ONLY (stats.record_push ());
73
- return true ;
74
- }
75
- return false ;
76
- }
77
-
78
60
template <class E , MEMFLAGS F, unsigned int N> inline bool
79
61
GenericTaskQueue<E, F, N>::push(E t) {
80
62
uint localBot = _bottom;
81
63
assert (localBot < N, " _bottom out of range." );
82
64
idx_t top = _age.top ();
83
65
uint dirty_n_elems = dirty_size (localBot, top);
84
- assert (dirty_n_elems < N, " n_elems out of range." );
66
+ // A dirty_size of N-1 cannot happen in push. Considering only push:
67
+ // (1) dirty_n_elems is initially 0.
68
+ // (2) push adds an element iff dirty_n_elems < max_elems(), which is N - 2.
69
+ // (3) only push adding an element can increase dirty_n_elems.
70
+ // => dirty_n_elems <= N - 2, by induction
71
+ // => dirty_n_elems < N - 1, invariant
72
+ //
73
+ // A pop_global that is concurrent with push cannot produce a state where
74
+ // dirty_size == N-1. pop_global only removes an element if dirty_elems > 0,
75
+ // so can't underflow to -1 (== N-1) with push.
76
+ assert (dirty_n_elems <= max_elems (), " n_elems out of range." );
85
77
if (dirty_n_elems < max_elems ()) {
86
78
// g++ complains if the volatile result of the assignment is
87
79
// unused, so we cast the volatile away. We cannot cast directly
@@ -92,9 +84,8 @@ GenericTaskQueue<E, F, N>::push(E t) {
92
84
Atomic::release_store (&_bottom, increment_index (localBot));
93
85
TASKQUEUE_STATS_ONLY (stats.record_push ());
94
86
return true ;
95
- } else {
96
- return push_slow (t, dirty_n_elems);
97
87
}
88
+ return false ; // Queue is full.
98
89
}
99
90
100
91
template <class E , MEMFLAGS F, unsigned int N>
0 commit comments