ChronicleMap WriteContext用法

时间:2015-05-26 22:59:39

标签: chronicle chronicle-map

查看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);
        }
    }

1 个答案:

答案 0 :(得分:0)

说实话,解析你的问题真的很难。

其中一个是向地图添加条目(如果不存在)。
  

只有先前地图中没有给定键的值时才能进行另一个。

我不明白其中的区别。对我来说,这些句子是同义的。

  

WriteContext.value()引用什么?上一个条目的值,或者我在对acquireUsingLocked()的调用中提供的可能更新的值?

writeContext.value()始终与您在示例中提供给==方法acquireUsingLocked()的值相同(newValue)。如果不可行,则抛出一些RuntimeException

  

此外,如果之前没有地图中的条目,并且我不想更新地图,我应该调用WriteContext.removeEntry()还是WriteContext.dontPutOnClose()?

WriteContext.removeEntry(),因为在acquireUsingLocked()返回时,该条目已经放入地图中。

ChronicleMap中的方法acquireUsingLocked(),版本2.x适用于两种类型的值:data value generatedCharSequence,来自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.