I often do something like this:
if (task != null && !task.IsCompleted && !task.IsCanceled && !task.IsFaulted)
{
// do something, e.g. cancel the task
}
It would be great to have task.IsPending as a shortcut for !task.IsCompleted && !task.IsCanceled && !task.IsFaulted, but it's not there. And task.Status == TaskStatus.Running is not the same, as task can be in one of the waiting states.
I have a custom Task extension method for this, but I'm curious why it is not there in the first place. Is checking for pending status this way considered somehow deprecated?
I think you're just looking for:
if (task != null && !task.IsCompleted)
As documented, IsCompleted covers faulted and canceled states as well as RanToCompletion:
IsCompleted will return true when the task is in one of the three final states: RanToCompletion, Faulted, or Canceled.
Related
I'm trying to implement a "search as you type" pattern in Java.
The goal of the design is that no change gets lost but at the same time, the (time consuming) search operation should be able to abort early and try with the updated pattern.
Here is what I've come up so far (Java 8 pseudocode):
AtomicReference<String> patternRef
AtomicLong modificationCount
ReentrantLock busy;
Consumer<List<ResultType>> resultConsumer;
// This is called in a background thread every time the user presses a key
void search(String pattern) {
// Update the pattern
synchronized {
patternRef.set(pattern)
modificationCount.inc()
}
try {
if (!busy.tryLock()) {
// Another search is already running, let it handle the change
return;
}
// Get local copy of the pattern and modCount
synchronized {
String patternCopy = patternRef.get();
long modCount = modificationCount.get()
}
while (true) {
// Try the search. It will return false when modificationCount changes before the search is finished
boolean success = doSearch(patternCopy, modCount)
if (success) {
// Search completed before modCount was changed again
break
}
// Try again with new pattern+modCount
synchronized {
patternCopy = patternRef.get();
modCount = modificationCount.get()
}
}
} finally {
busy.unlock();
}
}
boolean doSearch(String pattern, long modCount)
... search database ...
if (modCount != modificationCount.get()) {
return false;
}
... prepare results ...
if (modCount != modificationCount.get()) {
return false;
}
resultConsumer.accept(result); // Consumer for the UI code to do something
return modCount == modificationCount.get();
}
Did I miss some important point? A race condition or something similar?
Is there something in Java 8 which would make the code above more simple?
The fundamental problem of this code can be summarized as “trying to achieve atomicity by multiple distinct atomic constructs”. The combination of multiple atomic constructs is not atomic and trying to reestablish atomicity leads to very complicated, usually broken, and inefficient code.
In your case, doSearch’s last check modCount == modificationCount.get() happens while still holding the lock. After that, another thread (or multiple other threads) could update the search string and mod count, followed by finding the lock occupied, hence, concluding that another search is running and will take care.
But that thread doesn’t care after that last modCount == modificationCount.get() check. The caller just does if (success) { break; }, followed by the finally { busy.unlock(); } and returns.
So the answer is, yes, you have potential race conditions.
So, instead of settling on two atomic variables, synchronized blocks, and a ReentrantLock, you should use one atomic construct, e.g. a single atomic variable:
final AtomicReference<String> patternRef = new AtomicReference<>();
Consumer<List<ResultType>> resultConsumer;
// This is called in a background thread every time the user presses a key
void search(String pattern) {
if(patternRef.getAndSet(pattern) != null) return;
// Try the search. doSearch will return false when not completed
while(!doSearch(pattern) || !patternRef.compareAndSet(pattern, null))
pattern = patternRef.get();
}
boolean doSearch(String pattern) {
//... search database ...
if(pattern != (Object)patternRef.get()) {
return false;
}
//... prepare results ...
if(pattern != (Object)patternRef.get()) {
return false;
}
resultConsumer.accept(result); // Consumer for the UI code to do something
return true;
}
Here, a value of null indicates that no search is running, so if a background thread sets this to a non-null value and finds the old value to be null (in an atomic operation), it knows it has to perform the actual search. After the search, it tries to set the reference to null again, using compareAndSet with the pattern used for the search. Thus, it can only succeed if it has not changed again. Otherwise, it will fetch the new value and repeat.
These two atomic updates are already sufficient to ensure that there is only a single search operation at a time while not missing an updated search pattern. The ability of doSearch to return early when it detects a change, is just a nice to have and not required by the caller’s loop.
Note that in this example, the check within doSearch has been reduced to a reference comparison (using a cast to Object to prevent compiler warnings), to demonstrate that it can be as cheap as the int comparison of your original approach. As long as no new string has been set, the reference will be the same.
But, in fact, you could also use a string comparison, i.e. if(!pattern.equals(patternRef.get())) { return false; } without a significant performance degradation. String comparison is not (necessarily) expensive in Java. The first thing, the implementation of String’s equals does, is a reference comparison. So if the string has not changed, it will return true immediately here. Otherwise, it will check the lengths then (unlike C strings, the length is known beforehand) and return false immediately on a mismatch. So in the typical scenario of the user typing another character or pressing backspace, the lengths will differ and the comparison bail out immediately.
Say that I am using a Gradle plugin that defines task foo, which is up to date under a certain condition. Unfortunately, I don't have the source, so I don't know when it is.
I would like to make it so that foo is up to date if the original condition is true, and if a custom condition is also true.
I know I can add my custom condition like this:
foo.outputs.upToDateWhen {
return myCondition == true
}
But I want to be able to do something like this:
foo.outputs.upToDateWhen {
return super.upToDateWhen && myCondition == true
}
Is there any way to do what I am looking for? Can I add an up to date condition in such a way that I can have it preserve the original up to date condition?
What you describe is actually the default behaviour. The description of the upToDateWhen method in the docs is:
Adds a predicate to determine whether the outputs of this task are up-to-date. The given closure is executed at task execution time. The closure is passed the task as a parameter. If the closure returns false, the task outputs are considered out-of-date and the task will be executed.
You can add multiple such predicates. The task outputs are considered out-of-date when any predicate returns false.
I'm writing classes extending from XCTestCase to do some UI Automation tests. In my test base class I have something like:
- (BOOL)isOnLoginFormView
{
return self.app.textFields[#"User ID"] != nil && self.app.secureTextFields[#"Password"] != nil && self.app.buttons[#"<b>Login</b>"] != nil;
}
I use this method in another test case method. In a situation when the login form is not present it should continue with some other code (checking for the existence of another view) but my UI test fails in any case if the above method return NO. Is there anything I can do so the test is not failing if the above method returns NO? Optimally the test cases should only fail if I fail them explicitly with an assert.
Nevermind! I figured out it works with this:
return self.app.textFields[#"User ID"].exists && self.app.secureTextFields[#"Password"].exists && self.app.buttons[#"<b>Login</b>"].exists;
I have a jenkins plugin which contains code like this:
public int getLastBuildNumber() {
if (project != null && project.getLastBuild() != null ) {
return project.getLastBuild().getNumber();
}
return 0;
}
When I publish the code with mvn release:prepare release:perform -Dusername=myusername -Dpassword=mypassword, I got a bug saying Possible null pointer dereference.
Here's the result of mvn findbugs:gui:
Why does it say The return value from a method is dereferenced without a null check?
I think project != null && project.getLastBuild() != null is the null check, isn't it?
Is this a bug of findbugs? How can I solve it? Or can I disable findbugs when releasing my jenkins plugin?
You can visit here for the full code.
Unless your Project class is immutable or (at least) the value returned by getLastBuild() is a final field, your null-checks are not enough.
That's because, in theory, some other thread may call project.setLastBuild(null) just before your return statement:
if (project != null && project.getLastBuild() != null) {
// thread T does project.setLastBuild(null) here -- for whatever reason
return project.getLastBuild().getNumber(); // NPE!
}
To make this bullet proof, you need to move away from those moving parts and make your own local copies (synchronization is hardly an option in this case, imho):
LastBuild lastBuild = project != null ? project.getLastBuild() : null; // this only works as long as your project reference is final
return lastBuild != null ? lastBuild.getNumber() : 0;
Or, even better, make use of the Java8 Optional to perform all the necessary null-checks (implicitly) in one go:
return Optional.ofNullable(project)
.map(Project::getLastBuild)
.map(LastBuild::getNumber)
.orElse(0);
I have a problem with code contracts and linq. I managed to narrow the issue to the following code sample. And now I am stuck.
public void SomeMethod()
{
var list = new List<Question>();
if (list.Take(5) == null) { }
// resharper hints that condition can never be true
if (list.ForPerson(12) == null) { }
// resharper does not hint that condition can never be true
}
public static IQueryable<Question> ForPerson(this IQueryable<Question> source, int personId)
{
if(source == null) throw new ArgumentNullException();
return from q in source
where q.PersonId == personId
select q;
}
What is wrong with my linq chain? Why doesn't resharper 'complain' when analyzing the ForPerson call?
EDIT: return type for ForPerson method changed from string to IQueryable, which I meant. (my bad)
Reshaper is correct that the result of a Take or Skip is never null - if there are no items the result is an IEnumerable<Question> which has no elements. I think to do what you want you should check Any.
var query = list.Take(5);
if (!query.Any())
{
// Code here executes only if there were no items in the list.
}
But how does this warning work? Resharper cannot know that the method never returns null from only looking at the method definition, and I assume that it does not reverse engineer the method body to determine that it never returns null. I assume therefore that it has been specially hard-coded with a rule specifying that the .NET methods Skip and Take do not return null.
When you write your own custom methods Reflector can make assumptions about your method behaviour from the interface, but your interface allows it to return null. Therefore it issues no warnings. If it analyzed the method body then it could see that null is impossible and would be able to issue a warning. But analyzing code to determine its possible behaviour is an incredibly difficult task and I doubt that Red Gate are willing to spend the money on solving this problem when they could add more useful features elsewhere with a much lower development cost.
To determine whether a boolean expression can ever return true is called the Boolean satisfiability problem and is an NP-hard problem.
You want Resharper to determine whether general method bodies can ever return null. This is a generalization of the above mentioned NP-hard problem. It's unlikely any tool will ever be able to do this correctly in 100% of cases.
if(source == null) throw new ArgumentNullException();
That's not the code contract way, do you instead mean:
Contract.Require(source != null);