Search in sources :

Example 6 with AtomicReferenceArray

use of java.util.concurrent.atomic.AtomicReferenceArray in project gocd by gocd.

the class ConcurrentHashMapV8 method internalCompute.

/** Implementation for compute */
@SuppressWarnings("unchecked")
private final Object internalCompute(K k, boolean onlyIfPresent, BiFun<? super K, ? super V, ? extends V> mf) {
    int h = spread(k.hashCode());
    Object val = null;
    int delta = 0;
    int count = 0;
    for (AtomicReferenceArray<Node> tab = table; ; ) {
        Node f;
        int i, fh;
        Object fk;
        if (tab == null)
            tab = initTable();
        else if ((f = tabAt(tab, i = (tab.length() - 1) & h)) == null) {
            if (onlyIfPresent)
                break;
            Node node = new Node(fh = h | LOCKED, k, null, null);
            if (casTabAt(tab, i, null, node)) {
                try {
                    count = 1;
                    if ((val = mf.apply(k, null)) != null) {
                        node.val = val;
                        delta = 1;
                    }
                } finally {
                    if (delta == 0)
                        setTabAt(tab, i, null);
                    if (!node.casHash(fh, h)) {
                        node.hash = h;
                        synchronized (node) {
                            node.notifyAll();
                        }
                        ;
                    }
                }
            }
            if (count != 0)
                break;
        } else if ((fh = f.hash) == MOVED) {
            if ((fk = f.key) instanceof TreeBin) {
                TreeBin t = (TreeBin) fk;
                t.acquire(0);
                try {
                    if (tabAt(tab, i) == f) {
                        count = 1;
                        TreeNode p = t.getTreeNode(h, k, t.root);
                        Object pv;
                        if (p == null) {
                            if (onlyIfPresent)
                                break;
                            pv = null;
                        } else
                            pv = p.val;
                        if ((val = mf.apply(k, (V) pv)) != null) {
                            if (p != null)
                                p.val = val;
                            else {
                                count = 2;
                                delta = 1;
                                t.putTreeNode(h, k, val);
                            }
                        } else if (p != null) {
                            delta = -1;
                            t.deleteTreeNode(p);
                        }
                    }
                } finally {
                    t.release(0);
                }
                if (count != 0)
                    break;
            } else
                tab = (AtomicReferenceArray<Node>) fk;
        } else if ((fh & LOCKED) != 0) {
            checkForResize();
            f.tryAwaitLock(tab, i);
        } else if (f.casHash(fh, fh | LOCKED)) {
            try {
                if (tabAt(tab, i) == f) {
                    count = 1;
                    for (Node e = f, pred = null; ; ++count) {
                        Object ek, ev;
                        if ((e.hash & HASH_BITS) == h && (ev = e.val) != null && ((ek = e.key) == k || k.equals(ek))) {
                            val = mf.apply(k, (V) ev);
                            if (val != null)
                                e.val = val;
                            else {
                                delta = -1;
                                Node en = e.next;
                                if (pred != null)
                                    pred.next = en;
                                else
                                    setTabAt(tab, i, en);
                            }
                            break;
                        }
                        pred = e;
                        if ((e = e.next) == null) {
                            if (!onlyIfPresent && (val = mf.apply(k, null)) != null) {
                                pred.next = new Node(h, k, val, null);
                                delta = 1;
                                if (count >= TREE_THRESHOLD)
                                    replaceWithTreeBin(tab, i, k);
                            }
                            break;
                        }
                    }
                }
            } finally {
                if (!f.casHash(fh | LOCKED, fh)) {
                    f.hash = fh;
                    synchronized (f) {
                        f.notifyAll();
                    }
                    ;
                }
            }
            if (count != 0) {
                if (tab.length() <= 64)
                    count = 2;
                break;
            }
        }
    }
    if (delta != 0) {
        counter.add((long) delta);
        if (count > 1)
            checkForResize();
    }
    return val;
}
Also used : AtomicReferenceArray(java.util.concurrent.atomic.AtomicReferenceArray) RubyObject(org.jruby.RubyObject) IRubyObject(org.jruby.runtime.builtin.IRubyObject)

Example 7 with AtomicReferenceArray

use of java.util.concurrent.atomic.AtomicReferenceArray in project gocd by gocd.

the class ConcurrentHashMapV8 method internalPutIfAbsent.

/** Implementation for putIfAbsent */
private final Object internalPutIfAbsent(Object k, Object v) {
    int h = spread(k.hashCode());
    int count = 0;
    for (AtomicReferenceArray<Node> tab = table; ; ) {
        int i;
        Node f;
        int fh;
        Object fk, fv;
        if (tab == null)
            tab = initTable();
        else if ((f = tabAt(tab, i = (tab.length() - 1) & h)) == null) {
            if (casTabAt(tab, i, null, new Node(h, k, v, null)))
                break;
        } else if ((fh = f.hash) == MOVED) {
            if ((fk = f.key) instanceof TreeBin) {
                TreeBin t = (TreeBin) fk;
                Object oldVal = null;
                t.acquire(0);
                try {
                    if (tabAt(tab, i) == f) {
                        count = 2;
                        TreeNode p = t.putTreeNode(h, k, v);
                        if (p != null)
                            oldVal = p.val;
                    }
                } finally {
                    t.release(0);
                }
                if (count != 0) {
                    if (oldVal != null)
                        return oldVal;
                    break;
                }
            } else
                tab = (AtomicReferenceArray<Node>) fk;
        } else if ((fh & HASH_BITS) == h && (fv = f.val) != null && ((fk = f.key) == k || k.equals(fk)))
            return fv;
        else {
            Node g = f.next;
            if (g != null) {
                // at least 2 nodes -- search and maybe resize
                for (Node e = g; ; ) {
                    Object ek, ev;
                    if ((e.hash & HASH_BITS) == h && (ev = e.val) != null && ((ek = e.key) == k || k.equals(ek)))
                        return ev;
                    if ((e = e.next) == null) {
                        checkForResize();
                        break;
                    }
                }
            }
            if (((fh = f.hash) & LOCKED) != 0) {
                checkForResize();
                f.tryAwaitLock(tab, i);
            } else if (tabAt(tab, i) == f && f.casHash(fh, fh | LOCKED)) {
                Object oldVal = null;
                try {
                    if (tabAt(tab, i) == f) {
                        count = 1;
                        for (Node e = f; ; ++count) {
                            Object ek, ev;
                            if ((e.hash & HASH_BITS) == h && (ev = e.val) != null && ((ek = e.key) == k || k.equals(ek))) {
                                oldVal = ev;
                                break;
                            }
                            Node last = e;
                            if ((e = e.next) == null) {
                                last.next = new Node(h, k, v, null);
                                if (count >= TREE_THRESHOLD)
                                    replaceWithTreeBin(tab, i, k);
                                break;
                            }
                        }
                    }
                } finally {
                    if (!f.casHash(fh | LOCKED, fh)) {
                        f.hash = fh;
                        synchronized (f) {
                            f.notifyAll();
                        }
                        ;
                    }
                }
                if (count != 0) {
                    if (oldVal != null)
                        return oldVal;
                    if (tab.length() <= 64)
                        count = 2;
                    break;
                }
            }
        }
    }
    counter.add(1L);
    if (count > 1)
        checkForResize();
    return null;
}
Also used : AtomicReferenceArray(java.util.concurrent.atomic.AtomicReferenceArray) RubyObject(org.jruby.RubyObject) IRubyObject(org.jruby.runtime.builtin.IRubyObject)

Example 8 with AtomicReferenceArray

use of java.util.concurrent.atomic.AtomicReferenceArray in project gocd by gocd.

the class ConcurrentHashMapV8 method internalMerge.

/** Implementation for merge */
@SuppressWarnings("unchecked")
private final Object internalMerge(K k, V v, BiFun<? super V, ? super V, ? extends V> mf) {
    int h = spread(k.hashCode());
    Object val = null;
    int delta = 0;
    int count = 0;
    for (AtomicReferenceArray<Node> tab = table; ; ) {
        int i;
        Node f;
        int fh;
        Object fk, fv;
        if (tab == null)
            tab = initTable();
        else if ((f = tabAt(tab, i = (tab.length() - 1) & h)) == null) {
            if (casTabAt(tab, i, null, new Node(h, k, v, null))) {
                delta = 1;
                val = v;
                break;
            }
        } else if ((fh = f.hash) == MOVED) {
            if ((fk = f.key) instanceof TreeBin) {
                TreeBin t = (TreeBin) fk;
                t.acquire(0);
                try {
                    if (tabAt(tab, i) == f) {
                        count = 1;
                        TreeNode p = t.getTreeNode(h, k, t.root);
                        val = (p == null) ? v : mf.apply((V) p.val, v);
                        if (val != null) {
                            if (p != null)
                                p.val = val;
                            else {
                                count = 2;
                                delta = 1;
                                t.putTreeNode(h, k, val);
                            }
                        } else if (p != null) {
                            delta = -1;
                            t.deleteTreeNode(p);
                        }
                    }
                } finally {
                    t.release(0);
                }
                if (count != 0)
                    break;
            } else
                tab = (AtomicReferenceArray<Node>) fk;
        } else if ((fh & LOCKED) != 0) {
            checkForResize();
            f.tryAwaitLock(tab, i);
        } else if (f.casHash(fh, fh | LOCKED)) {
            try {
                if (tabAt(tab, i) == f) {
                    count = 1;
                    for (Node e = f, pred = null; ; ++count) {
                        Object ek, ev;
                        if ((e.hash & HASH_BITS) == h && (ev = e.val) != null && ((ek = e.key) == k || k.equals(ek))) {
                            val = mf.apply((V) ev, v);
                            if (val != null)
                                e.val = val;
                            else {
                                delta = -1;
                                Node en = e.next;
                                if (pred != null)
                                    pred.next = en;
                                else
                                    setTabAt(tab, i, en);
                            }
                            break;
                        }
                        pred = e;
                        if ((e = e.next) == null) {
                            val = v;
                            pred.next = new Node(h, k, val, null);
                            delta = 1;
                            if (count >= TREE_THRESHOLD)
                                replaceWithTreeBin(tab, i, k);
                            break;
                        }
                    }
                }
            } finally {
                if (!f.casHash(fh | LOCKED, fh)) {
                    f.hash = fh;
                    synchronized (f) {
                        f.notifyAll();
                    }
                    ;
                }
            }
            if (count != 0) {
                if (tab.length() <= 64)
                    count = 2;
                break;
            }
        }
    }
    if (delta != 0) {
        counter.add((long) delta);
        if (count > 1)
            checkForResize();
    }
    return val;
}
Also used : AtomicReferenceArray(java.util.concurrent.atomic.AtomicReferenceArray) RubyObject(org.jruby.RubyObject) IRubyObject(org.jruby.runtime.builtin.IRubyObject)

Example 9 with AtomicReferenceArray

use of java.util.concurrent.atomic.AtomicReferenceArray in project guava by google.

the class CacheLoadingTest method doConcurrentGet.

/**
   * Test-helper method that performs {@code nThreads} concurrent calls to {@code cache.get(key)}
   * or {@code cache.getUnchecked(key)}, and returns a List containing each of the results. The
   * result for any given call to {@code cache.get} or {@code cache.getUnchecked} is the value
   * returned, or the exception thrown.
   *
   * <p>As we iterate from {@code 0} to {@code nThreads}, threads with an even index will call
   * {@code getUnchecked}, and threads with an odd index will call {@code get}. If the cache throws
   * exceptions, this difference may be visible in the returned List.
   */
private static <K> List<Object> doConcurrentGet(final LoadingCache<K, ?> cache, final K key, int nThreads, final CountDownLatch gettersStartedSignal) throws InterruptedException {
    final AtomicReferenceArray<Object> result = new AtomicReferenceArray<Object>(nThreads);
    final CountDownLatch gettersComplete = new CountDownLatch(nThreads);
    for (int i = 0; i < nThreads; i++) {
        final int index = i;
        Thread thread = new Thread(new Runnable() {

            @Override
            public void run() {
                gettersStartedSignal.countDown();
                Object value = null;
                try {
                    int mod = index % 3;
                    if (mod == 0) {
                        value = cache.get(key);
                    } else if (mod == 1) {
                        value = cache.getUnchecked(key);
                    } else {
                        cache.refresh(key);
                        value = cache.get(key);
                    }
                    result.set(index, value);
                } catch (Throwable t) {
                    result.set(index, t);
                }
                gettersComplete.countDown();
            }
        });
        thread.start();
        // (in startSignal.await()), and the others waiting for that thread's result.
        while (thread.isAlive() && thread.getState() != Thread.State.WAITING) {
            Thread.yield();
        }
    }
    gettersStartedSignal.countDown();
    gettersComplete.await();
    List<Object> resultList = Lists.newArrayListWithExpectedSize(nThreads);
    for (int i = 0; i < nThreads; i++) {
        resultList.add(result.get(i));
    }
    return resultList;
}
Also used : AtomicReferenceArray(java.util.concurrent.atomic.AtomicReferenceArray) CountDownLatch(java.util.concurrent.CountDownLatch) Thread.currentThread(java.lang.Thread.currentThread)

Example 10 with AtomicReferenceArray

use of java.util.concurrent.atomic.AtomicReferenceArray in project hazelcast by hazelcast.

the class ThreadsafeCombinerTest method github_issue_3625.

/**
     * Combiner creation is not threadsafe
     *
     * @throws Exception
     */
@Test
public void github_issue_3625() throws Exception {
    class TestCombinerFactory implements CombinerFactory {

        @Override
        public Combiner newCombiner(Object key) {
            return new Combiner() {

                @Override
                public void combine(Object value) {
                }

                @Override
                public Object finalizeChunk() {
                    return null;
                }
            };
        }
    }
    class CreationTask implements Runnable {

        private final CountDownLatch latchStart;

        private final CountDownLatch latchEnd;

        private final AtomicReferenceArray<Combiner> array;

        private final DefaultContext<Integer, Integer> defaultContext;

        private final int index;

        CreationTask(CountDownLatch latchStart, CountDownLatch latchEnd, AtomicReferenceArray<Combiner> array, DefaultContext<Integer, Integer> defaultContext, int index) {
            this.latchStart = latchStart;
            this.latchEnd = latchEnd;
            this.array = array;
            this.defaultContext = defaultContext;
            this.index = index;
        }

        @Override
        public void run() {
            try {
                latchStart.await();
                Combiner combiner = defaultContext.getOrCreateCombiner(1);
                array.set(index, combiner);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                latchEnd.countDown();
            }
        }
    }
    int threadCount = 20;
    AtomicReferenceArray<Combiner> combiners = new AtomicReferenceArray<Combiner>(threadCount);
    DefaultContext<Integer, Integer> context = new DefaultContext<Integer, Integer>(new TestCombinerFactory(), null);
    CountDownLatch latchStart = new CountDownLatch(1);
    CountDownLatch latchEnd = new CountDownLatch(threadCount);
    for (int i = 0; i < threadCount; i++) {
        Thread t = new Thread(new CreationTask(latchStart, latchEnd, combiners, context, i));
        t.start();
    }
    latchStart.countDown();
    latchEnd.await(1, TimeUnit.MINUTES);
    for (int i = 0; i < threadCount - 1; i++) {
        Combiner c1 = combiners.get(i);
        Combiner c2 = combiners.get(i + 1);
        assertTrue("Returned combiners are not identical: " + c1 + " -> " + c2, c1 == c2);
    }
}
Also used : Combiner(com.hazelcast.mapreduce.Combiner) CountDownLatch(java.util.concurrent.CountDownLatch) CombinerFactory(com.hazelcast.mapreduce.CombinerFactory) AtomicReferenceArray(java.util.concurrent.atomic.AtomicReferenceArray) QuickTest(com.hazelcast.test.annotation.QuickTest) Test(org.junit.Test)

Aggregations

AtomicReferenceArray (java.util.concurrent.atomic.AtomicReferenceArray)31 CountDownLatch (java.util.concurrent.CountDownLatch)13 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)9 AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)6 RubyObject (org.jruby.RubyObject)6 IRubyObject (org.jruby.runtime.builtin.IRubyObject)6 Config (com.hazelcast.config.Config)4 HazelcastInstance (com.hazelcast.core.HazelcastInstance)4 Random (java.util.Random)4 Test (org.junit.Test)4 Thread.currentThread (java.lang.Thread.currentThread)3 ExecutorService (java.util.concurrent.ExecutorService)3 JoinConfig (com.hazelcast.config.JoinConfig)2 MulticastConfig (com.hazelcast.config.MulticastConfig)2 NetworkConfig (com.hazelcast.config.NetworkConfig)2 TcpIpConfig (com.hazelcast.config.TcpIpConfig)2 IMap (com.hazelcast.core.IMap)2 TestHazelcastInstanceFactory (com.hazelcast.test.TestHazelcastInstanceFactory)2 QuickTest (com.hazelcast.test.annotation.QuickTest)2 ArrayList (java.util.ArrayList)2