15317bbafSopenharmony_ci/* 25317bbafSopenharmony_ci * Fast QR Code generator library 35317bbafSopenharmony_ci * 45317bbafSopenharmony_ci * Copyright (c) Project Nayuki. (MIT License) 55317bbafSopenharmony_ci * https://www.nayuki.io/page/fast-qr-code-generator-library 65317bbafSopenharmony_ci * 75317bbafSopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy of 85317bbafSopenharmony_ci * this software and associated documentation files (the "Software"), to deal in 95317bbafSopenharmony_ci * the Software without restriction, including without limitation the rights to 105317bbafSopenharmony_ci * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 115317bbafSopenharmony_ci * the Software, and to permit persons to whom the Software is furnished to do so, 125317bbafSopenharmony_ci * subject to the following conditions: 135317bbafSopenharmony_ci * - The above copyright notice and this permission notice shall be included in 145317bbafSopenharmony_ci * all copies or substantial portions of the Software. 155317bbafSopenharmony_ci * - The Software is provided "as is", without warranty of any kind, express or 165317bbafSopenharmony_ci * implied, including but not limited to the warranties of merchantability, 175317bbafSopenharmony_ci * fitness for a particular purpose and noninfringement. In no event shall the 185317bbafSopenharmony_ci * authors or copyright holders be liable for any claim, damages or other 195317bbafSopenharmony_ci * liability, whether in an action of contract, tort or otherwise, arising from, 205317bbafSopenharmony_ci * out of or in connection with the Software or the use or other dealings in the 215317bbafSopenharmony_ci * Software. 225317bbafSopenharmony_ci */ 235317bbafSopenharmony_ci 245317bbafSopenharmony_cipackage io.nayuki.fastqrcodegen; 255317bbafSopenharmony_ci 265317bbafSopenharmony_ciimport java.lang.ref.SoftReference; 275317bbafSopenharmony_ciimport java.util.HashSet; 285317bbafSopenharmony_ciimport java.util.Map; 295317bbafSopenharmony_ciimport java.util.Set; 305317bbafSopenharmony_ciimport java.util.concurrent.ConcurrentHashMap; 315317bbafSopenharmony_ciimport java.util.function.Function; 325317bbafSopenharmony_ci 335317bbafSopenharmony_ci 345317bbafSopenharmony_ci// A thread-safe cache based on soft references. 355317bbafSopenharmony_cifinal class Memoizer<T,R> { 365317bbafSopenharmony_ci 375317bbafSopenharmony_ci private final Function<T,R> function; 385317bbafSopenharmony_ci Map<T,SoftReference<R>> cache = new ConcurrentHashMap<>(); 395317bbafSopenharmony_ci private Set<T> pending = new HashSet<>(); 405317bbafSopenharmony_ci 415317bbafSopenharmony_ci 425317bbafSopenharmony_ci // Creates a memoizer based on the given function that takes one input to compute an output. 435317bbafSopenharmony_ci public Memoizer(Function<T,R> func) { 445317bbafSopenharmony_ci function = func; 455317bbafSopenharmony_ci } 465317bbafSopenharmony_ci 475317bbafSopenharmony_ci 485317bbafSopenharmony_ci // Computes function.apply(arg) or returns a cached copy of a previous call. 495317bbafSopenharmony_ci public R get(T arg) { 505317bbafSopenharmony_ci // Non-blocking fast path 515317bbafSopenharmony_ci { 525317bbafSopenharmony_ci SoftReference<R> ref = cache.get(arg); 535317bbafSopenharmony_ci if (ref != null) { 545317bbafSopenharmony_ci R result = ref.get(); 555317bbafSopenharmony_ci if (result != null) 565317bbafSopenharmony_ci return result; 575317bbafSopenharmony_ci } 585317bbafSopenharmony_ci } 595317bbafSopenharmony_ci 605317bbafSopenharmony_ci // Sequential slow path 615317bbafSopenharmony_ci while (true) { 625317bbafSopenharmony_ci synchronized(this) { 635317bbafSopenharmony_ci SoftReference<R> ref = cache.get(arg); 645317bbafSopenharmony_ci if (ref != null) { 655317bbafSopenharmony_ci R result = ref.get(); 665317bbafSopenharmony_ci if (result != null) 675317bbafSopenharmony_ci return result; 685317bbafSopenharmony_ci cache.remove(arg); 695317bbafSopenharmony_ci } 705317bbafSopenharmony_ci assert !cache.containsKey(arg); 715317bbafSopenharmony_ci 725317bbafSopenharmony_ci if (pending.add(arg)) 735317bbafSopenharmony_ci break; 745317bbafSopenharmony_ci 755317bbafSopenharmony_ci try { 765317bbafSopenharmony_ci this.wait(); 775317bbafSopenharmony_ci } catch (InterruptedException e) { 785317bbafSopenharmony_ci throw new RuntimeException(e); 795317bbafSopenharmony_ci } 805317bbafSopenharmony_ci } 815317bbafSopenharmony_ci } 825317bbafSopenharmony_ci 835317bbafSopenharmony_ci try { 845317bbafSopenharmony_ci R result = function.apply(arg); 855317bbafSopenharmony_ci cache.put(arg, new SoftReference<>(result)); 865317bbafSopenharmony_ci return result; 875317bbafSopenharmony_ci } finally { 885317bbafSopenharmony_ci synchronized(this) { 895317bbafSopenharmony_ci pending.remove(arg); 905317bbafSopenharmony_ci this.notifyAll(); 915317bbafSopenharmony_ci } 925317bbafSopenharmony_ci } 935317bbafSopenharmony_ci } 945317bbafSopenharmony_ci 955317bbafSopenharmony_ci} 96