Приложения
Приложение А. Функции, константы и структуры 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 выполняет следующие действия:
- Данные блокируются, как при вызове rdsLockBlockData.
- Вызывается функция, указатель на которую передан в параметре Func, с параметром, переданным в параметре Param. Возвращенное функцией целое число запоминается.
- Блокировка данных снимается, как при вызове rdsUnlockBlockData.
- Запомненный результат возврата вызванной функции возвращается вызвавшей программе.
Параметр 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();
См. также