-
Notifications
You must be signed in to change notification settings - Fork 353
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
Support for taking over the ownership of the collection/array/vararg #6029
Comments
Unfortunately, no. This is a known limitation of the RLC; see further discussion here. |
@jacek-lewandowski we are actively brainstorming on how to add support for this. If you could link an example using an array of resources showing how they get closed it could be helpful to us. |
Also, for varargs, we do have the unchecked |
Thanks for the feedback! In Cassandra, indeed, we have methods that close multiple resources at once. For example, many of them are in the Thanks for pointing me to the discussion. I'll follow it. |
One nasty issue we need to think through here is mutation. Consider: class Closeables implements Closeable {
final @Owning Closeable[] res;
Closeables(@Owning Closeable... r) {
res = r;
}
void update(@Owning Closeable c, int i) {
// what should the verifier do about the old value in the array?
res[i] = c;
}
...
} Similar issues arise for mutable collections. Possibly we need to prohibit such mutation for collections / arrays of |
Maybe there could be an annotation which would mark a collection immutable? |
One option would be to trust rather than check an immutability annotation on collections, and let the RLC use that fact. Obviously, this is unsound, but it might be a good first step towards enabling us to verify ownership of resources by collections. |
So I was trying to implement a resources map to be used to such situations, I have this: @InheritableMustCall({ "removeAll" })
public class ResourcesMap<K, V>
{
private final Map<K, V> map;
public ResourcesMap()
{
this.map = new HashMap<>();
}
public @MustCallAlias V get(K key)
{
return map.get(key);
}
public @Owning V remove(K key)
{
return map.remove(key);
}
@CreatesMustCallFor
public @MustCallAlias V put(K key, @Owning V value)
{
return map.put(key, value);
}
public void forEach(Consumer<@MustCallAlias V> consumer)
{
map.values().forEach(consumer);
}
public <T> void removeAll(T initial, OwningBiFunction<T, V> consumer)
{
Iterator<V> iterator = map.values().iterator();
T acc = initial;
while (iterator.hasNext())
{
V value = iterator.next();
try
{
iterator.remove();
}
finally
{
acc = consumer.apply(acc, value);
}
}
}
public <T> void removeAll(OwningConsumer<V> consumer)
{
Iterator<V> iterator = map.values().iterator();
while (iterator.hasNext())
{
V value = iterator.next();
try
{
iterator.remove();
}
finally
{
consumer.accept(value);
}
}
}
public interface OwningConsumer<V> extends Consumer<V>
{
@Override
void accept(@Owning V v);
}
public interface OwningBiFunction<T, V> extends BiFunction<T, V, T>
{
@Override
T apply(T t, @Owning V v);
}
} which is used in the following way: ResourcesMap<TableId, UncommittedTableData.FlushWriter> flushWriters = new ResourcesMap<>();
try (CloseableIterator<PaxosKeyState> iterator = updateSupplier.flushIterator(paxos))
{
while (iterator.hasNext())
{
PaxosKeyState next = iterator.next();
UncommittedTableData.FlushWriter writer = flushWriters.get(next.tableId);
if (writer == null)
{
writer = getOrCreateTableState(next.tableId).flushWriter();
flushWriters.put(next.tableId, writer);
}
writer.append(next);
}
flushWriters.removeAll(UncommittedTableData.FlushWriter::finish);
}
catch (IOException t)
{
flushWriters.removeAll((Throwable) t, (acc, flushWriter) -> flushWriter.abort((acc)));
throw new IOException(t);
} where the @InheritableMustCall({ "finish", "abort" })
public interface FlushWriter
{
void append(PaxosKeyState commitState) throws IOException;
void finish();
Throwable abort(Throwable accumulate);
default void appendAll(Iterable<PaxosKeyState> states) throws IOException
{
for (PaxosKeyState state : states)
append(state);
}
} Now, when I try to check it, it complains with the following:
I'm not sure what I'm doing wrong there? |
@jacek-lewandowski this latest issue looks like a separate bug to me. I am not sure of the root cause. Could you file it as a distinct issue from this one? |
sure, will do |
A simple example is as follows:
For the resources obtained outside
this works:
this does not work:
Is there a way to take over the ownership each item of a vararg / array / collection?
The text was updated successfully, but these errors were encountered: