Требования к операционной системе: iOS 5.0 и выше.
Мобильное устройство: iPad
В данном примере описывается блокировка источника данных карты. После запуска примера выполняются следующие операции:
создается источник данных карты с помощью таблицы данных и экспресс-отчета;
создается поток исполнения программы, в котором производятся блокировка и разблокирование, а также некоторые действия с источником данных карты;
внутри первого потока создается новый поток исполнения программы, в котором также производятся блокировка, разблокирование и некоторые действия с источником данных карты.
Для выполнения примера необходимо разместить в теле метода executeExample класса ViewController (см. раздел «Отображение экспресс-отчёта») следующий код:
// Получаем делегат экспресс-отчета EAReportDelegateImpl *delegate = [m_controller delegate]; // Получаем источник данных карты MapDataViewDatasource *delegateMapDatasource = [delegate mapDatasource]; // Получаем из источника данных карты измерение метрик, измерение объектов наблюдения и измерение, используемое для построения временной шкалы SPPLDimension metricsDimension = [delegateMapDatasource metricsDimension_Map]; SPPLDimension topoDimension = [delegateMapDatasource observationDimension_Map]; SPPLDimension calendarDimension = [delegateMapDatasource timelineDimension_Map]; // Устанавливаем полученные измерения в экспресс-отчете m_olapReport->putDimensionToFixed(metricsDimension); m_olapReport->putDimensionToLeft(topoDimension); m_olapReport->putDimensionToTop(calendarDimension); m_olapReport->setMetrics(metricsDimension->id()); m_olapReport->setObjectives(topoDimension->id()); m_olapReport->setTimeline(calendarDimension->id()); // Создаем объект-основу для построения таблиц с данными SPPLPivot pivot = PPLPivot::pivot(m_olapReport); // Создаем таблицу данных SPPLPivotTable pivotTable = PPLPivotTable::pivotTable(pivot); // Создаем новый источник данных карты MapDataViewDatasource *mapDatasource = [[MapDataViewDatasource alloc] initWithPivotTable:pivotTable olapReport:m_olapReport withFullTopoSelection:YES]; // Создаем новый поток исполнения программы NSThread *thread1 =[[NSThread alloc] initWithTarget:self selector:@selector(thread1Run:) object:mapDatasource]; // Устанавливаем низкий приоритет для нового потока [thread1 setThreadPriority: 0.1]; // Запускаем новый поток исполнения программы [thread1 start];
Также необходимо в классе ViewController добавить следующие методы вместе с их реализацией:
// Выполняет действия первого потока исполнения программы
- (void) thread1Run: (MapDataViewDatasource *) mapDatasource {
NSLog(@"Источник данных заблокирован в 1 потоке");
// Создаем новый поток исполнения программы
NSThread *thread2 =[[NSThread alloc] initWithTarget:self selector:@selector(thread2Run:) object:mapDatasource];
// Устанавливаем высокий приоритет для нового потока
[thread2 setThreadPriority: 1.0];
// Запускаем новый поток исполнения программы
[thread2 start];
// Получаем справочник наименований измерений метрик
// Если источник данных был заблокирован, то исполнение потока будет приостановлено при обращении к источнику данных карты
NSDictionary *metricsDimensionsKeys = [mapDatasource metricsDimensionsKeys];
NSLog(@"Источник данных разблокирован в 1 потоке");
}
// Выполняет действия второго потока исполнения программы
- (void) thread2Run: (MapDataViewDatasource *) mapDatasource {
NSLog(@"Источник данных заблокирован в 2 потоке");
// Получаем справочник наименований измерений метрик
// Если источник данных был заблокирован, то исполнение потока будет приостановлено при обращении к источнику данных карты
NSDictionary *metricsDimensionsKeys = [mapDatasource metricsDimensionsKeys];
NSLog(@"Источник данных разблокирован в 2 потоке");
}
В результате выполнения примера в консоли среды разработки будут выведены сообщения, по которым можно определить последовательность исполнения операций программы:
Источник данных заблокирован в 1 потоке
Источник данных заблокирован в 2 потоке
Источник данных разблокирован в 1 потоке
Источник данных разблокирован в 2 потоке
Логика последовательности операций потоков нарушена, так как второй поток исполнения программы вызван внутри первого потока с более высоким приоритетом. Чтобы избежать подобных ситуаций, необходимо использовать блокировку потоков. Заменим код в методе thread1Run: в классе ViewController на следующий код:
// Блокируем источник данных карты [[mapDatasource updateLock] lock]; NSLog(@"Источник данных заблокирован в 1 потоке"); // Создаем новый поток исполнения программы NSThread *thread2 =[[NSThread alloc] initWithTarget:self selector:@selector(thread2Run:) object:mapDatasource]; // Устанавливаем высокий приоритет для нового потока [thread2 setThreadPriority: 1.0]; // Запускаем новый поток исполнения программы [thread2 start]; // Получаем справочник наименований измерений метрик
// Если источник данных был заблокирован, то исполнение потока будет приостановлено при обращении к источнику данных карты NSDictionary *metricsDimensionsKeys = [mapDatasource metricsDimensionsKeys]; NSLog(@"Источник данных разблокирован в 1 потоке"); // Осуществляем разблокирование источника данных карты [[mapDatasource updateLock] unlock];
Также необходимо заметить код в методе thread2Run: в классе ViewController на следующий код:
// Блокируем источник данных карты [[mapDatasource updateLock] lock]; NSLog(@"Источник данных заблокирован в 2 потоке"); // Получаем справочник наименований измерений метрик
// Если источник данных был заблокирован, то исполнение потока будет приостановлено при обращении к источнику данных карты NSDictionary *metricsDimensionsKeys = [mapDatasource metricsDimensionsKeys]; NSLog(@"Источник данных разблокирован в 2 потоке"); // Осуществляем разблокирование источника данных карты [[mapDatasource updateLock] unlock];
В результате выполнения обновленного примера в консоли среды разработки будет выведена правильная последовательность исполнения операций программы:
Источник данных заблокирован в 1 потоке
Источник данных разблокирован в 1 потоке
Источник данных заблокирован в 2 потоке
Источник данных разблокирован в 2 потоке
Второй поток исполнения программы был вызван внутри первого потока с более высоким приоритетом, но так как источник данных был заблокирован в первом потоке, повторная попытка блокировки приводит к тому, что поток приостанавливается и добавляется в очередь потоков, ожидающих освобождения источника данных.
См. также: