之前在GDALDestroyDriverManager 分析中没有看到对dGDALDatasert的回收。先看一个例子程序,这个例子打开了一个tif文件,读取了一些基本信息。
为了简单示范,没有写成C++的各种类分散到各个文件中。
#include "stdafx.h" #include "gdal_priv.h" #include "cpl_conv.h" // for CPLMalloc() #include <string> #include <iostream> #include <sstream> #include <iomanip> #include <boost/cstdint.hpp> using namespace std; void print_line() { cout << "----------------------" << endl; } void printDataType(GDALDataType type) { if (type == GDALDataType::GDT_Byte) { cout << "GDALDataType: GDT_Byte" << endl; } else { cout << "GDALDataType: GDT_Unknown" << endl; } } void printAccess(GDALAccess access) { if (access == GDALAccess::GA_ReadOnly) { cout << "GDALAccess: GA_ReadOnly" << endl; } else { cout << "GDALAccess: GA_Update" << endl; } } void printCategoryNames(char** names) { if (names == NULL) { cout << "non category names" << endl; return; } size_t i = 0; char* str = names[i]; while(str != "") { cout << str << endl; str = names[i]; } } void printColorInterp(GDALColorInterp interp) { switch(interp) { case GDALColorInterp::GCI_AlphaBand: cout << "GDALColorInterp: GCI_AlphaBand" << endl; break; case GDALColorInterp::GCI_BlackBand: cout << "GDALColorInterp: GCI_BlackBand" << endl; break; case GDALColorInterp::GCI_RedBand: cout << "GDALColorInterp: GCI_RedBand" << endl; break; case GDALColorInterp::GCI_GreenBand: cout << "GDALColorInterp: GCI_GreenBand" << endl; break; case GDALColorInterp::GCI_BlueBand: cout << "GDALColorInterp: GCI_BlueBand" << endl; break; default: cout << "GDALColorInterp: GCI_Undefined: " << interp << endl; } } void printColorTable(GDALColorTable* table) { if (table == NULL) { cout << "color table is null" << endl; return; } cout << "ColorEntryCount: " << table->GetColorEntryCount() << endl; } string getBytesAsHexString(uint8_t * data, size_t size) { stringstream stream; stream << std::hex << std::uppercase << std::setfill('0'); for (size_t i = 0; i < size; ++i) { stream <<std::setw(2) << static_cast<uint32_t>(data[i] & 0xff) << " "; } return stream.str(); } void printBand(GDALRasterBand* band) { cout << "XSize: " << band->GetXSize() << endl; cout << "YSize: " << band->GetYSize() << endl; cout << "Band number(index for itself): " << band->GetBand() << endl; printDataType(band->GetRasterDataType()); int x_size = 0; int y_size = 0; band->GetBlockSize(&x_size, &y_size); cout << "Band Block size, x size: " << x_size << " pixels , y size: " << y_size << " pixels" << endl; printAccess(band->GetAccess()); printCategoryNames(band->GetCategoryNames()); cout << "no data value: " << band->GetNoDataValue() << endl; cout << "minimum value: " << band->GetMinimum() << endl; cout << "maximum value: " << band->GetMaximum() << endl; cout << "offset value: " << band->GetOffset() << endl; cout << "scale value: " << band->GetScale() << endl; cout << "unit type: " << band->GetUnitType() << endl; printColorInterp(band->GetColorInterpretation()); printColorTable(band->GetColorTable()); GByte * data = static_cast<GByte*>(CPLMalloc(x_size * y_size)); band->ReadBlock(5000, 3000, data); cout << "one block data: " << getBytesAsHexString(data, x_size * y_size) << endl; } void printTiffInfo(GDALDataset* set) { print_line(); cout << "Tiff info " << endl; cout << "RasterXSize: " << set->GetRasterXSize() << endl; cout << "RasterYSize: " << set->GetRasterYSize() << endl; size_t band_count = set->GetRasterCount(); cout << "Raster band count: " << band_count << endl; for (size_t i = 1; i <= band_count; ++i) { GDALRasterBand* band = set->GetRasterBand(i); print_line(); cout << "Band " << i << " : " << endl; printBand(band); } } int _tmain(int argc, _TCHAR* argv[]) { GDALAllRegister(); string data_dir = "../../../study/data/"; string tiffPath = data_dir + "v4_dem_gtopo30/v4_dem.tif"; GDALDataset* dataset = (GDALDataset *) GDALOpen(tiffPath.c_str(), GA_ReadOnly); if (dataset == NULL) { cout << "open ttf file in TiffCopy app failed" << endl; GDALDestroyDriverManager(); exit(1); } cout << "loading tiff file successfully" << endl; printTiffInfo(dataset); GDALClose(dataset); GDALDestroyDriverManager(); return 0; }
在main函数中,用GDALOpen打开了一个tif文件,并且获得了GDALDataset对象的指针,然后用GDALClose销毁了这个对象。下面是GDALClose代码:
/** * rief Close GDAL dataset. * * For non-shared datasets (opened with GDALOpen()) the dataset is closed * using the C++ "delete" operator, recovering all dataset related resources. * For shared datasets (opened with GDALOpenShared()) the dataset is * dereferenced, and closed only if the referenced count has dropped below 1. * * @param hDS The dataset to close. May be cast from a "GDALDataset *". */ void CPL_STDCALL GDALClose( GDALDatasetH hDS ) { VALIDATE_POINTER0( hDS, "GDALClose" ); GDALDataset *poDS = (GDALDataset *) hDS; CPLMutexHolderD( &hDLMutex ); CPLLocaleC oLocaleForcer; if (poDS->GetShared()) { /* -------------------------------------------------------------------- */ /* If this file is in the shared dataset list then dereference */ /* it, and only delete/remote it if the reference count has */ /* dropped to zero. */ /* -------------------------------------------------------------------- */ if( poDS->Dereference() > 0 ) return; delete poDS; return; } /* -------------------------------------------------------------------- */ /* This is not shared dataset, so directly delete it. */ /* -------------------------------------------------------------------- */ delete poDS; }
注释表明GDALDataset支持普通和引用计数管理两种生命周期管理方式。代码中表明在销毁的时候使用了互斥量,因此是线程安全的。