|
|||||||
АвтоАвтоматизацияАрхитектураАстрономияАудитБиологияБухгалтерияВоенное делоГенетикаГеографияГеологияГосударствоДомДругоеЖурналистика и СМИИзобретательствоИностранные языкиИнформатикаИскусствоИсторияКомпьютерыКулинарияКультураЛексикологияЛитератураЛогикаМаркетингМатематикаМашиностроениеМедицинаМенеджментМеталлы и СваркаМеханикаМузыкаНаселениеОбразованиеОхрана безопасности жизниОхрана ТрудаПедагогикаПолитикаПравоПриборостроениеПрограммированиеПроизводствоПромышленностьПсихологияРадиоРегилияСвязьСоциологияСпортСтандартизацияСтроительствоТехнологииТорговляТуризмФизикаФизиологияФилософияФинансыХимияХозяйствоЦеннообразованиеЧерчениеЭкологияЭконометрикаЭкономикаЭлектроникаЮриспунденкция |
Procedure OnInsert(s: string)Begin End; Проблемы: 1) затраты на дизайн; (register/unregister для поддержки некоторых обработчиков, возможость отметы вставки, синхронизация при доступе из разных потоков) Разрыв контекста (beforeInsert, afterInsert. Перехватываются обе процедуры. А если несколько потоков? Разные процедуры должны работать с 1м контекстом) 3) нарушение инварианта var InsertInProgress (B.Insert – true, A.Insert – false) В случае исключения переменная InsertInProgress остается в неправильном состоянии. Нарушение инварианта – следствие нарушения контектса. Скрытая рекурсия. Insert* (s: string) Begin InsertIvent(S) – м.б. неявная рекурсия End; Рекурсия м.б. недопустима, но компилятор обладает недостаточной информацией. A.Insert(s). Выгрузка модулей. Если модуль нужно выгрузить, возможно ли дать ОС команду «выгрузить модуль»? Нет, т.к. он может иметь ссылки с других модулей. Сама система не может удалить модель, не имеет права его выбросить. Решение всех указанных проблем – переопределение процедур. MODULE A; MODULE B PROCEDURE Insert* (S:string); IMPORT A; BEGIN PROCEDURE A.Insert+ (S:string); … BEGIN END; … … BASE(s); END A. … END; END B. Реализация: 1) перенастройка адресов (при загрузке модуля реализации В. Старое значение нужно сохранить в переменной); 2) вызов через процедурную переменную – для всех процедур модуля объявляется неявная переменная, модуль переопределяет процедуры; 3) процедура-переходник. Делается вызов процедуры-переходника, которая вызовет функцию через процедурную переменную, переходник сделает jmp. Перехват – изменение переменных, через которые делается вызов; Замена кода процедуры по месту. В 1х инструкциях сделать jmp на свою процедуру. NET компиляция происходит в промежуточный язык (полностью лишен недостатков). За счет представления программы в промежуточном языке можно осуществить перехват. Минусы: 1) сначала нужно пройтись по всему коду – затраты времени; 2) все вызовы косвенные – потеря производительности; 3) всегда есть потеря на jmp; Требует генерации специального кода компилятором. Процедура не м.б. слишком короткой (только ret на перехват).
Расширение данных Задача: модули А, В, С. В и С импортируют А. А имеет множество объектных типов. При загрузке В и С требуется доопределить поля данных в объектах, не приостанавливая их работу. 3 разных производителя, А не дает модифицировать код, В и С не знают друг о друге. MODULE Network TYPE Socket* = POINTER TO RECORD … END; PROCEDURE Send* (S: Socket; Data: String) BEGIN … END END Network; Module NetworkMonitor Import Network; TYPE SocketStat = POINTER TO RECORD CurrentSpeed: INTEGER; … END; PROCEDURE Network Send+ (S: Network.Socket; Data: String); Var Stat: SocketStat; BEGIN BASE(S, Data); Stat:= FindSocketStat(S); Stat.CurrentSpeed:= …; END; END NetworkMonitor; TYPE SocketStat = POINTER TO RECORD (Socket) … END; PROCEDURE … (S:Network.Socket; Data: String); BEGIN BASE(S,Data); S(SocketStat).CurrentSpeed:= …; Поиск по сайту: |
Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Студалл.Орг (0.004 сек.) |