查看ChronicleMap(2.1.7),在调用acquireUsingLocked()时,我并不完全清楚WriteContext的正确用法;
我感兴趣的场景是一个函数,我需要从函数调用者的角度原子地执行2个动作。其中之一是在地图中添加条目(如果不存在)。只有先前地图中没有给定键的值时才能进行另一个。
如果地图中的给定键之前没有值,并且第二个操作失败,则不应更新地图,以便后续测试找不到相应键的值。
如果地图中已存在给定密钥的条目,我不想更新其原始值,我不想进行第二次操作。但是,我确实需要使用原始条目的值来构造调用者的返回值。
WriteContext.created()的文档说它只有在先前存在条目时才返回true。如果该条目先前存在,是否可以从上下文中获取对前一个值的引用(或者其他一些方式 - 比如在WriteContext范围内调用map.get())?
WriteContext.value()引用什么?上一个条目的值,或者我在对acquireUsingLocked()的调用中提供的可能更新的值?
另外,如果地图中以前没有条目,并且我不想更新地图,我应该调用WriteContext.removeEntry()还是WriteContext.dontPutOnClose()?
以下是我认为需要的逻辑示例:
EntryData newValue = new EntryData();
EntryData originalValue = null;
try (WriteContext<String, EntryData> context = _map.acquireUsingLocked(key, newValue) ) {
if ( !context.created() ) {
if ( doSomething() ) {
result = createResult(newValue);
}
else {
context.removeEntry();
result = null;
}
}
else {
context.dontPutOnClose();
originalValue = context.value();
result = createResult(originalValue);
}
}
答案 0 :(得分:0)
说实话,解析你的问题真的很难。
其中一个是向地图添加条目(如果不存在)。
只有先前地图中没有给定键的值时才能进行另一个。
我不明白其中的区别。对我来说,这些句子是同义的。
WriteContext.value()引用什么?上一个条目的值,或者我在对acquireUsingLocked()的调用中提供的可能更新的值?
writeContext.value()
始终与您在示例中提供给==
方法acquireUsingLocked()
的值相同(newValue
)。如果不可行,则抛出一些RuntimeException
。
此外,如果之前没有地图中的条目,并且我不想更新地图,我应该调用WriteContext.removeEntry()还是WriteContext.dontPutOnClose()?
WriteContext.removeEntry()
,因为在acquireUsingLocked()
返回时,该条目已经放入地图中。
ChronicleMap中的方法acquireUsingLocked()
,版本2.x适用于两种类型的值:data value generated和CharSequence
,来自StringBuilder
。
数据值生成接口是指向堆外内存的指针。如果在映射中没有键的条目时调用acquireUsingLocked()
,则会创建一个新条目,填充零字节,usingValue
指向已存储在映射中的堆外字节:
try (WriteContext<K, LongValue> wc = map.acquireUsingLocked(k, value)) {
// update off-heap bytes, already serving as a value for the key
// now: k -> LongValue { 0 }
value.setValue(42);
// now: k -> LongValue { 42 }
}
在CharSequence
值的情况下,当调用acquireUsingLocked()
并且没有注意到键的值时,它会将空char序列放入键中并将给定的StringBuilder
值设置为零长度:sb.setLength(0)
。您可以更新WriteContext
中的值,例如sb.append("Hello")
。调用WriteContext.close()
时(尝试使用资源块结束),将再次选取此sb
值并将查询的密钥放入映射中。为防止这种情况发生,您可以致电dontPutOnClose()
。
以上所有听起来都很尴尬,所以 Chronicle Map 3.x引入了新的,连贯的&#34;背景&#34;图案即可。它不会以任何方式隐式更新地图。
try (ExternalMapQueryContext<K, V, ?> cxt = map.queryContext(key)) {
cxt.writeLock().lock();
MapEntry<K, V> entry = map.entry();
if (entry != null) {
// entry is already present in the map.
map.value.get(); // access the _previous_ value;
// value is not updated until you call:
cxt.replaceValue(entry, cxt.wrapValueAsData(newValue));
// or remove:
cxt.remove(entry);
} else {
// entry is absent.
// can insert a value using:
cxt.insert(cxt.absentEntry(), cxt.wrapValueAsData(newValue));
}
}
// no implicit inserts, removes, updates.