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