Блокировка источника данных карты

Требования к операционной системе: 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 потоке

 

Второй поток исполнения программы был вызван внутри первого потока с более высоким приоритетом, но так как источник данных был заблокирован в первом потоке, повторная попытка блокировки приводит к тому, что поток приостанавливается и добавляется в очередь потоков, ожидающих освобождения источника данных.

См. также:

Примеры использования компонентов