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
29 GDIHashtable::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
put(void * key,void * value)37 void* GDIHashtable::put(void* key, void* value) {
38 manager.decrementCounter();
39 return Hashtable::put(key, value);
40 }
41
release(void * key)42 void GDIHashtable::release(void* key) {
43 if (!manager.isBatchingEnabled()) {
44 void* value = remove(key);
45 DASSERT(value != NULL);
46 m_deleteProc(value);
47 }
48 }
49
flush()50 void 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
flushAll()79 void 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
add(GDIHashtable * table)88 void 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
remove(GDIHashtable * table)98 void 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
clear()116 void 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
BatchDestructionManager(UINT nFirstThreshold,UINT nSecondThreshold,UINT nDestroyPeriod)129 GDIHashtable::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