diff --git a/src/main/java/com/zaxxer/hikari/util/ConcurrentBag.java b/src/main/java/com/zaxxer/hikari/util/ConcurrentBag.java new file mode 100644 index 00000000..f9a72b3e --- /dev/null +++ b/src/main/java/com/zaxxer/hikari/util/ConcurrentBag.java @@ -0,0 +1,117 @@ +package com.zaxxer.hikari.util; + +import java.lang.reflect.Field; +import java.util.LinkedList; +import java.util.concurrent.locks.ReentrantLock; + +public class ConcurrentBag +{ + private static sun.misc.Unsafe unsafe = getUnsafe(); + + private LinkedList> sharedList; + + private ThreadLocal> threadList = new ThreadLocal>() { + protected java.util.LinkedList initialValue() + { + LinkedList list = new LinkedList(); + sharedList.add(list); + return list; + } + }; + + public ConcurrentBag() + { + sharedList = new LinkedList<>(); + } + + @SuppressWarnings("restriction") + private static sun.misc.Unsafe getUnsafe() + { + try + { + Field f = sun.misc.Unsafe.class.getDeclaredField("theUnsafe"); + f.setAccessible(true); + return (sun.misc.Unsafe) f.get(null); + } + catch (Exception e) + { + throw new RuntimeException("Cannot access sun.misc.Unsafe"); + } + } + + private static class SinglyLinkedList + { + private ReentrantLock putLock = new ReentrantLock(); + private ReentrantLock takeLock = new ReentrantLock(); + + Node head; + Node tail; + + void add(T value) + { + Node node = new Node(value); + final ReentrantLock putLock = this.putLock; + putLock.lock(); + try + { + if (head == null) + { + head = tail = node; + } + else + { + tail.next = node; + } + } + finally + { + putLock.unlock(); + } + } + + void remove(T value) + { + final ReentrantLock putLock = this.putLock; + final ReentrantLock takeLock = this.takeLock; + putLock.lock(); + takeLock.lock(); + try + { + Node node = head; + Node prev = null; + while (node != null) + { + if (node.value == value) + { + if (prev == null) + { + head = node; + } + else + { + prev.next = node.next; + } + break; + } + node = node.next; + } + } + finally + { + takeLock.unlock(); + putLock.unlock(); + } + } + } + + private static class Node + { + E value; + Node next; + + Node(E value) + { + this.value = value; + } + } +}