/** * Execute a callable acquiring a unique lock (mutex) for a given {@link HashId}. Locks is released upon callable * return. * * @param id ot get a lock to * @param callable lamda to execute exclusively for the id * @param <T> is type * * @return whatever the callable returns * * @throws Exception whatever callable throws */ public <T> T synchronize(HashId id, Function<Object, T> callable) throws Exception { ItemLock lock = null; // short exclusive mutex: obtaning a lock synchronized (monitors) { lock = monitors.get(id); if (lock == null) { lock = new ItemLock(); monitors.put(id, lock); } } // now we only lock the item: synchronized (lock) { return (T) callable.apply(lock); } }
@Test @Ignore("in the sequence causes SIGSEGV in java machine in sqlite module") public void lock() throws Exception { for( int z=0; z<10; z++ ) { HashId id = HashId.createRandom(); count = 0; ItemLock il = new ItemLock(); il.synchronize(id, (__) -> count++); il.synchronize(id, (__) -> count++); il.synchronize(id, (__) -> count++); assertEquals(3, count); assertEquals(1, il.size()); id = null; for (int i = 0; i < 10; i++) { System.gc(); System.runFinalization(); if (il.size() == 0) break; Thread.sleep(100); } assertEquals(0, il.size()); } }
Map<HashId,StateRecord> finished = new HashMap<>(); Map<HashId,StateRecord> failed = new HashMap<>(); ItemLock itemLock = new ItemLock(); Map<HashId,StateRecord> nullContarcts = new HashMap<>(); System.out.println(">> " + recordsToSanitate.size());