XlExtensionsImpl.mesa
Copyright Ó 1993 by Xerox Corporation. All rights reserved.
Christian Jacobi, February 2, 1993 2:12:41 pm PST
Christian Jacobi, February 3, 1993 12:13 pm PST
DIRECTORY Atom, RefTab, RuntimeError, Xl, XlDispatch, XlExtensions, XlPrivateTypes;
XlExtensionsImpl:
CEDAR
MONITOR
LOCKS c
USING c: Connection
IMPORTS Atom, RefTab, Xl, XlDispatch
EXPORTS Xl, XlExtensions
SHARES XlPrivateTypes =
BEGIN OPEN Xl, XlExtensions;
<<Xl.>>ConnectionPrivate: PUBLIC TYPE = XlPrivateTypes.ConnectionPrivateImplRec;
extensionClassTable: RefTab.Ref ¬ RefTab.Create[];
ProcessExtensionEvent:
PUBLIC
PROC [xEvent:
REF Xl.EventRep.extension]
RETURNS [
BOOL] = {
dispatch: BYTE ~ xEvent.originalCodeByte MOD 128;
IF dispatch>=XlExtensions.firstExtension
THEN {
cp: REF XlPrivateTypes.ConnectionPrivateImplRec ~ xEvent.connection.cPriv;
ext: Extension ~ cp.extensions[dispatch];
IF ext#
NIL
THEN {
cont: XlExtensions.ExtensionContinue;
xEvent.extension ¬ ext.class.key;
cont ¬ ext.class.processEvents[ext, xEvent];
SELECT cont
FROM
dispatch => {XlDispatch.FindAndDispatch[xEvent]; RETURN [FALSE]};
noop => RETURN [FALSE];
reuse => RETURN [TRUE];
ENDCASE;
};
};
RETURN [TRUE];
};
DefineExtensionClass:
PUBLIC
PROC [key:
ATOM, processEvents: ProcessExtensionEventProc, majorEventsCnt:
NAT] = {
s: REF ExtensionClass ¬ NEW[ExtensionClass ¬ [key: key, processEvents: processEvents, majorEventsCnt: majorEventsCnt]];
[] ¬ RefTab.Store[extensionClassTable, key, s];
};
StartExtension:
PUBLIC
PROC [c: Connection, key:
ATOM]
RETURNS [e: Extension ¬
NIL] = {
Protected:
PROC [c: Connection, key:
ATOM]
RETURNS [Extension] = {
ex: Extension; class: REF ExtensionClass; qer: QueryExtensionRec;
cp: REF XlPrivateTypes.ConnectionPrivateImplRec ~ c.cPriv;
WITH RefTab.Fetch[cp.extensionTab, key].val
SELECT
FROM
ex: Extension => RETURN [ex];
x: ATOM => RETURN [NIL];
ENDCASE => {};
WITH RefTab.Fetch[extensionClassTable, key].val
SELECT
FROM
x: REF ExtensionClass => class ¬ x;
ENDCASE => RETURN [NIL];
qer ¬ Xl.QueryExtension[c, Atom.GetPName[key] !
Xl.XError, UNCAUGHT => {qer.presentOnServer ¬ FALSE; CONTINUE}
];
IF ~qer.presentOnServer
THEN {
[] ¬ RefTab.Store[cp.extensionTab, key, $no];
RETURN [NIL];
};
ex ¬ NEW[ExtensionRec ¬ [majorOpcode: qer.majorOpcode, firstEvent: qer.firstEvent, firstError: qer.firstError, class: class]];
FOR i:
NAT
IN [0..class.majorEventsCnt)
DO
cp.extensions[ex.firstEvent+i] ¬ ex;
ENDLOOP;
[] ¬ RefTab.Store[cp.extensionTab, key, ex];
RETURN [ex];
};
DefineExtensionTab:
ENTRY
PROC [c: Connection, cp:
REF XlPrivateTypes.ConnectionPrivateImplRec] = {
IF cp.extensionTab=NIL THEN cp.extensionTab ¬ RefTab.Create[];
};
cp: REF XlPrivateTypes.ConnectionPrivateImplRec ~ c.cPriv;
IF cp.extensionTab=NIL THEN DefineExtensionTab[c, cp];
WITH RefTab.Fetch[cp.extensionTab, key].val
SELECT
FROM
ex: Extension => RETURN [ex];
x: ATOM => RETURN [NIL];
ENDCASE => {};
EnterExtensionLock[c];
e ¬ Protected[c, key ! UNCAUGHT => CONTINUE];
LeaveExtensionLock[c];
};
extensionLock: REF ~ NEW[INT];
checkAgain: CONDITION;
EnterExtensionLock:
ENTRY
PROC [c: Connection] = {
cp: REF XlPrivateTypes.ConnectionPrivateImplRec ~ c.cPriv;
WHILE cp.extensionLock DO WAIT checkAgain ENDLOOP;
cp.extensionLock ¬ TRUE;
};
LeaveExtensionLock:
ENTRY
PROC [c: Connection] = {
cp: REF XlPrivateTypes.ConnectionPrivateImplRec ~ c.cPriv;
cp.extensionLock ¬ FALSE;
BROADCAST checkAgain
};
END.