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.