Текущий раздел:

Описания RDS

Приложения

Приложение А. Функции, константы и структуры RDS

А.5. Сервисные функции и макросы RDS

А.5.3. Синхронизация потоков RDS

А.5.3.1. rdsBlockDataSyncCall – вызвать функцию с блокировкой данных

# Приложения

## Приложение А. Функции, константы и структуры RDS

### А.5. Сервисные функции и макросы RDS

#### А.5.3. Синхронизация потоков RDS

Описываются функции, предотвращающие одновременное обращение к данным блоков из двух одновременное работающих потоков RDS: главного потока и потока расчета.

##### А.5.3.1. rdsBlockDataSyncCall – вызвать функцию с блокировкой данных

Функция rdsBlockDataSyncCall вызывает пользовательскую функцию, указатель на которую передается в ее первом параметре, блокируя доступ ко всем данным RDS на время этого вызова.

      int RDSCALL rdsBlockDataSyncCall(
        RDS_IpV Func,    // Функция пользователя
        LPVOID Param     // Параметр функции пользователя
      );

Тип указателя на эту функцию

RDS_ICb4pV

Параметры

Func(RDS_IpV)
  Указатель на пользовательскую функцию, которую нужно вызвать с блокировкой данных. Пользовательская функция должна иметь следующий вид:

        int RDSCALL имя_функции(LPVOID param);

  Тип этого параметра RDS_IpV описан в «RdsDef.h» как указатель на такую функцию:

        typedef int (RDSCALL *RDS_IpV)(LPVOID);

Param(LPVOID)
  Параметр типа void*, передаваемый в пользовательскую функцию при вызове.

Возвращаемое значение

Целое число, возвращенное вызванной функцией пользователя.

Примечания

Функция rdsBlockDataSyncCall обычно используется для выполнения каких-либо действий с данными блоков (например, вызова других сервисных функций RDS или обращения к статическим переменным блока) не из функции модели или функции модуля автокомпиляции, то есть в те моменты, когда данные не заблокированы RDS автоматически. Чаще всего такая ситуация возникает при открытии немодальных окон в модели блока (см. §1.8 руководства программиста), процедуры которых вызываются Windows без синхронизации с RDS. Если процедура окна обратится к данным блока одновременно с потоком расчета RDS, могут возникнуть серьезные ошибки, поэтому такие обращения необходимо синхронизировать. При обращении к данным блока из функции модели или модуля автокомпиляции за синхронизацией следит RDS, поэтому в вызове специальных функций нет необходимости.

При вызове rdsBlockDataSyncCall RDS выполняет следующие действия:

1. Данные блокируются, как при вызове rdsLockBlockData.
2. Вызывается функция, указатель на которую передан в параметре Func, с параметром, переданным в параметре Param. Возвращенное функцией целое число запоминается.
3. Блокировка данных снимается, как при вызове rdsUnlockBlockData.
4. Запомненный результат возврата вызванной функции возвращается вызвавшей программе.

Параметр Param, имеющий тип LPVOID (произвольный указатель), передается в вызываемую функцию пользователя без изменений. Это единственный способ передать ей какие-либо данные: например, можно передать указатель на какую-либо структуру, а внутри пользовательской функции привести его к нужному типу и обращаться к полям этой структуры.

Фактически, вызов rdsBlockDataSyncCall всегда можно заменить парой вызовов rdsLockBlockData и rdsUnlockBlockData, между которыми вызывается пользовательская функция. Использование rdsBlockDataSyncCall с ее внутренней блокировкой данных позволяет уменьшить вероятность ошибки программиста: если при блокировке данных вручную забыть вызвать rdsUnlockBlockData, данные останутся заблокированными, что приведет к остановке потока расчета RDS.

Пример

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

      // Функция пользователя
      int RDSCALL MySyncFunc(LPVOID param)
      { wchar_t *text=(wchar_t*)param;
        return rdsMessageBoxW(text,L"Сообщение",MB_YESNO);
      }
        ...
      // Вызов функциии с синхронизацией
      int ret=rdsBlockDataSyncCall(MySyncFunc,L"Выполнить действие?");

Этот пример можно было бы переписать без использования rdsBlockDataSyncCall следующим образом:

      // Действия с синхронизацией
      int ret;
      // Блокировка данных
      rdsLockBlockData();
      // Выполнение действий
      ret=rdsMessageBoxW(L"Выполнить действие?",L"Сообщение",MB_YESNO);
      // Снятие блокировки
      rdsUnlockBlockData();

См. также

rdsLockBlockData, rdsUnlockBlockData.