V put()

in bookkeeper-server/src/main/java/org/apache/bookkeeper/util/collections/ConcurrentLongHashMap.java [405:472]


        V put(long key, V value, int keyHash, boolean onlyIfAbsent, LongFunction<V> valueProvider) {
            int bucket = keyHash;

            long stamp = writeLock();
            int capacity = this.capacity;

            // Remember where we find the first available spot
            int firstDeletedKey = -1;

            try {
                while (true) {
                    bucket = signSafeMod(bucket, capacity);

                    long storedKey = keys[bucket];
                    V storedValue = values[bucket];

                    if (storedKey == key) {
                        if (storedValue == EmptyValue) {
                            values[bucket] = value != null ? value : valueProvider.apply(key);
                            ++size;
                            ++usedBuckets;
                            return valueProvider != null ? values[bucket] : null;
                        } else if (storedValue == DeletedValue) {
                            values[bucket] = value != null ? value : valueProvider.apply(key);
                            ++size;
                            return valueProvider != null ? values[bucket] : null;
                        } else if (!onlyIfAbsent) {
                            // Over written an old value for same key
                            values[bucket] = value;
                            return storedValue;
                        } else {
                            return storedValue;
                        }
                    } else if (storedValue == EmptyValue) {
                        // Found an empty bucket. This means the key is not in the map. If we've already seen a deleted
                        // key, we should write at that position
                        if (firstDeletedKey != -1) {
                            bucket = firstDeletedKey;
                        } else {
                            ++usedBuckets;
                        }

                        keys[bucket] = key;
                        values[bucket] = value != null ? value : valueProvider.apply(key);
                        ++size;
                        return valueProvider != null ? values[bucket] : null;
                    } else if (storedValue == DeletedValue) {
                        // The bucket contained a different deleted key
                        if (firstDeletedKey == -1) {
                            firstDeletedKey = bucket;
                        }
                    }

                    ++bucket;
                }
            } finally {
                if (usedBuckets > resizeThresholdUp) {
                    try {
                        int newCapacity = alignToPowerOfTwo((int) (capacity * expandFactor));
                        rehash(newCapacity);
                    } finally {
                        unlockWrite(stamp);
                    }
                } else {
                    unlockWrite(stamp);
                }
            }
        }