- •05.12.12 Лекция 12
- •Темпоральная логика
- •Определение Модальной логики
- •Динамически порождаемые процессы
- •Радиус-сервер интернет-телефонии
- •Спецификация скелета радиус-сервера.
- •Главный процесс радиусСервер
- •Сеанс входящего звонка
- •Авторизация внешнего абонента, номера и пути
- •Сеанс звонка
- •Сеанс исходящего звонка
- •Авторизация внутреннего абонента
- •Свойства спецификации сеанса
- •Реализация скелета радиус-сервера
- •Этап4. Замена receive на if
- •Этап6. Сборка обработчика из разных кусков сопрограммы
- •class SEANCE {
- •else if (AuthPathBillingReply(ID j, bool ответ))
- •Реализация для ненадежных каналов
- •Изменившаяся часть реализации радиус-сервера
- •Процессорная спецификация языка исчисления вычислимых предикатов
- •type ID;
- •Исполнение программы
- •runRight(SECT s, RIGHT right) {
- •Исполнение параллельной композиции
else if (AuthPathBillingReply(ID j, bool ответ))
{СИТ ! AuthPathReply(ответ); if (se.stop) #stop;
if (ответ) $sCall else if (se.outgoing) $sAuthNumPath else #stop
}
else if (AuthOutgoingBillingReply(ID j, bool ответ)) { СИТ ! AuthOutgoingReply(ответ);
if (se.stop) #stop; if (ответ) $sAuthNumPath else $sKey
}
else if (Key(ID j))
{БС ! KeyBilling(ID j); $sKeyBilling } else if (KeyBillingReply(bool ответ))
{СИТ ! KeyReply(ответ);
if (se.stop) #stop; if ( ответ) $sKey else $sAuthNumPath
}
else if (Stop(ID j))
if (se.state in {sAuthNum, sCall, sKey, sAuthNumPath}) #stop else se.stop = true
else if (AuthNum(ID j))
{БС ! AuthNumBilling(); $sAuthNumBilling } else if (AuthPath(ID j))
{БС ! AuthPathBilling(); $sAuthPathBilling }
else if (StartCall(ID j)) $sStartCall;
else if (StartTalk(ID j)) $sTalk
else if (StopTalk(ID j)) $sStopTalk;
else if (StopCall(ID j)) { БС ! CallBilling(); if (se.stop) #stop
else if (se.outgoing) $sAuthNumPath else #stop
};
stop: БС ! StopBiling(); удалитьСеанс(se.id) #loop
}
Реализация для ненадежных каналов
Особенности ненадежных каналов: потеря, дублирование, изменение порядка сообщений
Цепочки следования сообщений:
AuthIncomingPath {StartCal, StartTalk, StopTalk, StopCall, Stop} AuthIncoming AuthPath {StartCal, StartTalk, StopTalk, StopCall, Stop}
AuthOutgoing Key AuthNum AuthPath {StartCal, StartTalk, StopTalk, StopCall, Stop}
Спецификация процесса сеансЗвонка меняется !
В четверке сообщений StartCal, StartTalk, StopTalk, StopCall значимыми являются только StopTalk и StopCall.
Используется таймер, чтобы избежать дедлок в случае потери сообщений
Сообщения, относящиеся к предыдущему звонку, могут прийти при обработке очередного звонка необходимо уметь распознавать принадлежность сообщения звонку в случае серии звонков в одном сеансе хранить информацию о всех звонках серии
Stop() завершает сеанс лишь в случае завершения сеанса звонка (получения StopCall)
Изменившаяся часть реализации радиус-сервера
else if (AuthNumBillingReply(ID j, bool ответ)) { СИТ ! AuthNumReply(ответ);
if (se.stop) if (se.completedAll()) #stop else SetTimeout() else if ( ответ) if (se.outgoing) $sAuthNumPath else #stop else if (se.outgoing se.incomingPath) $sAuthNum
else { БС ! AuthPathBilling(); $sAuthPathBilling }
}
else if (Stop())
if (se.state = sKey) #stop else se.stop = true else if (StopTalk() StopCall())
if ( (se.stop se.outgoing) & se.completedAll() ) { БС ! CallBilling(); #stop }
Почти все специальные внутренние состояния становятся ненужными
Процессорная спецификация языка исчисления вычислимых предикатов
Процессорная спецификация описывает
функционирование процессора языка программирования.
Операционная семантика языка исчисления вычислимых предикатов, определяемая предикатной программой исполнения программы на языке исчисления
Кодирование программы и данных
type NAME; |
// множество всевозможных имен |
|
|
type TYPE; |
// множество произвольных типов |
|
|
type VAR = struct NAME name, TYPE type end; |
// переменная |
||
type SVAR = seq VAR; |
// список переменных |
|
type PREDNAMES = set NAME; // набор имен предикатов программы type Program(PREDNAMES predNames) = array predNames of PredicateDef; type PredicateDef = struct SVAR in, out, local, RIGHT right end;
type RIGHT = |
|
|
union |
|
|
super: |
CALL fst, snd | // суперпозиция fst; snd |
|
paral: |
CALL fst, snd | // параллельная композиция fst || snd |
|
alter: |
VAR cond, CALL then, else | |
|
|
// if cond then then else else end |
|
gen: |
NAME predName, SVAR in1, in2, out | |
|
|
// lambda(in2: out) predName(in1, in2: out) |
|
appl: |
NAME predName, SVAR in, out | |
// predName(in: out) |
arrcons: |
VAR arr, NAME predName, range, SVAR in2, rangepars | |
|
base: |
// forAll i range(rangepars) do arr[i] = predName(i, in2) end |
|
// базисный предикат исчисления |
||
end; |
|
|
type CALL = struct NAME predName, SVAR in, out end; // вызов предиката
type VALUE; |
// значение произвольного типа |
|
type SVALUE = seq VALUE; |
// список значений |
|
type QNAME = set NAME; |
|
type SECT(QNAME sn) = array sn of VALUE; // секция памяти
type ID; |
// генеральное множество имен секций |
|
type SID = set ID; |
// тип подмножества имен секций |
type MEMORY(SID sip) = array sip of SECT; // память программы
Операции над секциями
newSect(SVAR q: SECT s, ID id)
id sip & profileSect(q: s) & sip’ = sip + id & mem’ = mem + (id: s); val(SECT s, VAR x: VALUE v) v = s[x];
assign(SECT s, VAR x, VALUE v: SECT s’) s[x] := v s’ = s(x: v); multival(SECT s, SVAR z: SVALUE w) w = s[z]
if z = nil then w = nil else w = s[head(z)] + multival(s, tail(z)) end; multiassign(SECT s, SVAR z, SVALUE w: SECT s’) s[z] := w
if z = nil then s’ = s
else multiassign(s(head(z): head(w)), tail(z), tail(w): s’) end;
delSect(ID id: ) id sip sip’ = sip - id & mem’= mem[sip’];
Исполнение программы
Program prog; PREDNAMES predNames;
runProgram(NAME startPred, SVALUE pars: SVAR results) startPred predNames {
PredicateDef p = prog[startPred]; newSect(p.in + p.out: SECT s, ID id); s[p.in] := pars;
runCall(s, startPred, p.in, p.out); results:= s[p.out];
};
Исполнение вызова предиката
runCall(SECT sext, NAME predName, SVAR in, SVAR out) predName predNames {
PredicateDef p = prog[startPred]; newSect(p.in + p.out + p.local: SECT s, ID id); s[p.in] := sext[in];
runRirht(s, p.right); sext[out] := s[p.out]; delSect(id)
};
runRight(SECT s, RIGHT right) { |
|
|
case right of |
|
|
super: |
runSuper(SECT s, CALL fst, snd) |
| |
paral: |
runParal(SECT s, CALL fst, snd) |
| |
alter: |
runIf(SECT s, VAR cond, CALL then, else) |
| |
gen: |
runLambda(SECT s, NAME predName, SVAR in1, in2, out) | |
||
|
// lambda(in2: out) predName(in1, in2: out) |
||
appl: |
|
|
|
runApplPred(SECT s, NAME predName, SVAR in, out) | |
|||
arrcons: |
runForAll(SECT s, VAR arr, NAME predName, range, |
||
|
|
|
SVAR in2, rangepars) | |
base: |
// forAll i range(rangepars) do arr[i] = predName(i, in2) end |
||
runBasePred(SECT s) // базисный предикат исчисления |
|||
end |
|
|
|
};
Исполнение суперпозиции runSuper(SECT s, CALL fst, snd) {
runCall(s, fst.predName, fst.in, fst.out); runCall(s, snd.predName, snd.in, snd.out);
};
Исполнение параллельной композиции
runParal(SECT s, CALL fst, snd) {
runCall(s, fst.predName, fst.in, fst.out) || runCall(s, snd.predName, snd.in, snd.out);
};
Исполнение условного оператора
runIf(SECT s, VAR cond, CALL then, else) {
if s[cond] then runCall(s, then.predName, then.in, then.out) else runCall(s, else.predName, else.in, else.out) end
};