1.. _rfc-16: 2 3================================================================================ 4RFC 16: OGR Thread Safety 5================================================================================ 6 7Author: Frank Warmerdam 8 9Contact: warmerdam@pobox.com 10 11Status: Development 12 13Summary 14------- 15 16In an effort to better support thread safety in OGR some methods are 17added as internal infrastructure is updated. 18 19Definitions 20----------- 21 22*Reentrant*: A reentrant function can be called simultaneously by 23multiple threads provided that each invocation of the function 24references unique data. 25 26*Thread-safe*: A thread-safe function can be called simultaneously by 27multiple threads when each invocation references shared data. All access 28to the shared data is serialized. 29 30Objective 31--------- 32 33To make all of the OGR core and selected drivers reentrant, and to make 34the driver registrar, drivers and datasources at least potentially 35thread-safe. 36 37TestCapability() 38---------------- 39 40The TestCapability() method on the driver, and datasource will be 41extended to include ways of testing for reentrancy and thread safety on 42particular instances. The following macros will be added: 43 44:: 45 46 #define OLCReentrant "Reentrant" 47 #define ODsCLayerClones "LayerClones" 48 #define ODsCReentrant "Reentrant" 49 #define ODsCThreadSafe "Threadsafe" 50 51Meaning: 52 53- OLCReentrant: The layer class is reentrant. Multiple threads can 54 operate on distinct instances of this class - including different 55 layers on a single datasource. 56- ODsCReentrant: The datasource class is reentrant. Multiple threads 57 can operate on distinct instances of this class. 58- ODsCThreadSafe: The datasource class is thread-safe. Multiple threads 59 can operate on a single instance of this class. 60- ODsCLayerClones: The OGRDataSource::GetLayerClone() method is 61 supported, and returns a layer instance with distinct state from the 62 default layer returned by GetLayer(). 63 64Note that a single layer instance cannot be threadsafe as long as layer 65feature reading status is implicit in the layer object. The default 66return value for all test values is FALSE, as is normal for the 67TestCapability() method, but specific drivers can return TRUE after 68determining that the driver datasources or layers are in fact reentrant 69and/or threadsafe. 70 71OGRSFDriverRegistrar 72-------------------- 73 74Various changes have already been made to make the driver registrar 75thread safe, primarily by protecting operations on it with a mutex. 76 77OGRSFDriver 78----------- 79 80No changes are required to the OGRSFDriver base class for thread safety, 81primarily because it does almost nothing. 82 83OGRDataSource 84------------- 85 86This class has been modified to include an m_hMutex class data member 87which is a mutex used to ensure thread safe access to internal 88datastructures such as the layer list. Classes derived from 89OGRDataSource that wish to implement threadsafe operation should use 90this mutex when exclusivity is required. 91 92A new method is added to this class: 93 94:: 95 96 OGRLayer *GetLayerClone( int i ); 97 98The default implementation of this method returns NULL. If the 99ODsCLayerClones capability is true for the datasource, this method must 100return duplicates of the requested layer that have distinct feature 101reading state. That is they can have their own spatial and attribute 102filter settings, and the internal feature iterator (for GetNextFeature() 103and ResetReading()) is distinct from other OGRLayer instances 104referencing the same underlying datasource layer. 105 106The intention of this method in the multi-threaded context is that 107different threads can have clones of a layer with distinct read state. A 108sort of poor-mans threadsafety, even though in fact it is just 109reentrancy. 110 111Layers return by GetLayerClone() should be released with the 112OGRDataSource::ReleaseResultSet() method, much like layers returned by 113ExecuteSQL(). 114 115ExecuteSQL() 116------------ 117 118The default OGR implementation of OGRDataSource::ExecuteSQL() internally 119uses and modifies the layer state (feature iterators and filters) and as 120such is not appropriate to use on a datasource that is attempting to be 121threadsafe even though it is understood that individual layers are not 122threadsafe. 123 124The proposed solution is that this code will be modified to use 125GetLayerClone() if the datasource supports GetLayerClone(). 126 127Testing 128------- 129 130A multi-threaded C++ test harnass will be implemented for read-only 131stress testing of datasources claiming to support reentrancy and 132threadsafety. 133 134No testing of reentrancy and threadsafety will be incorporated into the 135regression test suite (gdalautotest) as it does not appear to be 136practical. 137 138Implementation 139-------------- 140 141Frank Warmerdam will implement all the core features of this RFC for the 142GDAL/OGR 1.5.0 release. As well the Shapefile, Personal Geodatabase, 143ODBC and Oracle drivers will implement OLCReentrant, ODsCLayerClones, 144ODsCReentrant and ODsThreadSafe. 145