-
Notifications
You must be signed in to change notification settings - Fork 918
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ARTEMIS-856 - Support consumersBeforeDispatch and delayBeforeDispatch #2175
Closed
Closed
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
154 changes: 154 additions & 0 deletions
154
...is-commons/src/main/java/org/apache/activemq/artemis/utils/AtomicBooleanFieldUpdater.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,154 @@ | ||
/* | ||
* Licensed to the Apache Software Foundation (ASF) under one or more | ||
* contributor license agreements. See the NOTICE file distributed with | ||
* this work for additional information regarding copyright ownership. | ||
* The ASF licenses this file to You under the Apache License, Version 2.0 | ||
* (the "License"); you may not use this file except in compliance with | ||
* the License. You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
package org.apache.activemq.artemis.utils; | ||
|
||
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; | ||
import sun.reflect.CallerSensitive; | ||
|
||
public class AtomicBooleanFieldUpdater<T> { | ||
|
||
/** | ||
* Creates and returns an updater for objects with the given field. | ||
* The Class argument is needed to check that reflective types and | ||
* generic types match. | ||
* | ||
* @param tclass the class of the objects holding the field | ||
* @param fieldName the name of the field to be updated | ||
* @param <U> the type of instances of tclass | ||
* @return the updater | ||
* @throws IllegalArgumentException if the field is not a | ||
* volatile long type | ||
* @throws RuntimeException with a nested reflection-based | ||
* exception if the class does not hold field or is the wrong type, | ||
* or the field is inaccessible to the caller according to Java language | ||
* access control | ||
*/ | ||
@CallerSensitive | ||
public static <U> AtomicBooleanFieldUpdater<U> newUpdater(Class<U> tclass, String fieldName) { | ||
return new AtomicBooleanFieldUpdater<>(AtomicIntegerFieldUpdater.newUpdater(tclass, fieldName)); | ||
} | ||
|
||
private static int toInt(boolean value) { | ||
return value ? 1 : 0; | ||
} | ||
|
||
private static boolean toBoolean(int value) { | ||
return value != 0; | ||
} | ||
|
||
private final AtomicIntegerFieldUpdater<T> atomicIntegerFieldUpdater; | ||
|
||
/** | ||
* Protected do-nothing constructor for use by subclasses. | ||
*/ | ||
protected AtomicBooleanFieldUpdater(AtomicIntegerFieldUpdater<T> atomicIntegerFieldUpdater) { | ||
this.atomicIntegerFieldUpdater = atomicIntegerFieldUpdater; | ||
} | ||
|
||
/** | ||
* Atomically sets the field of the given object managed by this updater | ||
* to the given updated value if the current value {@code ==} the | ||
* expected value. This method is guaranteed to be atomic with respect to | ||
* other calls to {@code compareAndSet} and {@code set}, but not | ||
* necessarily with respect to other changes in the field. | ||
* | ||
* @param obj An object whose field to conditionally set | ||
* @param expect the expected value | ||
* @param update the new value | ||
* @return {@code true} if successful | ||
* @throws ClassCastException if {@code obj} is not an instance | ||
* of the class possessing the field established in the constructor | ||
*/ | ||
public boolean compareAndSet(T obj, boolean expect, boolean update) { | ||
return atomicIntegerFieldUpdater.compareAndSet(obj, toInt(expect), toInt(update)); | ||
} | ||
|
||
|
||
|
||
/** | ||
* Atomically sets the field of the given object managed by this updater | ||
* to the given updated value if the current value {@code ==} the | ||
* expected value. This method is guaranteed to be atomic with respect to | ||
* other calls to {@code compareAndSet} and {@code set}, but not | ||
* necessarily with respect to other changes in the field. | ||
* | ||
* <p><a href="package-summary.html#weakCompareAndSet">May fail | ||
* spuriously and does not provide ordering guarantees</a>, so is | ||
* only rarely an appropriate alternative to {@code compareAndSet}. | ||
* | ||
* @param obj An object whose field to conditionally set | ||
* @param expect the expected value | ||
* @param update the new value | ||
* @return {@code true} if successful | ||
* @throws ClassCastException if {@code obj} is not an instance | ||
* of the class possessing the field established in the constructor | ||
*/ | ||
public boolean weakCompareAndSet(T obj, boolean expect, boolean update) { | ||
return atomicIntegerFieldUpdater.weakCompareAndSet(obj, toInt(expect), toInt(update)); | ||
} | ||
|
||
/** | ||
* Sets the field of the given object managed by this updater to the | ||
* given updated value. This operation is guaranteed to act as a volatile | ||
* store with respect to subsequent invocations of {@code compareAndSet}. | ||
* | ||
* @param obj An object whose field to set | ||
* @param newValue the new value | ||
*/ | ||
public void set(T obj, boolean newValue) { | ||
atomicIntegerFieldUpdater.set(obj, toInt(newValue)); | ||
} | ||
|
||
/** | ||
* Eventually sets the field of the given object managed by this | ||
* updater to the given updated value. | ||
* | ||
* @param obj An object whose field to set | ||
* @param newValue the new value | ||
* @since 1.6 | ||
*/ | ||
public void lazySet(T obj, boolean newValue) { | ||
atomicIntegerFieldUpdater.lazySet(obj, toInt(newValue)); | ||
} | ||
|
||
/** | ||
* Gets the current value held in the field of the given object managed | ||
* by this updater. | ||
* | ||
* @param obj An object whose field to get | ||
* @return the current value | ||
*/ | ||
public boolean get(T obj) { | ||
return toBoolean(atomicIntegerFieldUpdater.get(obj)); | ||
} | ||
|
||
/** | ||
* Atomically sets the field of the given object managed by this updater | ||
* to the given value and returns the old value. | ||
* | ||
* @param obj An object whose field to get and set | ||
* @param newValue the new value | ||
* @return the previous value | ||
*/ | ||
public boolean getAndSet(T obj, boolean newValue) { | ||
return toBoolean(atomicIntegerFieldUpdater.getAndSet(obj, toInt(newValue))); | ||
} | ||
|
||
public String toString(T obj) { | ||
return Boolean.toString(get(obj)); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know that is a sad that JDK isn't providing this class with a native implementation, but I would use directly
AtomicIntegerFiledUpdater
orAtomicReferenceFieldUpdater
withBoolean
values instead.The reason is that there is an implicit behaviour of any
SomethingFiledUpdater
that can't be enforced here: the declaration of avolatile Something
.Instead, the real purpose of this class is to treat integer values like boolean ones so I suppose that using a plain statitc util class to convert boolean<->integer will make it simple while avoiding to provide a more complex concurrent util class.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@franz1981 isn't that too much nit picking? :)
I like the work as is.. as anything in life.. it can always be improved.. but the excellent is the enemy of the very good :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@franz1981 using Boolean you might as well then just use atomic boolean, which you commented eadlier on and rightly so to use atomic updater. As the point is to save having object reference overheads.
The point of the class is just to make it reusable if else where you want else you end up with lots of dupe code just for all the int to bool logic.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree about the reasons but given that the JVM doesn't trust final fields you won't get the same performance you would have just using the int updater. Given that, I suppose that everything that let it works is ok for me: the PR is well done as always :)