Я работаю с большой старой кодовой базой C (интерпретатором), которая широко использует глобальные переменные, в результате чего у меня не может быть двух ее экземпляров одновременно. Существует ли простой (идеально автоматизированный) подход для преобразования этого кода во что-то повторяющееся? то есть какой-нибудь инструмент рефакторинга, который сделает все глобальные переменные частью структуры и добавит указатель на все переменные?
Могу ли я преобразовать в C ++ и обернуть все это в определение класса?
Я бы порекомендовал преобразовать ваш проект в проект C ++ 11 и изменить все ваши статические переменные в threadlocal
,
Это может занять до нескольких дней работы в зависимости от размера вашего проекта. В некоторых случаях это будет работать.
Я не знаю ни одного «готового» решения для этого типа проблемы.
Как правило, глобальные переменные затрудняют повторный ввод кода.
Если вы можете удалить все глобальные переменные [просто удалите глобальные переменные и посмотрите, где вы получите ошибки компилятора]. Замените глобальные переменные структурой, а затем используйте структуру для каждого переданного экземпляра, и с этим можно справиться (если состояние экземпляров интерпретатора является независимым и экземплярам не нужно знать о каждом из них). Другой). [Конечно, вам может потребоваться иметь более одной структуры для решения проблемы, но ваши глобальные переменные должны иметь возможность «прилипать к структуре»].
Конечно, создание структуры и кода вместе в виде класса C ++ (который может иметь меньшие классы в качестве части решения) было бы «следующим шагом», но это не совсем просто сделать, если вы не знакомы с C ++ и дизайном классов.
Вы пытаетесь сделать его реентерабельным, чтобы иметь возможность сделать его многопоточным и разделить работу между потоками?
Если это так, я хотел бы рассмотреть возможность сделать его многопоточным, а не многопоточным,
Что я обычно делаю с интерпретаторами, так это сразу иду в класс с экземплярами vars, а не с глобальными. Не уверен, что вы интерпретируете, но может быть возможно передать путь к файлу или контейнер строки, который класс интерпретирует с внутренним потоком, таким образом инкапсулируя весь прогон интерпретации.
Можно обернуть все это в определение класса, но это не сработает для кода, который принимает адреса функций и передает их в C-код. Кроме того, преобразование большой базы унаследованного кода для компиляции с помощью компилятора C ++ достаточно утомительно, что, вероятно, перевешивает усилия по удалению глобальных переменных вручную.
За исключением этого, у вас есть два варианта:
Поскольку для реализации многопоточности требуется повторное включение, может быть проще всего объявить все глобальные переменные токарно-местный. Если у вас есть компилятор C, который поддерживает локальные потоки, это обычно так же просто, как пощечина __thread
(или другое ключевое слово для конкретного компилятора) перед каждым объявлением. Затем вы создаете новый интерпретатор просто путем создания нового потока и инициализации интерпретатора обычным способом.
Если вы не можете использовать __thread
или эквивалент, тогда вы должны сделать немного больше работы. Вам необходимо поместить все глобальные переменные в структуру и заменить каждый доступ к глобальной переменной. foo
с get_ctx()->foo
, Это утомительно, но просто. Как только вы закончите, get_ctx()
может выделить и вернуть состояние локального интерпретатора потока, используя API по вашему выбору.
Инструмент преобразования программ, который может обрабатывать язык Си, сможет автоматизировать такие изменения.
Он должен иметь возможность разрешать каждый символ в своем объявлении, и условные выражения препроцессора, вероятно, будут проблемой. Я бы назвал один, но НАСТОЛЬКО фанатичный объект, когда я это делаю.
Ваше решение структуры, содержащей глобальные переменные, является правильной идеей; вам нужно переписать, чтобы заменить каждое глобальное объявление элементом слота, и каждый доступ к глобальному с доступом к соответствующему члену структуры.
Остается вопрос, откуда берется указатель структуры? Одним из ответов является глобальная переменная, которая мультиплексируется при переключении потоков; лучший ответ, если он доступен в вашей ОС, это получить указатель структуры из локальных переменных потока.