All Downloads are FREE. Search and download functionalities are using the official Maven repository.

nextflow.util.LockManager.groovy Maven / Gradle / Ivy

Go to download

A DSL modelled around the UNIX pipe concept, that simplifies writing parallel and scalable pipelines in a portable manner

There is a newer version: 24.11.0-edge
Show newest version
/*
 * Copyright 2013-2024, Seqera Labs
 *
 * 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 nextflow.util

import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.locks.Lock
import java.util.concurrent.locks.ReentrantLock
import java.util.function.Function

import groovy.transform.CompileStatic
/**
 * A lock manager that allows the acquire of a lock on a unique key object
 *
 * @author Paolo Di Tommaso 
 */
@CompileStatic
class LockManager {

    private int MAX_SIZE = 200

    /**
     * Maintain a pool of lock handler to reduce garbage collection
     */
    private List pool = new ArrayList<>(MAX_SIZE)

    /**
     * Associate a lock handle for each key
     */
    private ConcurrentHashMap entries = new ConcurrentHashMap<>()


    /**
     * Acquire a lock. The lock needs to be released using the `release` method eg.
     *
     * def lock = lockManager.acquire(key)
     * try {
     *     // safe code
     * }
     * finally {
     *     lock.release()
     * }
     *
     * @param key A key object over which the lock needs to be acquired
     * @return The lock handler
     */
    LockHandle acquire(key) {
        LockHandle result = entries.computeIfAbsent(key,newLock())
        result.sync.lock()
        result.count++
        return result
    }

    private Function newLock() {
        new Function() {
            @Override
            LockHandle apply(Object key) {
                return getOrCreate0(key)
            }
        }
    }


    private synchronized LockHandle getOrCreate0(key) {
        if( pool.size() ) {
            def handle = pool.remove(pool.size()-1)
            handle.key = key
            return handle
        }
        new LockHandle(key)
    }

    private synchronized void release0(LockHandle handle) {
        entries.remove(handle.key)
        handle.key = null
        if( pool.size()




© 2015 - 2025 Weber Informatics LLC | Privacy Policy