001package org.cpsolver.ifs.assignment.context; 002 003import java.util.Arrays; 004import java.util.concurrent.locks.ReentrantReadWriteLock; 005 006import org.cpsolver.ifs.assignment.Assignment; 007import org.cpsolver.ifs.assignment.DefaultParallelAssignment; 008import org.cpsolver.ifs.model.Value; 009import org.cpsolver.ifs.model.Variable; 010 011 012/** 013 * A simple assignment context holder implementation used by the {@link DefaultParallelAssignment} class. 014 * {@link CanHoldContext} are used when possible, storing contexts in arrays, on the 015 * {@link DefaultParallelAssignment#getIndex()} position. 016 * 017 * @see AssignmentContext 018 * @see AssignmentContextReference 019 * @see AssignmentContextHolder 020 * 021 * @version IFS 1.3 (Iterative Forward Search)<br> 022 * Copyright (C) 2014 Tomas Muller<br> 023 * <a href="mailto:muller@unitime.org">muller@unitime.org</a><br> 024 * <a href="http://muller.unitime.org">http://muller.unitime.org</a><br> 025 * <br> 026 * This library is free software; you can redistribute it and/or modify 027 * it under the terms of the GNU Lesser General Public License as 028 * published by the Free Software Foundation; either version 3 of the 029 * License, or (at your option) any later version. <br> 030 * <br> 031 * This library is distributed in the hope that it will be useful, but 032 * WITHOUT ANY WARRANTY; without even the implied warranty of 033 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 034 * Lesser General Public License for more details. <br> 035 * <br> 036 * You should have received a copy of the GNU Lesser General Public 037 * License along with this library; if not see <a href='http://www.gnu.org/licenses'>http://www.gnu.org/licenses</a>. 038 * @param <V> Variable 039 * @param <T> Value 040 **/ 041public class DefaultParallelAssignmentContextHolder<V extends Variable<V, T>, T extends Value<V, T>> extends AssignmentContextHolderMap<V, T> { 042 private int iIndex = -1; 043 private final ReentrantReadWriteLock iLock = new ReentrantReadWriteLock(); 044 045 public DefaultParallelAssignmentContextHolder(int threadIndex) { 046 iIndex = threadIndex; 047 } 048 049 /** 050 * Returns contexts as an existing, big enough array. 051 * @param holder assignment context holder 052 * @return an initialized array of the appropriate assignment contexts 053 */ 054 protected AssignmentContext[] getContexts(CanHoldContext holder) { 055 iLock.readLock().lock(); 056 try { 057 AssignmentContext[] contexts = holder.getContext(); 058 if (contexts != null && iIndex < contexts.length) 059 return contexts; 060 } finally { 061 iLock.readLock().unlock(); 062 } 063 iLock.writeLock().lock(); 064 try { 065 AssignmentContext[] contexts = holder.getContext(); 066 if (contexts == null) { 067 contexts = new AssignmentContext[Math.max(10, 1 + iIndex)]; 068 holder.setContext(contexts); 069 } else if (contexts.length <= iIndex) { 070 contexts = Arrays.copyOf(contexts, iIndex + 10); 071 holder.setContext(contexts); 072 } 073 return contexts; 074 } finally { 075 iLock.writeLock().unlock(); 076 } 077 } 078 079 @Override 080 @SuppressWarnings("unchecked") 081 public <U extends AssignmentContext> U getAssignmentContext(Assignment<V, T> assignment, AssignmentContextReference<V, T, U> reference) { 082 if (iIndex >= 0 && reference.getParent() instanceof CanHoldContext) { 083 AssignmentContext[] contexts = getContexts((CanHoldContext)reference.getParent()); 084 AssignmentContext context = contexts[iIndex]; 085 if (context != null) return (U) context; 086 087 context = reference.getParent().createAssignmentContext(assignment); 088 contexts[iIndex] = context; 089 090 return (U) context; 091 } else { 092 return super.getAssignmentContext(assignment, reference); 093 } 094 } 095 096 @Override 097 public <C extends AssignmentContext> void clearContext(AssignmentContextReference<V, T, C> reference) { 098 if (iIndex >= 0 && reference.getParent() instanceof CanHoldContext) { 099 AssignmentContext[] contexts = getContexts((CanHoldContext)reference.getParent()); 100 contexts[iIndex] = null; 101 } else { 102 super.clearContext(reference); 103 } 104 } 105}