001/* 002* SizedObjectFactory -- A class that holds factories to produce objects that require variable size inputs. 003* 004* Copyright (C) 2011-2025 by Joseph A. Huwaldt. All rights reserved. 005* 006* This library is free software; you can redistribute it and/or 007* modify it under the terms of the GNU Lesser General Public 008* License as published by the Free Software Foundation; either 009* version 2 of the License, or (at your option) any later version. 010* 011* This library is distributed in the hope that it will be useful, 012* but WITHOUT ANY WARRANTY; without even the implied warranty of 013* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 014* Lesser General Public License for more details. 015* 016* You should have received a copy of the GNU Lesser General Public License 017* along with this program; if not, write to the Free Software 018* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 019* Or visit: http://www.gnu.org/licenses/lgpl.html 020**/ 021package jahuwaldt.js.util; 022 023import javolution.context.ObjectFactory; 024 025 026/** 027* <p> This class holds factories to produces objects of variable size/length. 028* It allows for object recycling, pre-allocation and stack allocations: 029* 030* <pre> 031* {@code 032* static SizedObjectFactory<BinomialCoef> BINOMIAL_FACTORY = new SizedObjectFactory<BinomialCoef> { 033* protected BinomialCoef create(int size) { 034* return new BinomialCoef(size); 035* } 036* }; 037* ... 038* BinomialCoef bin = BINOMIAL_FACTORY.array(256); 039* } 040* </pre> 041* 042* @author Joseph A. Huwaldt Date: May 11, 2011 043* @version February 22, 2025 044**/ 045public abstract class SizedObjectFactory<T extends SizedObject> { 046 047 /** 048 * Holds factory for arrays up to size 4. 049 */ 050 private final ObjectFactory _factory4 = new ObjectFactory() { 051 @Override 052 protected Object create() { 053 return SizedObjectFactory.this.create(4); 054 } 055 }; 056 057 /** 058 * Holds factory for arrays up to size 8. 059 */ 060 private final ObjectFactory _factory8 = new ObjectFactory() { 061 @Override 062 protected Object create() { 063 return SizedObjectFactory.this.create(8); 064 } 065 }; 066 067 /** 068 * Holds factory for arrays up to size 16. 069 */ 070 private final ObjectFactory _factory16 = new ObjectFactory() { 071 @Override 072 protected Object create() { 073 return SizedObjectFactory.this.create(16); 074 } 075 }; 076 077 /** 078 * Holds factory for arrays up to size 32. 079 */ 080 private final ObjectFactory _factory32 = new ObjectFactory() { 081 @Override 082 protected Object create() { 083 return SizedObjectFactory.this.create(32); 084 } 085 }; 086 087 /** 088 * Holds factory for arrays up to size 64. 089 */ 090 private final ObjectFactory _factory64 = new ObjectFactory() { 091 @Override 092 protected Object create() { 093 return SizedObjectFactory.this.create(64); 094 } 095 }; 096 097 /** 098 * Holds factory for arrays up to size 128. 099 */ 100 private final ObjectFactory _factory128 = new ObjectFactory() { 101 @Override 102 protected Object create() { 103 return SizedObjectFactory.this.create(128); 104 } 105 }; 106 107 /** 108 * Holds factory for arrays up to size 256. 109 */ 110 private final ObjectFactory _factory256 = new ObjectFactory() { 111 @Override 112 protected Object create() { 113 return SizedObjectFactory.this.create(256); 114 } 115 }; 116 117 /** 118 * Holds factory for arrays up to size 512. 119 */ 120 private final ObjectFactory _factory512 = new ObjectFactory() { 121 @Override 122 protected Object create() { 123 return SizedObjectFactory.this.create(512); 124 } 125 }; 126 127 /** 128 * Holds factory for arrays up to size 1024. 129 */ 130 private final ObjectFactory _factory1024 = new ObjectFactory() { 131 @Override 132 protected Object create() { 133 return SizedObjectFactory.this.create(1024); 134 } 135 }; 136 137 /** 138 * Holds factory for arrays up to size 2048. 139 */ 140 private final ObjectFactory _factory2048 = new ObjectFactory() { 141 @Override 142 protected Object create() { 143 return SizedObjectFactory.this.create(2048); 144 } 145 }; 146 147 /** 148 * Holds factory for arrays up to size 4096. 149 */ 150 private final ObjectFactory _factory4096 = new ObjectFactory() { 151 @Override 152 protected Object create() { 153 return SizedObjectFactory.this.create(4096); 154 } 155 }; 156 157 /** 158 * Holds factory for arrays up to size 8192. 159 */ 160 private final ObjectFactory _factory8192 = new ObjectFactory() { 161 @Override 162 protected Object create() { 163 return SizedObjectFactory.this.create(8192); 164 } 165 }; 166 167 /** 168 * Holds factory for arrays up to size 16384. 169 */ 170 private final ObjectFactory _factory16384 = new ObjectFactory() { 171 @Override 172 protected Object create() { 173 return SizedObjectFactory.this.create(16384); 174 } 175 }; 176 177 /** 178 * Holds factory for arrays up to size 32768. 179 */ 180 private final ObjectFactory _factory32768 = new ObjectFactory() { 181 @Override 182 protected Object create() { 183 return SizedObjectFactory.this.create(32768); 184 } 185 }; 186 187 /** 188 * Holds factory for arrays up to size 65536. 189 */ 190 private final ObjectFactory _factory65536 = new ObjectFactory() { 191 @Override 192 protected Object create() { 193 return SizedObjectFactory.this.create(65536); 194 } 195 }; 196 197 // Above 65536 we use the heap exclusively. 198 199 /** 200 * Default constructor. 201 */ 202 public SizedObjectFactory() { } 203 204 /** 205 * Returns an sized object possibly recycled or preallocated of specified 206 * minimum size. 207 * 208 * @param capacity the minimum size of the array to be returned. 209 * @return a recycled, pre-allocated or new factory array. 210 */ 211 public final T object(int capacity) { 212 return (capacity <= 4) ? (T) _factory4.object() 213 : largeArray(capacity); 214 } 215 216 private T largeArray(int capacity) { 217 if (capacity <= 8) 218 return (T) _factory8.object(); 219 if (capacity <= 16) 220 return (T) _factory16.object(); 221 if (capacity <= 32) 222 return (T) _factory32.object(); 223 if (capacity <= 64) 224 return (T) _factory64.object(); 225 if (capacity <= 128) 226 return (T) _factory128.object(); 227 if (capacity <= 256) 228 return (T) _factory256.object(); 229 if (capacity <= 512) 230 return (T) _factory512.object(); 231 if (capacity <= 1024) 232 return (T) _factory1024.object(); 233 if (capacity <= 2048) 234 return (T) _factory2048.object(); 235 if (capacity <= 4096) 236 return (T) _factory4096.object(); 237 if (capacity <= 8192) 238 return (T) _factory8192.object(); 239 if (capacity <= 16384) 240 return (T) _factory16384.object(); 241 if (capacity <= 32768) 242 return (T) _factory32768.object(); 243 if (capacity <= 65536) 244 return (T) _factory65536.object(); 245 return create(capacity); 246 } 247 248 /** 249 * Recycles the specified sized object. 250 * 251 * @param object the SizedObject to be recycled. 252 */ 253 public void recycle(SizedObject object) { 254 recycle(object, object.size()); 255 } 256 257 final void recycle(SizedObject array, int length) { 258 if (length <= 4) { 259 _factory4.recycle(array); 260 } else if (length <= 8) { 261 _factory8.recycle(array); 262 } else if (length <= 16) { 263 _factory16.recycle(array); 264 } else if (length <= 32) { 265 _factory32.recycle(array); 266 } else if (length <= 64) { 267 _factory64.recycle(array); 268 } else if (length <= 128) { 269 _factory128.recycle(array); 270 } else if (length <= 256) { 271 _factory256.recycle(array); 272 } else if (length <= 512) { 273 _factory512.recycle(array); 274 } else if (length <= 1024) { 275 _factory1024.recycle(array); 276 } else if (length <= 2048) { 277 _factory2048.recycle(array); 278 } else if (length <= 4096) { 279 _factory4096.recycle(array); 280 } else if (length <= 8192) { 281 _factory8192.recycle(array); 282 } else if (length <= 16384) { 283 _factory16384.recycle(array); 284 } else if (length <= 32768) { 285 _factory32768.recycle(array); 286 } else if (length <= 65536) { 287 _factory65536.recycle(array); 288 } 289 } 290 291 /** 292 * Constructs a new sized object of specified size from this factory 293 * (using the <code>new</code> keyword). 294 * 295 * @param size the size of the array. 296 * @return a new factory array. 297 */ 298 protected abstract T create(int size); 299 300}