| 123 | This solution is not perhaps the most optimal way to lock because the protection of the IReadBlock, IWriteBlock, and IRasterIO routines is over the entire dataset. This is very limiting when you are reading the same dataset in a threaded environment, because it is not possible to read more then one block at a time. |
| 124 | |
| 125 | === Solution 2 (RW Mutex in GDALRasterBlock ) === |
| 126 | |
| 127 | ==== Mutexes ==== |
| 128 | |
| 129 | For solution 2 the three mutexes are: |
| 130 | |
| 131 | * Band Mutex (per GDALRasterBand) |
| 132 | * RBM Mutex (per GDALRasterBlockManager) |
| 133 | * Block RW Mutex (per GDALRasterBlock) |
| 134 | |
| 135 | In order to prevent deadlocks the band mutex has priority. This means that you can not get the Band Mutex if you have the RBM or Blow RW Mutex, unless you already had the Band Mutex prior to this. You may not obtain the Block mutex and the RBM mutex at the same time. |
| 136 | |
| 137 | ===== Band Mutex ===== |
| 138 | |
| 139 | The objective of the Band Mutex is to manage the control of the array of blocks in the GDALRasterBand, and manages the locking of the GDALRasterBlocks. This is a per GDALRasterBand Mutex. |
| 140 | |
| 141 | ===== RBM Mutex ===== |
| 142 | |
| 143 | The objective of the RBM Mutex is to manage control of the LRU cache. This mutex is responsible for the control of the management of the cache's linked list and total amount of data stored in the cache. |
| 144 | |
| 145 | ===== Block RW Mutex ===== |
| 146 | |
| 147 | The objective of the Block RW Mutex is to protect the data stored within the the GDALRasterBlocks associated with a dataset, and lock during large Read or Write operations. This prevents two different threads from using memcpy on the same GDALRasterBlock at the same time. It is created on a per block basis. |
| 148 | |
| 149 | ==== Pros ==== |
| 150 | |
| 151 | This is probably the most complete solution to making an intensive and fast threaded solution for the blocking. This is because the IReadWrite, IWriteBlock, and IRasterIO now are able to possibly pass a mutex with their calls, as a void pointer pointer. A change was made to the mutex as well such that a void pointer pointer that is NULL passed to CPLMutexHolderD, will not result in any pointer being created or any locking to occur. This means much of the behavior of the existing code can be maintained by simply passing a NULL value for the mutex. All of these changes allow the drivers to maintain much more control over the way that locking occurs when protecting the data inside a block. |
| 152 | |
| 153 | ==== Cons ==== |
| 154 | |
| 155 | Obviously, this is a much more complex solution and therefore is harder to manage. It means that writing a driver is not as trivial as before and care must be taken in how locking is done within the driver in order to prevent deadlocks and maintain thread safety. The other issue that might arise from this is a slight slow down in non-threaded code because of the extra cycles spent locking data that will not be accessed in a threaded manner. Additionally, it might have issues in windows if too many mutexes are created (as there are quite a few more since it is a per GDALRasterBlock mutex). (Note: Not sure how I will be able to test this properly?) |