diff --git a/.editorconfig b/.editorconfig index 922a7c2..ab3ba96 100644 --- a/.editorconfig +++ b/.editorconfig @@ -13,5 +13,5 @@ trim_trailing_whitespace = true [*.{md, markdown}] trim_trailing_whitespace = false -[*.{yml, yaml}] +[*.{json, toml, xml, yml, yaml}] indent_size = 2 diff --git a/.gitignore b/.gitignore index 36a1562..8c5948b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,10 +1,11 @@ * !*/ +!/.github/** +!/src/** + !/*.md !/.editorconfig -!/.github/** !/.gitignore !/LICENSE !/pom.xml -!/src/** diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..1b888b7 --- /dev/null +++ b/LICENSE @@ -0,0 +1,15 @@ +MIT License + +Copyright (c) 2021 nothub + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, +modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md index ac2d141..cdc5ded 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,12 @@ A tiny and fast pubsub implementation with priorities and canceling. Check the -[example](https://github.com/nothub/TinyEventBus/blob/master/src/test/java/cc/neckbeard/tinypubsub/example/Example.java) +[example](https://github.com/nothub/TinyEventBus/blob/master/src/test/java/cc/neckbeard/tinyeventbus/example/Example.java) for a usage snippet. --- -[benchmarks](https://github.com/nothub/TinyEventBus/tree/master/src/test/java/cc/neckbeard/tinypubsub/benchmark) ( +[benchmarks](https://github.com/nothub/TinyEventBus/tree/master/src/test/java/cc/neckbeard/tinyeventbus/benchmark) ( openjdk 8, xeon e3-1230 3.30ghz): ``` diff --git a/pom.xml b/pom.xml index 8e57350..06c3299 100644 --- a/pom.xml +++ b/pom.xml @@ -2,59 +2,89 @@ - 4.0.0 - - cc.neckbeard - TinyEventBus - 0.4.0 - - ${project.groupId}:${project.artifactId} - jar - - - 1.8 - ${java.version} - ${java.version} - UTF-8 - - - - clean test - - - org.apache.maven.plugins - maven-compiler-plugin - 3.8.1 - - ${java.version} - ${java.version} - - - - org.apache.maven.plugins - maven-surefire-plugin - 2.22.2 - - - - - - - org.jetbrains - annotations - 20.1.0 - - - net.jodah - typetools - 0.6.2 - - - org.junit.jupiter - junit-jupiter-engine - 5.7.1 - test - - + 4.0.0 + + cc.neckbeard + TinyEventBus + 0.4.1 + jar + + ${project.artifactId} + A tiny and fast pubsub implementation with priorities and canceling. + https://github.com/nothub/TinyEventBus + + + + MIT License + http://www.opensource.org/licenses/mit-license.php + + + + + + nothub + nothub@posteo.net + neckbeard.cc + https://neckbeard.cc/ + + + + + scm:git:git://github.com/nothub/TinyEventBus.git + scm:git:ssh://github.com/nothub/TinyEventBus.git + https://github.com/nothub/TinyEventBus + + + + 1.8 + ${java.version} + ${java.version} + UTF-8 + + + + clean test + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + ${java.version} + ${java.version} + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.22.2 + + + + + + + org.jetbrains + annotations + 20.1.0 + + + net.jodah + typetools + 0.6.2 + + + org.junit.jupiter + junit-jupiter-engine + 5.7.1 + test + + + net.jodah + concurrentunit + 0.4.6 + test + + diff --git a/src/main/java/cc/neckbeard/tinyeventbus/Sub.java b/src/main/java/cc/neckbeard/tinyeventbus/Sub.java index 79c1fdb..98b625d 100644 --- a/src/main/java/cc/neckbeard/tinyeventbus/Sub.java +++ b/src/main/java/cc/neckbeard/tinyeventbus/Sub.java @@ -18,7 +18,7 @@ public Sub(Consumer consumer, int prio) { } public Sub(int prio, Consumer consumer) { - this(consumer, 0); + this(consumer, prio); } public Sub(Consumer consumer) { diff --git a/src/test/java/cc/neckbeard/tinyeventbus/benchmark/DelBenchmark.java b/src/test/java/cc/neckbeard/tinyeventbus/benchmark/DelBenchmark.java deleted file mode 100644 index ce3ce52..0000000 --- a/src/test/java/cc/neckbeard/tinyeventbus/benchmark/DelBenchmark.java +++ /dev/null @@ -1,46 +0,0 @@ -package cc.neckbeard.tinyeventbus.benchmark; - -import cc.neckbeard.tinyeventbus.Bus; -import cc.neckbeard.tinyeventbus.Sub; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.parallel.Execution; -import org.junit.jupiter.api.parallel.ExecutionMode; - -import java.util.ArrayList; -import java.util.List; -import java.util.stream.IntStream; - -@Execution(ExecutionMode.SAME_THREAD) -public class DelBenchmark { - - private static final Bus bus = new Bus(); - - @Test - void benchmark() { - - System.out.println("del"); - - final int subs = 1_000; - System.out.println("subs: " + subs); - - List> listenerContainers = new ArrayList<>(); - - IntStream.range(0, subs).forEach(i -> listenerContainers.add(new Sub<>(0, s -> {}))); - - IntStream - .range(0, subs) - .forEach(i -> bus.reg(listenerContainers.get(i))); - - final long start = System.nanoTime(); - - IntStream - .range(0, subs) - .forEach(i -> bus.del(listenerContainers.get(i))); - - final long end = System.nanoTime() - start; - - System.out.printf("%,dns (%,dms)\n", end, end / 1000000); - - } - -} diff --git a/src/test/java/cc/neckbeard/tinyeventbus/benchmark/PubBenchmark.java b/src/test/java/cc/neckbeard/tinyeventbus/benchmark/PubBenchmark.java deleted file mode 100644 index 38694c2..0000000 --- a/src/test/java/cc/neckbeard/tinyeventbus/benchmark/PubBenchmark.java +++ /dev/null @@ -1,54 +0,0 @@ -package cc.neckbeard.tinyeventbus.benchmark; - -import cc.neckbeard.tinyeventbus.Bus; -import cc.neckbeard.tinyeventbus.Sub; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.parallel.Execution; -import org.junit.jupiter.api.parallel.ExecutionMode; - -import java.util.ArrayList; -import java.util.List; -import java.util.stream.IntStream; - -@Execution(ExecutionMode.SAME_THREAD) -public class PubBenchmark { - - private static final String event = ""; - - private static final Bus bus = new Bus(); - private static int hits = 0; - - @Test - void benchmark() { - - System.out.println("pub"); - - final int subs = 1_000; - final int pubs = 1_000; - System.out.println("subs: " + subs); - System.out.println("pubs: " + pubs); - - List> listenerContainers = new ArrayList<>(); - - IntStream.range(0, subs).forEach(i -> listenerContainers.add(new Sub<>(0, s -> hits++))); - - IntStream - .range(0, subs) - .forEach(i -> bus.reg(listenerContainers.get(i))); - - final long start = System.nanoTime(); - - IntStream - .range(0, pubs) - .forEach(i -> bus.pub(event)); - - final long end = System.nanoTime() - start; - - System.out.printf("%,dns (%,dms)\n", end, end / 1000000); - - Assertions.assertEquals(subs * pubs, hits); - - } - -} diff --git a/src/test/java/cc/neckbeard/tinyeventbus/benchmark/RegBenchmark.java b/src/test/java/cc/neckbeard/tinyeventbus/benchmark/RegBenchmark.java deleted file mode 100644 index bb9b922..0000000 --- a/src/test/java/cc/neckbeard/tinyeventbus/benchmark/RegBenchmark.java +++ /dev/null @@ -1,42 +0,0 @@ -package cc.neckbeard.tinyeventbus.benchmark; - -import cc.neckbeard.tinyeventbus.Bus; -import cc.neckbeard.tinyeventbus.Sub; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.parallel.Execution; -import org.junit.jupiter.api.parallel.ExecutionMode; - -import java.util.ArrayList; -import java.util.List; -import java.util.stream.IntStream; - -@Execution(ExecutionMode.SAME_THREAD) -public class RegBenchmark { - - private static final Bus bus = new Bus(); - - @Test - void benchmark() { - - System.out.println("reg"); - - final int subs = 1_000; - System.out.println("subs: " + subs); - - List> listenerContainers = new ArrayList<>(); - - IntStream.range(0, subs).forEach(i -> listenerContainers.add(new Sub<>(0, s -> {}))); - - final long start = System.nanoTime(); - - IntStream - .range(0, subs) - .forEach(i -> bus.reg(listenerContainers.get(i))); - - final long end = System.nanoTime() - start; - - System.out.printf("%,dns (%,dms)\n", end, end / 1000000); - - } - -} diff --git a/src/test/java/cc/neckbeard/tinyeventbus/tests/BenchmarkTests.java b/src/test/java/cc/neckbeard/tinyeventbus/tests/BenchmarkTests.java new file mode 100644 index 0000000..c7207c5 --- /dev/null +++ b/src/test/java/cc/neckbeard/tinyeventbus/tests/BenchmarkTests.java @@ -0,0 +1,132 @@ +package cc.neckbeard.tinyeventbus.tests; + +import cc.neckbeard.tinyeventbus.Bus; +import cc.neckbeard.tinyeventbus.Sub; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Order; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.parallel.Execution; +import org.junit.jupiter.api.parallel.ExecutionMode; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.IntStream; + +@Execution(ExecutionMode.SAME_THREAD) +public class BenchmarkTests { + + private static Bus bus = new Bus(); + private static int hits; + + void setUp() { + bus = new Bus(); + hits = 0; + System.gc(); + } + + @Test + void test_0_reg() { + reg(1_000); + reg(10_000); + } + + @Test + void test_1_del() { + del(1_000); + del(10_000); + } + + @Test + void test_2_pub() { + pub(1_000, 1_000); + pub(100, 10_000); + pub(10_000, 100); + } + + void reg(int subs) { + + setUp(); + + System.out.println("benchmark: bus.reg"); + + System.out.println("subs: " + subs); + + List> listenerContainers = new ArrayList<>(); + + IntStream.range(0, subs).forEach(i -> listenerContainers.add(new Sub<>(0, s -> { + }))); + + final long start = System.nanoTime(); + + IntStream + .range(0, subs) + .forEach(i -> bus.reg(listenerContainers.get(i))); + + final long end = System.nanoTime() - start; + + System.out.printf("%,dns (%,dms)\n", end, end / 1000000); + + } + + void del(int subs) { + + setUp(); + + System.out.println("benchmark: bus.del"); + + System.out.println("subs: " + subs); + + List> listenerContainers = new ArrayList<>(); + + IntStream.range(0, subs).forEach(i -> listenerContainers.add(new Sub<>(0, s -> { + }))); + + IntStream + .range(0, subs) + .forEach(i -> bus.reg(listenerContainers.get(i))); + + final long start = System.nanoTime(); + + IntStream + .range(0, subs) + .forEach(i -> bus.del(listenerContainers.get(i))); + + final long end = System.nanoTime() - start; + + System.out.printf("%,dns (%,dms)\n", end, end / 1000000); + + } + + void pub(int pubs, int subs) { + + setUp(); + + System.out.println("benchmark: bus.pub"); + + System.out.println("pubs: " + pubs); + System.out.println("subs: " + subs); + + List> listenerContainers = new ArrayList<>(); + + IntStream.range(0, subs).forEach(i -> listenerContainers.add(new Sub<>(0, s -> hits++))); + + IntStream + .range(0, subs) + .forEach(i -> bus.reg(listenerContainers.get(i))); + + final long start = System.nanoTime(); + + IntStream + .range(0, pubs) + .forEach(i -> bus.pub("")); + + final long end = System.nanoTime() - start; + + System.out.printf("%,dns (%,dms)\n", end, end / 1000000); + + Assertions.assertEquals(subs * pubs, hits); + + } + +} diff --git a/src/test/java/cc/neckbeard/tinyeventbus/tests/ConcurrencyTest.java b/src/test/java/cc/neckbeard/tinyeventbus/tests/ConcurrencyTest.java new file mode 100644 index 0000000..e18f646 --- /dev/null +++ b/src/test/java/cc/neckbeard/tinyeventbus/tests/ConcurrencyTest.java @@ -0,0 +1,56 @@ +package cc.neckbeard.tinyeventbus.tests; + +import cc.neckbeard.tinyeventbus.Bus; +import cc.neckbeard.tinyeventbus.Sub; +import net.jodah.concurrentunit.Waiter; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.parallel.Execution; +import org.junit.jupiter.api.parallel.ExecutionMode; + +import java.util.concurrent.TimeoutException; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.stream.IntStream; + +@Execution(ExecutionMode.CONCURRENT) +class ConcurrencyTest { + + private final Bus bus = new Bus(); + private final Waiter waiter = new Waiter(); + + private int hitsA = 0; + private int hitsB = 0; + private int hitsC = 0; + private int hitsD = 0; + + private final Sub sub = Sub.of(i -> { + waiter.assertEquals(i, hitsB); + hitsB++; + hitsD++; + waiter.assertTrue(hitsC < hitsD); + waiter.resume(); + }); + + @Test + void test() throws TimeoutException, InterruptedException { + bus.reg(sub); + IntStream.range(0, 1000).forEach(i -> { + bus.pub(hitsA); + hitsA++; + hitsC++; + }); + waiter.await(1000, 1000); + } + + @Test + void spam() { + AtomicBoolean invoked = new AtomicBoolean(false); + bus.reg(Sub.of(invoked::set)); + IntStream.range(0, 1000).forEach(i -> { + bus.pub(true); + Assertions.assertTrue(invoked.get()); + invoked.set(false); + }); + } + +} diff --git a/src/test/java/cc/neckbeard/tinyeventbus/tests/InstanceTests.java b/src/test/java/cc/neckbeard/tinyeventbus/tests/InstanceTests.java index acd81be..cd4feec 100644 --- a/src/test/java/cc/neckbeard/tinyeventbus/tests/InstanceTests.java +++ b/src/test/java/cc/neckbeard/tinyeventbus/tests/InstanceTests.java @@ -24,7 +24,6 @@ static void setUp() { } @Test - @Order(0) void reg() { bus.reg(sub); bus.pub(new BooleanEvent(true)); @@ -32,7 +31,6 @@ void reg() { } @Test - @Order(1) void del() { bus.del(sub); bus.pub(new BooleanEvent(true)); diff --git a/src/test/java/cc/neckbeard/tinyeventbus/tests/OrderTests.java b/src/test/java/cc/neckbeard/tinyeventbus/tests/OrderTest.java similarity index 98% rename from src/test/java/cc/neckbeard/tinyeventbus/tests/OrderTests.java rename to src/test/java/cc/neckbeard/tinyeventbus/tests/OrderTest.java index b4a3162..1e978b6 100644 --- a/src/test/java/cc/neckbeard/tinyeventbus/tests/OrderTests.java +++ b/src/test/java/cc/neckbeard/tinyeventbus/tests/OrderTest.java @@ -6,7 +6,7 @@ import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; -class OrderTests { +class OrderTest { private static Bus bus; private static String str; diff --git a/src/test/java/cc/neckbeard/tinyeventbus/tests/StaticTests.java b/src/test/java/cc/neckbeard/tinyeventbus/tests/StaticTests.java index 64c6b7c..c7be77a 100644 --- a/src/test/java/cc/neckbeard/tinyeventbus/tests/StaticTests.java +++ b/src/test/java/cc/neckbeard/tinyeventbus/tests/StaticTests.java @@ -24,7 +24,6 @@ static void setUp() { } @Test - @Order(0) void reg() { bus.reg(sub); bus.pub(new BooleanEvent(true)); @@ -32,7 +31,6 @@ void reg() { } @Test - @Order(1) void del() { bus.del(sub); bus.pub(new BooleanEvent(true));