0

ChronicleMap (2.1.7) を調べると、 acquireUsingLocked(); を呼び出すときの WriteContext の適切な使用法について正確にはわかりません。

私が興味を持っているシナリオは、関数呼び出し元の観点からアトミックに 2 つのアクションを実行する必要がある関数です。それらの 1 つは、存在しない場合、マップにエントリを追加することです。もう 1 つは、マップ内の指定されたキーの値が以前になかった場合にのみ実行されます。

マップ内の特定のキーに対する値が以前になく、この 2 番目のアクションが失敗した場合、後続のテストで対応するキーの値が見つからないように、マップを更新しないでください。

指定されたキーのマップに既にエントリがあった場合、元の値を更新したくなく、この 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

正直なところ、あなたの質問を解析するのは本当に難しいです。

それらの 1 つは、存在しない場合、マップにエントリを追加することです。

もう 1 つは、指定されたキーの値がマップ内に以前に存在しなかった場合にのみ実行されます。

違いがわかりません。私にとって、これらの文は同義語です。


WriteContext.value() は何を参照していますか? 前のエントリの値か、acquireUsingLocked() への呼び出しで提供した潜在的に更新された値?

writeContext.value()あなたの例では、メソッドに==提供した値と常に同じです( ) 。実行できない場合は、一部がスローされます。acquireUsingLocked()newValueRuntimeException

また、以前にマップにエントリがなく、マップを更新したくない場合は、WriteContext.removeEntry() または WriteContext.dontPutOnClose() を呼び出す必要がありますか?

WriteContext.removeEntry()acquireUsingLocked()戻るまでに、エントリはすでにマップに配置されているためです。


ChronicleMap バージョン 2.x のメソッドは、生成されたデータ値と経由acquireUsingLocked()の の 2 種類の値に合わせて調整されています。CharSequenceStringBuilder

データ値生成インターフェイスは、オフヒープ メモリへのポインタです。マップにキーのエントリがなかったときに呼び出された場合acquireUsingLocked()、新しいエントリが作成され、0 バイトで埋められ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値が長さ 0 に設定されます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 に答える