001// Copyright 2008-2013 The Apache Software Foundation 002// 003// Licensed under the Apache License, Version 2.0 (the "License"); 004// you may not use this file except in compliance with the License. 005// You may obtain a copy of the License at 006// 007// http://www.apache.org/licenses/LICENSE-2.0 008// 009// Unless required by applicable law or agreed to in writing, software 010// distributed under the License is distributed on an "AS IS" BASIS, 011// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 012// See the License for the specific language governing permissions and 013// limitations under the License. 014 015package org.apache.tapestry5.ioc.internal; 016 017import org.apache.tapestry5.ioc.IOOperation; 018import org.apache.tapestry5.ioc.Invokable; 019import org.apache.tapestry5.ioc.OperationTracker; 020import org.apache.tapestry5.ioc.internal.util.JDKUtils; 021import org.slf4j.Logger; 022 023import java.io.IOException; 024import java.util.concurrent.locks.Lock; 025 026/** 027 * Manages a per-thread OperationTracker using a ThreadLocal. 028 */ 029public class PerThreadOperationTracker implements OperationTracker 030{ 031 private final Logger logger; 032 033 private final Lock lock = JDKUtils.createLockForThreadLocalCreation(); 034 035 private final ThreadLocal<OperationTrackerImpl> perThread = new ThreadLocal<OperationTrackerImpl>() 036 { 037 @Override 038 protected OperationTrackerImpl initialValue() 039 { 040 return new OperationTrackerImpl(logger); 041 } 042 }; 043 044 public PerThreadOperationTracker(Logger logger) 045 { 046 this.logger = logger; 047 } 048 049 OperationTracker get() 050 { 051 lock.lock(); 052 053 try 054 { 055 return perThread.get(); 056 } finally 057 { 058 lock.unlock(); 059 } 060 } 061 062 void cleanup() 063 { 064 try 065 { 066 lock.lock(); 067 if (perThread.get().isEmpty()) perThread.remove(); 068 } finally 069 { 070 lock.unlock(); 071 } 072 } 073 074 public void run(String description, Runnable operation) 075 { 076 try 077 { 078 get().run(description, operation); 079 } finally 080 { 081 cleanup(); 082 } 083 } 084 085 public <T> T invoke(String description, Invokable<T> operation) 086 { 087 try 088 { 089 return get().invoke(description, operation); 090 } finally 091 { 092 cleanup(); 093 } 094 } 095 096 public <T> T perform(String description, IOOperation<T> operation) throws IOException 097 { 098 try 099 { 100 return get().perform(description, operation); 101 } finally 102 { 103 cleanup(); 104 } 105 } 106}