【问题标题】:ChronicleMap WriteContext usageChronicleMap WriteContext 用法
【发布时间】:2016-06-21 15:23:55
【问题描述】:

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

【问题讨论】:

    标签: chronicle chronicle-map


    【解决方案1】:

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

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

    只有当映射中的给定键之前没有值时,才应该发生另一个。

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


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

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

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

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


    ChronicleMap 2.x 版中的方法acquireUsingLocked() 针对两种类型的值进行了定制: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() 被调用,并且没有观察到键的值时,它会将空字符序列放入键并将给定的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.
    

    【讨论】:

      猜你喜欢
      • 2016-07-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-01
      • 2015-07-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多