Home | History | Annotate | Download | only in api
      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 
     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 
     43 AdbObjectHandle::~AdbObjectHandle() {
     44   ATLASSERT(0 == ref_count_);
     45   ATLASSERT(NULL == adb_handle_);
     46 }
     47 
     48 LONG AdbObjectHandle::AddRef() {
     49   ATLASSERT(ref_count_ > 0);
     50   return InterlockedIncrement(&ref_count_);
     51 }
     52 
     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 
     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 
     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 
    140 bool AdbObjectHandle::IsObjectOfType(AdbObjectType obj_type) const {
    141   return (obj_type == object_type());
    142 }
    143 
    144 void AdbObjectHandle::LastReferenceReleased() {
    145   ATLASSERT(!IsOpened());
    146 }
    147 
    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