struct A {
int nValue;
}; // твоя структураstruct AX : A {
int& fnValue() {return nValue;}
}; // а это я добавил - по члену на каждое поле#define A AX
#define nValue fnValue()
int _tmain(int argc, _TCHAR* argv[])
{
// это твоя исходная программа, я тут ничего не меняю
A a;
a.nValue = 10;
A* pa = &a;
pa->nValue = 100;
return 0;
}
Все обращения к полям перехвачены, ставь lock в перехватчиках.
With best regards
Pavel Dvorkin
Re[3]: Использование структуры в многопоточном приложении
Здравствуйте, Геннадий Майко, Вы писали:
ГМ>Не будет ли здесь проблем с кодом типа:
ГМ>{ ГМ>... ГМ>ptStrcut->FieldA = 20; ГМ>ptStrcut->FiedlB = ptStruct->FiledC; ГМ>int LocalVar = ptStruct->FieldD; ГМ>... ГМ>}
Да вроде недолжно:
{
pair<locker, resource*> p = get_resource();
p.second->FieldA = 20;
p.second->FieldB = p.second->FieldC;
int LocalVar = p.second->FieldD;
}
Но надо быть внимательным .
Re: Использование структуры в многопоточном приложении
Здравствуйте, Геннадий Майко, Вы писали:
ГМ>Добрый день!
ГМ>Есть проект, написанный на С, в котором есть глобальная структура. Указатель на эту структуру используется в нескольких функциях как для записи, так и для чтения данных в/из этой структуры. Прект однопоточный.
ГМ>Есть намерение в другом проекте (С++/С) эффективно использовать каждую из таких функций в отдельном потоке. Понятно, что при этом необходимо обеспечить корректный доступ к полям этой глобальной структуре из разных потоков. Код этих функций крайне желательно не менять (первый проект пишется другой группой, очень не хочется им мешать); в крайнем случае можно его заменять с помощью препроцессора. Дописывать код (например, wrapper functions или свои классы) вполне можно.
ГМ>Какие есть идеи по корректному использованию такой глобальной структуры при минимальном изменении кода существуюших функций?
ГМ>С уважением, ГМ>Геннадий Майко
ГМ>P.S. У меня есть пару соображений, но я специально пока не буду их озвучивать здесь, чтобы сначала послушать мнения уважаемых коллег.
Есть Microsoft Specific решение... __declspec(property(
аналогично, можно реализовать свои кросплатформенные геттеры/сеттеры с локом по середине.
Есть проект, написанный на С, в котором есть глобальная структура. Указатель на эту структуру используется в нескольких функциях как для записи, так и для чтения данных в/из этой структуры. Прект однопоточный.
Есть намерение в другом проекте (С++/С) эффективно использовать каждую из таких функций в отдельном потоке. Понятно, что при этом необходимо обеспечить корректный доступ к полям этой глобальной структуре из разных потоков. Код этих функций крайне желательно не менять (первый проект пишется другой группой, очень не хочется им мешать); в крайнем случае можно его заменять с помощью препроцессора. Дописывать код (например, wrapper functions или свои классы) вполне можно.
Какие есть идеи по корректному использованию такой глобальной структуры при минимальном изменении кода существуюших функций?
С уважением,
Геннадий Майко
P.S. У меня есть пару соображений, но я специально пока не буду их озвучивать здесь, чтобы сначала послушать мнения уважаемых коллег.
Re: Использование структуры в многопоточном приложении
Здравствуйте, Геннадий Майко, Вы писали:
ГМ>Какие есть идеи по корректному использованию такой глобальной структуры при минимальном изменении кода существуюших функций?
1. Если надо написать быстро, то можно использовать своеобразный getter, который возвращает pair<mutex_lock, resource*>.
2. Если API небольшой то можно полность инкапсулировать код, продублировать интерфейс, и более-менее эффективо использовать ресурс.
Re: Использование структуры в многопоточном приложении
ГМ>Какие есть идеи по корректному использованию такой глобальной структуры при минимальном изменении кода существуюших функций?
Я что-то не понял, в чем подвох. Использовать обертки, в которых применять объекты синхронизации перед вызовом оригинальных функций. Или я чего-то не уловил?
Да здравствует мыло душистое и веревка пушистая.
Re[2]: Использование структуры в многопоточном приложении
Здравствуйте, Vamp,
ГМ>>Какие есть идеи по корректному использованию такой глобальной структуры при минимальном изменении кода существуюших функций? V>Я что-то не понял, в чем подвох. Использовать обертки, в которых применять объекты синхронизации перед вызовом оригинальных функций. Или я чего-то не уловил?
--
В своих (новых) функциях я так смогу сделать, а вот как это сделать в старом коде, который менять не хочется?
C уважением,
Геннадий Майко.
Re[2]: Использование структуры в многопоточном приложении
Здравствуйте, jerry_ru,
ГМ>>Какие есть идеи по корректному использованию такой глобальной структуры при минимальном изменении кода существуюших функций?
_>1. Если надо написать быстро, то можно использовать своеобразный getter, который возвращает pair<mutex_lock, resource*>.
--
Не будет ли здесь проблем с кодом типа:
{
...
ptStrcut->FieldA = 20;
ptStrcut->FiedlB = ptStruct->FiledC;
int LocalVar = ptStruct->FieldD;
...
}
_>2. Если API небольшой то можно полность инкапсулировать код, продублировать интерфейс, и более-менее эффективо использовать ресурс.
--
Увы, интерфейс (т.е. объем структур) очень большой. Наверное, будет сделать трудно.
C уважением,
Генадий Майко.
Re[3]: Использование структуры в многопоточном приложении
ГМ>В своих (новых) функциях я так смогу сделать, а вот как это сделать в старом коде, который менять не хочется?
Планируется одновременно обращаться к объектам и из старого проекта, и из нового? Сдается мне, что это не очень хорошая мысль.
Да здравствует мыло душистое и веревка пушистая.
Re[4]: Использование структуры в многопоточном приложении
Здравствуйте, Vamp,
ГМ>>В своих (новых) функциях я так смогу сделать, а вот как это сделать в старом коде, который менять не хочется? V>Планируется одновременно обращаться к объектам и из старого проекта, и из нового? Сдается мне, что это не очень хорошая мысль.
--
Нет, одновременно будет работать или старый, или новый проект (в котором будут исползоваться "as is" функции старого проекта).
C уважением,
Геннаддий Майко.
Re[5]: Использование структуры в многопоточном приложении
ГМ>Нет, одновременно будет работать или старый, или новый проект (в котором будут исползоваться "as is" функции старого проекта).
Ну тогда я не вижу проблемы. Переименовываешь старые функции в ..._thread_unsafe и заводишь новые — с именами старых, но объектами синхронизации.
Да здравствует мыло душистое и веревка пушистая.
Re: Использование структуры в многопоточном приложении
Здравствуйте, jerry_ru,
ГМ>>Не будет ли здесь проблем с кодом типа:
ГМ>>{ ГМ>>... ГМ>>ptStrcut->FieldA = 20; ГМ>>ptStrcut->FiedlB = ptStruct->FiledC; ГМ>>int LocalVar = ptStruct->FieldD; ГМ>>... ГМ>>}
_>Да вроде недолжно: _>
Первую проблему здесь я вижу в эффективности — один locker во всех потоках. Но я могу попытаться использовать разные locker для доступа к разным частям структуры.
Вторая проблема связана с тем, что эти старые функции могут использовать довольно много других функций, которые тоже работают с этим же указателем. Здесь можно попытаться подменить описания этих функций и передать им таким образом один дополнительный параметр.
C уважением,
Шеннадий Майко.
Re[6]: Использование структуры в многопоточном приложении
Здравствуйте, Vamp,
ГМ>>Нет, одновременно будет работать или старый, или новый проект (в котором будут исползоваться "as is" функции старого проекта). V>Ну тогда я не вижу проблемы. Переименовываешь старые функции в ..._thread_unsafe и заводишь новые — с именами старых, но объектами синхронизации.
--
Именно так я и делаю, когда могу выделить функцию.
Но я не хочу переписывать функции, в которых встречается код типа:
{
...
ptStrcut->FieldA = 20;
ptStrcut->FiedlB = ptStruct->FieldC;
int LocalVar = ptStruct->FieldD;
...
}
Потому что завтра функции старого проекта могут изменится и мне будет тяжело за ним уследить.
C уважением,
Геннадий Майко.
Re[2]: Использование структуры в многопоточном приложении
I>причем локер может быть как глобальный так и локальный
--
Да, я могу сделать по функции на каждое поле структуры и использовать их в моих функция, хотя это и муторно. А как их использовать в старом коде:
{
...
ptStrcut->FieldA = 20;
ptStrcut->FiedlB = ptStruct->FieldC;
int LocalVar = ptStruct->FieldD;
...
}
C уважением,
Геннадий Майко.
Re[7]: Использование структуры в многопоточном приложении
ГМ>Потому что завтра функции старого проекта могут изменится и мне будет тяжело за ним уследить.
Понял. Я бы ввел шаг прекомпиляции со скриптом — который бы заменил имена функций в определениях, но оставил бы их в вызовах. Благо, для С это нетрудно сделать.
Да здравствует мыло душистое и веревка пушистая.
Re[3]: Использование структуры в многопоточном приложении
Здравствуйте, Геннадий Майко, Вы писали:
ГМ>Да, я могу сделать по функции на каждое поле структуры
Синхронизация, в общем случае, делается не на доступ к отдельным полям, а на операции с объектом. Я бы начал с того, что выделил интерфейс доступа к вашему глобальному объекту и чтобы доступ к полям был только через этот интерфейс. А дальше бы уже занимался навешиваем всяких guard-ов на этот интерфейс. Если тупо оставить все как есть и синхронизировать обращения к полям, то толку будет мало.
Re[3]: Использование структуры в многопоточном приложении
Здравствуйте, alsemm,
ГМ>>Да, я могу сделать по функции на каждое поле структуры A>Синхронизация, в общем случае, делается не на доступ к отдельным полям, а на операции с объектом. Я бы начал с того, что выделил интерфейс доступа к вашему глобальному объекту и чтобы доступ к полям был только через этот интерфейс. А дальше бы уже занимался навешиваем всяких guard-ов на этот интерфейс. Если тупо оставить все как есть и синхронизировать обращения к полям, то толку будет мало.
--
Да, идея неплохая. Вот я и придумаваю, как мне встроить какой-то интерфейс к моему глобальному объекту в существующий код, желательно без замены этого кода.
C уважением,
Геннадий Майко.
Re[4]: Использование структуры в многопоточном приложении
--
Да, так можно сделать.
Правда при одном и том же guard для всех функций IMHO эффективность резко упадет, потому что только одна функция потока legacy_function будет выполняться в одно и тоже время. Поэтому хотелось бы как-то обеспечить синхронизацию непосредственно при использовании полей структуры.
C уважением,
Геннадий Майко.
Re[5]: Использование структуры в многопоточном приложении
ГМ>-- ГМ>Да, так можно сделать. ГМ>Правда при одном и том же guard для всех функций IMHO эффективность резко упадет, потому что только одна функция потока legacy_function будет выполняться в одно и тоже время. Поэтому хотелось бы как-то обеспечить синхронизацию непосредственно при использовании полей структуры.
Ну можно сделать примерно так:
//гдето наверху может в синглтоне
guard full_guard;
guard write_guard;
guard read_guard;
...
//а в коде писать
{
#ifndef OLD_ONE_THREAD
scoped_lock(guard);
#endif
//а дальше вроде не менять ничего.
}
Ну и манипулировать гуардами для пущей гибкости. Хотя тут конечно очень многое зависит от кода.
тут не стоит говорить об эффективности, но как одно из самых простых решений прохляет... наверное.
Re[2]: Использование структуры в многопоточном приложении
PD>struct A {
PD> int nValue;
PD>}; // твоя структура
PD>struct AX : A {
PD> int& fnValue() {return nValue;}
PD>}; // а это я добавил - по члену на каждое поле
PD>#define A AX
PD>#define nValue fnValue()
PD>int _tmain(int argc, _TCHAR* argv[])
PD>{
PD>// это твоя исходная программа, я тут ничего не меняю
PD> A a;
PD> a.nValue = 10;
PD> A* pa = &a;
pa->nValue = 100;
PD> return 0;
PD>}
PD>
--
Я думаю, такой подход можно попробовать использовать, спасибо.
Я бы при этом еще закрыл доступ ко всем членам исходной структуры, наследуясь от нее как protected. Тогда появление новых элементов в ней вызывало бы ошибки компиляции, а не "молчаливый" доступ без защиты.
Еще одна небольшая проблема будет в том, что теперь функции исходной программы будут компилироваться как С++, а не как С; но с этим я готов смирится.