1/* 2 * Copyright (c) 1999, 2008, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26#include "GDIHashtable.h" 27#include "awt_GDIObject.h" 28 29GDIHashtable::BatchDestructionManager GDIHashtable::manager; 30 31/* 32 * The order of monitor entrance is BatchDestructionManager->List->Hashtable. 33 * GDIHashtable::put() and GDIHashtable::release() are designed to be called 34 * only when we are synchronized on the BatchDestructionManager lock. 35 */ 36 37void* GDIHashtable::put(void* key, void* value) { 38 manager.decrementCounter(); 39 return Hashtable::put(key, value); 40} 41 42void GDIHashtable::release(void* key) { 43 if (!manager.isBatchingEnabled()) { 44 void* value = remove(key); 45 DASSERT(value != NULL); 46 m_deleteProc(value); 47 } 48} 49 50void GDIHashtable::flush() { 51 52 CriticalSection::Lock l(lock); 53 54 for (int i = capacity; i-- > 0;) { 55 HashtableEntry* prev = NULL; 56 for (HashtableEntry* e = table[i] ; e != NULL ; ) { 57 AwtGDIObject* pGDIObject = (AwtGDIObject*)e->value; 58 if (pGDIObject->GetRefCount() <= 0) { 59 if (prev != NULL) { 60 prev->next = e->next; 61 } else { 62 table[i] = e->next; 63 } 64 count--; 65 HashtableEntry* next = e->next; 66 if (m_deleteProc) { 67 (*m_deleteProc)(e->value); 68 } 69 delete e; 70 e = next; 71 } else { 72 prev = e; 73 e = e->next; 74 } 75 } 76 } 77} 78 79void GDIHashtable::List::flushAll() { 80 81 CriticalSection::Lock l(m_listLock); 82 83 for (ListEntry* e = m_pHead; e != NULL; e = e->next) { 84 e->table->flush(); 85 } 86} 87 88void GDIHashtable::List::add(GDIHashtable* table) { 89 90 CriticalSection::Lock l(m_listLock); 91 92 ListEntry* e = new ListEntry; 93 e->table = table; 94 e->next = m_pHead; 95 m_pHead = e; 96} 97 98void GDIHashtable::List::remove(GDIHashtable* table) { 99 100 CriticalSection::Lock l(m_listLock); 101 102 ListEntry* prev = NULL; 103 for (ListEntry* e = m_pHead; e != NULL; prev = e, e = e->next) { 104 if (e->table == table) { 105 if (prev != NULL) { 106 prev->next = e->next; 107 } else { 108 m_pHead = e->next; 109 } 110 delete e; 111 return; 112 } 113 } 114} 115 116void GDIHashtable::List::clear() { 117 118 CriticalSection::Lock l(m_listLock); 119 120 ListEntry* e = m_pHead; 121 m_pHead = NULL; 122 while (e != NULL) { 123 ListEntry* next = e->next; 124 delete e; 125 e = next; 126 } 127} 128 129GDIHashtable::BatchDestructionManager::BatchDestructionManager(UINT nFirstThreshold, 130 UINT nSecondThreshold, 131 UINT nDestroyPeriod) : 132 m_nFirstThreshold(nFirstThreshold), 133 m_nSecondThreshold(nSecondThreshold), 134 m_nDestroyPeriod(nDestroyPeriod), 135 m_nCounter(0), 136 m_bBatchingEnabled(TRUE) 137{ 138} 139