DIRECTORY IO, PropList, Random, Rope, SymTab, SystemNames, Xl, XlPrivate, XlPrivateSplit, XlService; XlServiceImpl: CEDAR MONITOR IMPORTS IO, PropList, Random, Rope, SymTab, SystemNames, Xl EXPORTS Xl, XlPrivateSplit, XlService ~ BEGIN OPEN Xl, XlPrivate; ROPE: TYPE = Rope.ROPE; badService: ERROR = CODE; trustedServiceProp: REF ATOM = NEW[ATOM ¬ $trustedServiceProp]; serviceVersion: ROPE ~ "_Cedar_ServiceVersion"; --name of X atom to distinguish services serviceTab: SymTab.Ref ~ SymTab.Create[3]; Service: TYPE = REF ServiceImplRep; ServiceImplRep: TYPE ~ RECORD [ connectionCount: INT ¬ 0, --maybe alive connections only propList: PropList.List ¬ NIL, --the real properties for clients serviceKey: ROPE ¬ NIL ]; ServiceRep: PUBLIC TYPE = ServiceImplRep; debuggingAssumeServicePerModuleInstance: BOOL ~ FALSE; --then everything is same service !!! --usefull for debugging the port of Xl to new machine debuggingHackKey: ROPE ¬ IO.PutFR1["hack serviceKey %g", IO.time[]]; InitServiceStuff: PUBLIC PROC [c: Connection] = { serviceKey: ROPE; atom: XAtom ¬ MakeAtom[c, serviceVersion]; rootWindow: Window ¬ FirstRoot[c]; ret: PropertyReturnRec; IF debuggingAssumeServicePerModuleInstance THEN serviceKey ¬ debuggingHackKey ELSE { ret ¬ GetProperty[c: c, w: rootWindow, property: atom, supposedFormat: 8]; IF ret.format#8 OR ret.type#atom OR ret.value=NIL THEN { tentativeKey: ROPE ¬ IO.PutFLR["%g %g %g", LIST[IO.time[], IO.rope[SystemNames.MachineName[]], IO.int[Random.NextInt[]]] ]; BEGIN --prevent X server bug [XlR2 of MIT] WHILE Rope.Length[tentativeKey] MOD 4 # 0 DO tentativeKey ¬ Rope.Concat[tentativeKey, " "]; ENDLOOP; END; GrabServer[c]; ret ¬ GetProperty[c: c, w: rootWindow, property: atom, supposedFormat: 8]; IF ret.format#8 OR ret.type#atom OR ret.value=NIL THEN { ChangeProperty[c, rootWindow, atom, atom, replace, serviceKey ¬ tentativeKey]; }; UngrabServer[c]; }; serviceKey ¬ NARROW[ret.value]; }; [] ¬ EntryDefineService[c, serviceKey]; }; EntryDefineService: ENTRY PROC [c: Connection, serviceKey: ROPE] RETURNS [service: Service] = { ENABLE UNWIND => NULL; service ¬ NEW[ServiceImplRep ¬ [connectionCount: 0, serviceKey: serviceKey, propList: PropList.NewPropList[]]]; IF ~SymTab.Insert[serviceTab, serviceKey, service] THEN service ¬ NARROW[SymTab.Fetch[serviceTab, serviceKey].val]; service.connectionCount ¬ service.connectionCount + 1; c.service ¬ service; c.serviceProperties ¬ service.propList; PutConnectionProp[c, trustedServiceProp, service]; }; ReleaseService: PUBLIC ENTRY PROC [c: Connection] = { ENABLE UNWIND => NULL; IF c#NIL THEN { service: Service ¬ c.service; IF service#NIL AND GetConnectionProp[c, trustedServiceProp]=service THEN { PutConnectionProp[c, trustedServiceProp, NIL]; --make sure service released once only service.connectionCount ¬ MAX[service.connectionCount - 1, 0]; IF service.connectionCount=0 THEN [] ¬ SymTab.Delete[serviceTab, service.serviceKey]; }; }; }; GetService: PUBLIC PROC [c: Connection] RETURNS [service: REF] = { service ¬ c.service }; PutProp: PUBLIC ENTRY PROC [service: REF, key: REF, val: REF ¬ NIL] = { WITH service SELECT FROM sr: REF ServiceImplRep => [] ¬ PropList.PutProp[sr.propList, key, val]; ENDCASE => RETURN WITH ERROR badService }; GetProp: PUBLIC ENTRY PROC [service: REF, key: REF] RETURNS [val: REF ¬ NIL] = { WITH service SELECT FROM sr: REF ServiceImplRep => RETURN [ PropList.GetProp[sr.propList, key] ]; ENDCASE => RETURN WITH ERROR badService }; PutServiceProp: PUBLIC PROC [c: Connection, key: REF, val: REF ¬ NIL] = { [] ¬ PropList.PutProp[c.serviceProperties, key, val] }; GetServiceProp: PUBLIC PROC [c: Connection, key: REF] RETURNS [val: REF] = { val ¬ PropList.GetProp[c.serviceProperties, key] }; GetServicePropAndInit: PUBLIC PROC [c: Connection, key: REF, init: InitializeProcType] RETURNS [val: REF] = { WrapInit: PropList.InitializeProcType = {val ¬ init[NARROW[data], key]}; val ¬ PropList.GetPropOrInit[c.serviceProperties, key, WrapInit, c].val }; END. δ XlServiceImpl.mesa Copyright Σ 1988, 1989, 1990, 1991, 1992 by Xerox Corporation. All rights reserved. Created by Christian Jacobi, April 27, 1988 4:10:20 pm PDT Christian Jacobi, May 8, 1992 3:35 pm PDT Willie-s, November 25, 1991 4:47 pm PST --the service is put on a property of the connection so we are sure about decreasing the connection count only once --Problem: the removal of dead dead services is not completely guaranteed depending on how connections die. This is a minor problem since we don't intend to use big timesharing and use many many servers yet. --Possible solution: we might have list of connections anyway; service maintenance could be bound to that list. --normal case <> Κ*–(cedarcode) style•NewlineDelimiter ™codešœ™Kšœ ΟeœI™TKšœ:™:K™)K™'—K˜šΟk œ˜ K˜ZK˜—šΟn œžœž˜Kšžœ4˜;Kšžœžœ˜%—šœžœ ž˜K˜—Kšžœžœžœ˜K˜Kšœ žœžœ˜š œžœžœžœžœ˜?K™t—KšœžœΟc(˜X˜*Jš kœf™ΡJ™p—K˜Kšœ žœžœ˜#šœžœžœ˜Kšœžœ ˜9Kšœžœ !˜@Kšœ žœž˜K˜—Kšœ žœžœ˜)K˜šœ)žœžœ˜7Kš %˜%Kš 5˜5—Kšœžœžœžœ ˜DK˜šŸœžœžœ˜1Kšœ žœ˜Kšœ*˜*Kšœ"˜"Kšœž˜šžœ)˜+Kšžœ˜"šžœ˜Kšœ ™ KšœJ˜Jš žœžœžœ žœžœ˜9Kšœ ™ Kš œžœžœžœžœ žœ"žœ˜{šžœ $˜*šžœžœž˜,Kšœ.˜.Kšžœ˜—Kšžœ˜—Kšœ˜KšœJ˜Jš žœžœžœ žœžœ˜8KšœN˜NK˜—Kšœ˜K˜—Kšœ žœ ˜Kšœ˜——K˜'K˜—K˜š Ÿœžœžœžœžœ˜_Kšžœžœžœ˜Kšœ žœb˜ošžœ1žœ˜8Kšœ žœ+˜;—Kšœ6˜6K˜K˜'K˜2K˜—K˜šŸœžœžœžœ˜5Kšžœžœžœ˜šžœžœžœ˜Kšœ˜šžœ žœžœ2žœ˜JKšœ)žœ &˜UKšœžœ!˜>Kšžœžœ4˜UK˜—K˜—K˜—K˜š Ÿ œžœžœžœ žœ˜BKšœ˜Kšœ˜—K˜šŸœž œžœ žœžœžœžœ˜Gšžœ žœž˜Kšœžœ@˜GKšžœžœžœžœ ˜'—K˜—K˜šŸœž œžœ žœžœžœžœžœ˜Pšžœ žœž˜Kšœžœžœ(˜HKšžœžœžœžœ ˜'—K˜K˜—š Ÿœžœžœžœžœžœ˜IK˜4K˜—K˜š Ÿœžœžœžœžœžœ˜LK˜0K˜K˜—š Ÿœžœžœžœžœžœ˜mKšŸœ,žœ˜HK˜GK˜—K˜Kšžœ˜K˜—…—˜¦