001 /* 002 * Cobertura - http://cobertura.sourceforge.net/ 003 * 004 * Copyright (C) 2010 Piotr Tabor 005 * 006 * Note: This file is dual licensed under the GPL and the Apache 007 * Source License (so that it can be used from both the main 008 * Cobertura classes and the ant tasks). 009 * 010 * Cobertura is free software; you can redistribute it and/or modify 011 * it under the terms of the GNU General Public License as published 012 * by the Free Software Foundation; either version 2 of the License, 013 * or (at your option) any later version. 014 * 015 * Cobertura is distributed in the hope that it will be useful, but 016 * WITHOUT ANY WARRANTY; without even the implied warranty of 017 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 018 * General Public License for more details. 019 * 020 * You should have received a copy of the GNU General Public License 021 * along with Cobertura; if not, write to the Free Software 022 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 023 * USA 024 */ 025 026 package net.sourceforge.cobertura.coveragedata.countermaps; 027 028 import java.util.Iterator; 029 import java.util.LinkedHashMap; 030 import java.util.Map; 031 import java.util.concurrent.ConcurrentHashMap; 032 import java.util.concurrent.ConcurrentMap; 033 import java.util.concurrent.atomic.AtomicInteger; 034 035 import net.sourceforge.cobertura.coveragedata.HasBeenInstrumented; 036 037 /** 038 * Thread-safe implementation of map that counts number of keys (like multi-set) 039 * @author ptab 040 * 041 * @param <T> 042 */ 043 public class AtomicCounterMap<T> implements CounterMap<T>,HasBeenInstrumented{ 044 private final ConcurrentMap<T, AtomicInteger> counters=new ConcurrentHashMap<T, AtomicInteger>(); 045 046 public final void incrementValue(T key, int inc){ 047 AtomicInteger v=counters.get(key); 048 if(v!=null){ 049 v.addAndGet(inc); 050 }else{ 051 v=counters.putIfAbsent(key, new AtomicInteger(inc)); 052 if(v!=null)v.addAndGet(inc); 053 } 054 } 055 056 public final void incrementValue(T key){ 057 //AtomicInteger v=counters.putIfAbsent(key, new AtomicInteger(1)); 058 //return (v!=null)?v.incrementAndGet():1; 059 AtomicInteger v=counters.get(key); 060 if(v!=null){ 061 v.incrementAndGet(); 062 }else{ 063 v=counters.putIfAbsent(key, new AtomicInteger(1)); 064 if(v!=null)v.incrementAndGet(); 065 } 066 } 067 068 public final int getValue(T key){ 069 AtomicInteger v=counters.get(key); 070 return v==null?0:v.get(); 071 } 072 073 074 public synchronized Map<T,Integer> getFinalStateAndCleanIt(){ 075 Map<T,Integer> res=new LinkedHashMap<T, Integer>(); 076 Iterator<Map.Entry<T, AtomicInteger>> iterator=counters.entrySet().iterator(); 077 while (iterator.hasNext()) { 078 Map.Entry<T, AtomicInteger> entry=iterator.next(); 079 T key=entry.getKey(); 080 int old=entry.getValue().get(); 081 iterator.remove(); 082 if(old>0){ 083 res.put(key, old); 084 } 085 } 086 return res; 087 } 088 089 public int getSize(){ 090 return counters.size(); 091 } 092 }