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