0

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

1 回答 1

0

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

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

只有在地图中给定键之前没有值的情况下,才应该发生另一个。

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


WriteContext.value() 指的是什么?上一个条目的值,还是我在调用 acquireUsingLocked() 时提供的可能更新的值?

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

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

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


ChronicleMap 2.x 版中的方法acquireUsingLocked()针对两种类型的值进行了定制:生成的数据值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()被调用并且没有观察到键的值时,它将空字符序列放入键并将给定StringBuilder值设置为零长度:sb.setLength(0)。您可以更新 内的值WriteContext,例如sb.append("Hello")。当WriteContext.close()被调用时(try-with-resources 块结束),该sb值被拾取并再次将查询键放入映射中。为了防止这种情况,您可以调用dontPutOnClose().


以上所有内容听起来都非常尴尬,因此Chronicle Map 3.x 引入了新的、连贯的“上下文”模式。它不会以任何方式隐式更新地图。

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.
于 2015-08-17T21:50:22.307 回答