001/**
002 *
003 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved.
004 *
005 * This library is free software; you can redistribute it and/or
006 * modify it under the terms of the GNU Lesser General Public
007 * License as published by the Free Software Foundation; either 
008 * version 2.1 of the License, or (at your option) any later version.
009 * 
010 * This library is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
013 * Lesser General Public License for more details.
014 * 
015 * You should have received a copy of the GNU Lesser General Public 
016 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
017 * 
018 **/
019package lucee.runtime.op;
020
021import java.util.IdentityHashMap;
022import java.util.Map;
023
024import lucee.commons.lang.types.RefBoolean;
025import lucee.commons.lang.types.RefBooleanImpl;
026
027
028public class ThreadLocalDuplication {
029
030        private static ThreadLocal<Map<Object,Object>> local=new ThreadLocal<Map<Object,Object>>();
031        private static ThreadLocal<RefBoolean> inside=new ThreadLocal<RefBoolean>();
032
033        public static boolean set(Object o, Object c) {
034                touch(true).put(o,c);
035                return isInside();
036        }
037
038        /*private static Object get(Object obj) {
039                Map<Object,Object> list = touch();
040                return list.get(obj);
041        }*/
042        
043
044
045        public static Object get(Object object, RefBoolean before) {
046                if(!isInside()){
047                        reset(true);
048                        before.setValue(false);
049                }
050                else
051                        before.setValue(true);
052                
053                Map<Object,Object> list = touch(false);
054                return list==null?null:list.get(object);
055        }
056        
057
058        private static Map<Object,Object> touch(boolean createIfNecessary) {
059                Map<Object,Object> set = local.get();
060                if(set==null) {
061                        if(!createIfNecessary) return null;
062                        
063                        set = new IdentityHashMap<Object,Object>();// it is importend to have a reference comparsion here
064                        local.set(set);
065                }
066                return set;
067        }
068        public static void reset() {
069                reset(false);
070        }
071        
072        private static void reset(boolean inside) {
073                Map<Object,Object> set = local.get();
074                if(set!=null) set.clear();
075                setIsInside(inside);
076        }
077
078        private static boolean isInside() {
079                RefBoolean b = inside.get();
080                return b!=null && b.toBooleanValue();
081        }
082        
083        private static void setIsInside(boolean isInside) {
084                RefBoolean b = inside.get();
085                if(b==null)inside.set(new RefBooleanImpl(isInside));
086                else b.setValue(isInside);
087        }
088
089}
090
091