From 438ec370958c3b954ab0ef482c147ea5328d6277 Mon Sep 17 00:00:00 2001 From: jaysunxiao Date: Mon, 23 Aug 2021 17:32:07 +0800 Subject: [PATCH] =?UTF-8?q?perf[orm]:=20=E5=9C=A8lpmap=E7=A7=8D=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0putIfAbsent?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lpmap/ConcurrentFileChannelHeapMap.java | 9 ++++ .../com/zfoo/orm/lpmap/ConcurrentHeapMap.java | 19 +++++++- .../main/java/com/zfoo/orm/lpmap/LpMap.java | 8 ++++ .../zfoo/orm/lpmap/ConcurrentHeapMapTest.java | 45 +++++++++++++++++++ 4 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 orm/src/test/java/com/zfoo/orm/lpmap/ConcurrentHeapMapTest.java diff --git a/orm/src/main/java/com/zfoo/orm/lpmap/ConcurrentFileChannelHeapMap.java b/orm/src/main/java/com/zfoo/orm/lpmap/ConcurrentFileChannelHeapMap.java index 2a3e93aa..937473fc 100644 --- a/orm/src/main/java/com/zfoo/orm/lpmap/ConcurrentFileChannelHeapMap.java +++ b/orm/src/main/java/com/zfoo/orm/lpmap/ConcurrentFileChannelHeapMap.java @@ -47,6 +47,15 @@ public class ConcurrentFileChannelHeapMap implements LpMap return concurrentHeapMap.put(key, value); } + @Override + public V putIfAbsent(long key, V packet) { + var previousValue = concurrentHeapMap.putIfAbsent(key, packet); + if (previousValue == null) { + previousValue = put(key, packet); + } + return previousValue; + } + @Override public V delete(long key) { fileChannelLock.lock(); diff --git a/orm/src/main/java/com/zfoo/orm/lpmap/ConcurrentHeapMap.java b/orm/src/main/java/com/zfoo/orm/lpmap/ConcurrentHeapMap.java index cf4b7851..83f28229 100644 --- a/orm/src/main/java/com/zfoo/orm/lpmap/ConcurrentHeapMap.java +++ b/orm/src/main/java/com/zfoo/orm/lpmap/ConcurrentHeapMap.java @@ -41,12 +41,29 @@ public class ConcurrentHeapMap implements LpMap { break; } - maxIndexAtomic.compareAndExchange(maxIndex, key); + maxIndexAtomic.compareAndSet(maxIndex, key); } return map.put(key, value); } + @Override + public V putIfAbsent(long key, V packet) { + var previousValue = map.putIfAbsent(key, packet); + if (previousValue == null) { + while (true) { + var maxIndex = maxIndexAtomic.get(); + + if (key <= maxIndex) { + break; + } + + maxIndexAtomic.compareAndSet(maxIndex, key); + } + } + return previousValue; + } + @Override public V delete(long key) { checkKey(key); diff --git a/orm/src/main/java/com/zfoo/orm/lpmap/LpMap.java b/orm/src/main/java/com/zfoo/orm/lpmap/LpMap.java index e48bcf9a..fc08c353 100644 --- a/orm/src/main/java/com/zfoo/orm/lpmap/LpMap.java +++ b/orm/src/main/java/com/zfoo/orm/lpmap/LpMap.java @@ -31,6 +31,14 @@ public interface LpMap { */ V put(long key, V packet); + default V putIfAbsent(long key, V packet) { + var v = get(key); + if (v == null) { + v = put(key, packet); + } + return v; + } + /** * @return 返回被删除的那个值 */ diff --git a/orm/src/test/java/com/zfoo/orm/lpmap/ConcurrentHeapMapTest.java b/orm/src/test/java/com/zfoo/orm/lpmap/ConcurrentHeapMapTest.java new file mode 100644 index 00000000..4617c6ad --- /dev/null +++ b/orm/src/test/java/com/zfoo/orm/lpmap/ConcurrentHeapMapTest.java @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2020 The zfoo Authors + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and limitations under the License. + */ + +package com.zfoo.orm.lpmap; + +import com.zfoo.orm.lpmap.model.MyPacket; +import com.zfoo.protocol.ProtocolManager; +import org.junit.Assert; +import org.junit.Test; + +import java.util.Set; + +/** + * @author jaysunxiao + * @version 3.0 + */ +public class ConcurrentHeapMapTest { + + @Test + public void putIfAbsentTest() { + ProtocolManager.initProtocol(Set.of(MyPacket.class)); + var myPacket = new MyPacket(); + myPacket.setA(1); + + var map = new ConcurrentHeapMap(); + + var previous1 = map.put(1, myPacket); + var previous2 = map.put(2, myPacket); + var previous3 = map.put(2, new MyPacket()); + + Assert.assertNull(previous1); + Assert.assertNull(previous2); + Assert.assertEquals(previous3, myPacket); + } + +}