<commit_before>package org.threadly.concurrent.lock;

import java.util.concurrent.atomic.AtomicReferenceArray;

import org.threadly.util.ArgumentVerifier;

/**
 * This structure allows for more controlled levels of parallelism.  It helps in allowing threads 
 * to only lock when their interest are the same.  It is guaranteed that every key provided will 
 * return the same lock.  But it is not guaranteed that two different keys will not have the same 
 * lock.
 * <p>
 * Currently this class only provides objects that should be synchronized on.  Compared to 
 * {@link java.util.concurrent.locks.Lock} objects which have {@code lock()}, {@code tryLock()}, 
 * and {@code unlock()} functionality.  This choice was primarily because of the way the internals 
 * of threadly work.
 * 
 * @since 1.0.0
 */
public class StripedLock {
  private final int expectedConcurrencyLevel;
  private final AtomicReferenceArray<Object> locks;
  
  /**
   * Constructs a new {@link StripedLock} with a given expected concurrency level.  The higher the 
   * concurrency level, the less lock contention will exist, but more locks will have to be 
   * synchronized on and more memory will be used to store the locks.
   * 
   * @param expectedConcurrencyLevel expected level of parallelism
   */
  public StripedLock(int expectedConcurrencyLevel) {
    ArgumentVerifier.assertGreaterThanZero(expectedConcurrencyLevel, "expectedConcurrencyLevel");
    
    this.expectedConcurrencyLevel = expectedConcurrencyLevel;
    locks = new AtomicReferenceArray<>(expectedConcurrencyLevel);
  }
  
  /**
   * Getter for the expected concurrency level this class was constructed with.
   * 
   * @return the constructed level of concurrency
   */
  public int getExpectedConcurrencyLevel() {
    return expectedConcurrencyLevel;
  }
  
  /**
   * Call to get a lock object for a given key.
   * 
   * @param key to use {@code hashCode()} from to determine lock
   * @return consistent Object for a given key
   */
  public Object getLock(Object key) {
    if (key == null) {
      return getLock(0);
    } else {
      return getLock(key.hashCode());
    }
  }
  
  /**
   * Call to get a lock object for a given hash code.
   * 
   * @param hashCode to use to determine which lock to return
   * @return consistent Object for a given hash code
   */
  public Object getLock(int hashCode) {
    int lockIndex = Math.abs(hashCode) % expectedConcurrencyLevel;
    Object result = locks.get(lockIndex);
    if (result == null) {
      result = new Object();
      if(!locks.compareAndSet(lockIndex, null, result)) {
        result = locks.get(lockIndex);
      }
    }
    
    return result;
  }
}<commit_msg>Moved stripedLock to just a normal object array<commit_after>package org.threadly.concurrent.lock;

import org.threadly.util.ArgumentVerifier;

/**
 * This structure allows for more controlled levels of parallelism.  It helps in allowing threads 
 * to only lock when their interest are the same.  It is guaranteed that every key provided will 
 * return the same lock.  But it is not guaranteed that two different keys will not have the same 
 * lock.
 * <p>
 * Currently this class only provides objects that should be synchronized on.  Compared to 
 * {@link java.util.concurrent.locks.Lock} objects which have {@code lock()}, {@code tryLock()}, 
 * and {@code unlock()} functionality.  This choice was primarily because of the way the internals 
 * of threadly work.
 * 
 * @since 1.0.0
 */
public class StripedLock {
  private final Object[] locks;
  
  /**
   * Constructs a new {@link StripedLock} with a given expected concurrency level.  The higher the 
   * concurrency level, the less lock contention will exist, but more locks will have to be 
   * synchronized on and more memory will be used to store the locks.
   * 
   * @param expectedConcurrencyLevel expected level of parallelism
   */
  public StripedLock(int expectedConcurrencyLevel) {
    ArgumentVerifier.assertGreaterThanZero(expectedConcurrencyLevel, "expectedConcurrencyLevel");
    locks = new Object[expectedConcurrencyLevel];
    for(int i=0; i<expectedConcurrencyLevel; i++) {
      locks[i] = new Object();
    }
  }
  
  /**
   * Getter for the expected concurrency level this class was constructed with.
   * 
   * @return the constructed level of concurrency
   */
  public int getExpectedConcurrencyLevel() {
    return locks.length;
  }
  
  /**
   * Call to get a lock object for a given key.
   * 
   * @param key to use {@code hashCode()} from to determine lock
   * @return consistent Object for a given key
   */
  public Object getLock(Object key) {
    if (key == null) {
      return getLock(0);
    } else {
      return getLock(key.hashCode());
    }
  }
  
  /**
   * Call to get a lock object for a given hash code.
   * 
   * @param hashCode to use to determine which lock to return
   * @return consistent Object for a given hash code
   */
  public Object getLock(int hashCode) {
    return locks[Math.abs(hashCode) % locks.length];
  }
}
{'fraction_non_alphanumeric': 0.08223815213062526, 'fraction_numerical': 0.0017921146953405018, 'mean_word_length': 3.300513698630137, 'pattern_counts': {'":': 0, '<': 8, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2012400', 'n_tokens_mistral': 1399, 'n_tokens_neox': 1361, 'n_words': 549}