1 /*
2 * Copyright (c) 1996, 2013, 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 "CmdIDList.h"
27
28 // How much space to allocate initially
29 static const UINT ARRAY_INITIAL_SIZE = 1024;
30
31 // Array expansion increment when need more free space
32 static const UINT ARRAY_SIZE_INCREMENT = 1024;
33
34 // It seems that Win95 can not handle ids greater than 2**16
35 static const UINT ARRAY_MAXIMUM_SIZE = 32768;
36
37
AwtCmdIDList()38 AwtCmdIDList::AwtCmdIDList()
39 {
40 m_capacity = ARRAY_INITIAL_SIZE;
41 m_first_free = -1;
42 m_array = (CmdIDEntry *)SAFE_SIZE_ARRAY_ALLOC(safe_Malloc, m_capacity, sizeof(AwtObject*));
43 BuildFreeList(0);
44 }
45
~AwtCmdIDList()46 AwtCmdIDList::~AwtCmdIDList()
47 {
48 free(m_array);
49 }
50
51
52 // Build a new free list from a newly allocated memory. This only
53 // happens after malloc/realloc, and new free entries are contiguous
54 // from first_index to m_capacity-1
BuildFreeList(UINT first_index)55 INLINE void AwtCmdIDList::BuildFreeList(UINT first_index)
56 {
57 DASSERT(m_first_free == -1);
58 for (UINT i = first_index; i < m_capacity-1; ++i)
59 m_array[i].next_free_index = i+1;
60 m_array[m_capacity-1].next_free_index = -1; // nil
61 m_first_free = first_index; // head of the free list
62 }
63
64
isFreeIDAvailable()65 jboolean AwtCmdIDList::isFreeIDAvailable() {
66 CriticalSection::Lock l(m_lock);
67
68 if (m_first_free == -1) { // out of free ids
69 if (m_capacity == ARRAY_MAXIMUM_SIZE) {
70 return JNI_FALSE;
71 }
72 }
73 return JNI_TRUE;
74 }
75
76 // Assign an id to the object. Recycle the first free entry from the
77 // head of the free list or allocate more memory for a new free list.
Add(AwtObject * obj)78 UINT AwtCmdIDList::Add(AwtObject* obj)
79 {
80 CriticalSection::Lock l(m_lock);
81 if (!isFreeIDAvailable()) {
82 throw std::bad_alloc(); // fatal error
83 }
84
85 if (m_first_free == -1) { // out of free ids
86 // snarf a bigger arena
87 UINT old_capacity = m_capacity; // will be the first free entry
88 m_capacity += ARRAY_SIZE_INCREMENT;
89 if (m_capacity > ARRAY_MAXIMUM_SIZE)
90 m_capacity = ARRAY_MAXIMUM_SIZE;
91 m_array = (CmdIDEntry *)SAFE_SIZE_ARRAY_REALLOC(safe_Realloc, m_array,
92 m_capacity, sizeof(CmdIDEntry*));
93 BuildFreeList(old_capacity);
94 }
95
96 DASSERT(m_first_free != -1);
97 UINT newid = m_first_free; // use the entry from the head of the list
98 m_first_free = m_array[newid].next_free_index; // advance free pointer
99 m_array[newid].obj = obj;
100
101 return newid;
102 }
103
104 // Return the object associated with this id..
Lookup(UINT id)105 AwtObject* AwtCmdIDList::Lookup(UINT id)
106 {
107 CriticalSection::Lock l(m_lock);
108 DASSERT(id < m_capacity);
109 if (m_array[id].next_free_index <= ARRAY_MAXIMUM_SIZE) {
110 return NULL;
111 }
112 return m_array[id].obj;
113 }
114
115 // Return this id to the head of the free list.
Remove(UINT id)116 void AwtCmdIDList::Remove(UINT id)
117 {
118 CriticalSection::Lock l(m_lock);
119 DASSERT(id < m_capacity);
120 DASSERT(m_array[id].next_free_index > ARRAY_MAXIMUM_SIZE); // it's a pointer
121 m_array[id].next_free_index = m_first_free;
122 m_first_free = id;
123 }
124