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
29static const UINT ARRAY_INITIAL_SIZE = 1024;
30
31// Array expansion increment when need more free space
32static const UINT ARRAY_SIZE_INCREMENT = 1024;
33
34// It seems that Win95 can not handle ids greater than 2**16
35static const UINT ARRAY_MAXIMUM_SIZE = 32768;
36
37
38AwtCmdIDList::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
46AwtCmdIDList::~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
55INLINE 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// Assign an id to the object.  Recycle the first free entry from the
65// head of the free list or allocate more memory for a new free list.
66UINT AwtCmdIDList::Add(AwtObject* obj)
67{
68    CriticalSection::Lock l(m_lock);
69
70    if (m_first_free == -1) {   // out of free ids
71        if (m_capacity == ARRAY_MAXIMUM_SIZE) {
72            // Really bad - out of ids.  Since we hardly can have *so*
73            // many items simultaneously in existence, we have an id
74            // leak somewhere.
75            DASSERT(FALSE);
76            return 0;
77        }
78        else {                  // snarf a bigger arena
79            UINT old_capacity = m_capacity; // will be the first free entry
80            m_capacity += ARRAY_SIZE_INCREMENT;
81            if (m_capacity > ARRAY_MAXIMUM_SIZE)
82                m_capacity = ARRAY_MAXIMUM_SIZE;
83            m_array = (CmdIDEntry *)SAFE_SIZE_ARRAY_REALLOC(safe_Realloc, m_array,
84                                        m_capacity, sizeof(CmdIDEntry*));
85            BuildFreeList(old_capacity);
86        }
87    }
88
89    DASSERT(m_first_free != -1);
90    UINT newid = m_first_free;  // use the entry from the head of the list
91    m_first_free = m_array[newid].next_free_index; // advance free pointer
92    m_array[newid].obj = obj;
93
94    return newid;
95}
96
97// Return the object associated with this id..
98AwtObject* AwtCmdIDList::Lookup(UINT id)
99{
100    CriticalSection::Lock l(m_lock);
101    DASSERT(id < m_capacity);
102    if (m_array[id].next_free_index <= ARRAY_MAXIMUM_SIZE) {
103        return NULL;
104    }
105    return m_array[id].obj;
106}
107
108// Return this id to the head of the free list.
109void AwtCmdIDList::Remove(UINT id)
110{
111    CriticalSection::Lock l(m_lock);
112    DASSERT(id < m_capacity);
113    DASSERT(m_array[id].next_free_index > ARRAY_MAXIMUM_SIZE); // it's a pointer
114    m_array[id].next_free_index = m_first_free;
115    m_first_free = id;
116}
117