• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  /*
2   * Copyright (C) 2006 The Android Open Source Project
3   *
4   * Licensed under the Apache License, Version 2.0 (the "License");
5   * you may not use this file except in compliance with the License.
6   * You may obtain a copy of the License at
7   *
8   *      http://www.apache.org/licenses/LICENSE-2.0
9   *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  /** \file
18    This file consists of implementation of a class AdbObjectHandle that
19    encapsulates an internal API object that is visible to the outside
20    of the API through a handle.
21  */
22  
23  #include "stdafx.h"
24  #include "adb_api.h"
25  #include "adb_object_handle.h"
26  
27  /// Global ADBAPIHANDLE -> AdbObjectHandle* map
28  AdbObjectHandleMap      the_map;
29  
30  /// Locker for the AdbObjectHandleMap instance
31  CComAutoCriticalSection the_map_locker;
32  
33  /// Next adb handle value generator
34  ULONG_PTR               next_adb_handle_value = 0;
35  
AdbObjectHandle(AdbObjectType obj_type)36  AdbObjectHandle::AdbObjectHandle(AdbObjectType obj_type)
37      : adb_handle_(NULL),
38        object_type_(obj_type),
39        ref_count_(1) {
40    ATLASSERT(obj_type < AdbObjectTypeMax);
41  }
42  
~AdbObjectHandle()43  AdbObjectHandle::~AdbObjectHandle() {
44    ATLASSERT(0 == ref_count_);
45    ATLASSERT(NULL == adb_handle_);
46  }
47  
AddRef()48  LONG AdbObjectHandle::AddRef() {
49    ATLASSERT(ref_count_ > 0);
50    return InterlockedIncrement(&ref_count_);
51  }
52  
Release()53  LONG AdbObjectHandle::Release() {
54    ATLASSERT(ref_count_ > 0);
55    LONG ret = InterlockedDecrement(&ref_count_);
56    ATLASSERT(ret >= 0);
57    if (0 == ret) {
58      LastReferenceReleased();
59      delete this;
60    }
61    return ret;
62  }
63  
CreateHandle()64  ADBAPIHANDLE AdbObjectHandle::CreateHandle() {
65    ADBAPIHANDLE ret = NULL;
66  
67    // We have to hold this lock while we're dealing with the handle
68    // and the table
69    the_map_locker.Lock();
70  
71    ATLASSERT(!IsOpened());
72  
73    if (!IsOpened()) {
74      try {
75        // Generate next handle value
76        next_adb_handle_value++;
77        ret = reinterpret_cast<ADBAPIHANDLE>(next_adb_handle_value);
78  
79        // Add ourselves to the map
80        the_map[ret] = this;
81  
82        // Save handle, addref and return
83        adb_handle_ = ret;
84        AddRef();
85      } catch (...) {
86        ret = NULL;
87        SetLastError(ERROR_OUTOFMEMORY);
88      }
89    } else {
90      // Signaling that this object is already opened
91      SetLastError(ERROR_GEN_FAILURE);
92    }
93  
94    the_map_locker.Unlock();
95  
96    return ret;
97  }
98  
CloseHandle()99  bool AdbObjectHandle::CloseHandle() {
100    bool ret = false;
101  
102    // Addref just in case that last reference to this object is being
103    // held in the map
104    AddRef();
105  
106    the_map_locker.Lock();
107  
108    ATLASSERT(IsOpened());
109  
110    if (IsOpened()) {
111      try {
112        // Look us up in the map.
113        AdbObjectHandleMap::iterator found = the_map.find(adb_handle());
114        ATLASSERT((found != the_map.end()) && (this == found->second));
115  
116        if ((found != the_map.end()) && (this == found->second)) {
117          // Remove ourselves from the map, close and release the object
118          the_map.erase(found);
119          adb_handle_ = NULL;
120          Release();
121          ret = true;
122        } else {
123          SetLastError(ERROR_INVALID_HANDLE);
124        }
125      } catch (...) {
126        ret = false;
127        SetLastError(ERROR_OUTOFMEMORY);
128      }
129    } else {
130      SetLastError(ERROR_INVALID_HANDLE);
131    }
132  
133    the_map_locker.Unlock();
134  
135    Release();
136  
137    return ret;
138  }
139  
IsObjectOfType(AdbObjectType obj_type) const140  bool AdbObjectHandle::IsObjectOfType(AdbObjectType obj_type) const {
141    return (obj_type == object_type());
142  }
143  
LastReferenceReleased()144  void AdbObjectHandle::LastReferenceReleased() {
145    ATLASSERT(!IsOpened());
146  }
147  
Lookup(ADBAPIHANDLE adb_hndl)148  AdbObjectHandle* AdbObjectHandle::Lookup(ADBAPIHANDLE adb_hndl) {
149    AdbObjectHandle* ret = NULL;
150  
151    the_map_locker.Lock();
152  
153    try {
154      // Look us up in the map.
155      AdbObjectHandleMap::iterator found = the_map.find(adb_hndl);
156      if (found != the_map.end()) {
157        ret = found->second;
158        ret->AddRef();
159      }
160    } catch (...) {
161      SetLastError(ERROR_OUTOFMEMORY);
162    }
163  
164    the_map_locker.Unlock();
165  
166    return ret;
167  }
168