-- $Id: java_object_api.ty,v 1.8 10/.0/.2 .1:.1:.5 mrusso Exp $ -- /***************************************************************************/ -- /* Copyright (C) 1997-1999 INRIA Sophia-Antipolis */ -- /* I. Attali, D. Caromel and M. Russo */ -- /* Projet OASIS */ -- /* 2004. route des Lucioles, BP 93 */ -- /* F-06902 Sophia Antipolis cedex */ -- /* (+33) 4 92 38 76 31 */ -- /* All rights reserved */ -- /***************************************************************************/ -- -- /***************************************************************************/ -- /* This file contains the API specifications for the class Object */ -- /* as well as functionnalities for the WaitSet data */ -- /***************************************************************************/ program java_object_api is use java; use PSP; import ENVchangeObjectStatusInStatusList ( ObjectId ) , ENVsendObjectList ( Objects ) from java_environment; import getObject ( ObjectId |- Objects -> Object ) , getObjectLockInformation ( ObjectId |- Objects -> ObjectId, integer ) , releaseObjectLock ( ObjectId |- Objects -> Objects ) , setNewThreadStatus ( ObjectId, ThreadStatus, ClassVariablesL |- Objects -> Objects ) , createExceptionObject ( Objects, ObjectId |- Identifier, ExceptText -> ObjectId, Objects, Insts ) from java_object_list; import appendtree ( _, _, _ ) , diff ( _, _ ) from prolog() ; set ObjectAPI is --SC: Performs all the Object constructors and methods. -- --SC: Specified constructor and methods: --SC: Object() --SC: notify() --SC: notifyAll() --SC: wait() -- --JC: Object list, Class variable list, Current executing thread reference, --JC: Current object reference --JC: |- Method or Constructor name, Argument list (maybe an empty list) --JC: -> modified object list, modified class variable list, --JC: Continuation instruction list (maybe empty), new current Thread status. judgement Objects, ClassVariablesL, Ref, Ref |- Identifier, java -> Objects, ClassVariablesL, Insts, ThreadStatus; Object: ObjL, ClVarL, _, ObjId |- identifier "Object", vals[] -> ObjL, ClVarL, insts[clr(ObjId, identifier "none", identifier "Object", env(pairs[], locs[]), insts[])], runnable() ; Notify: --RC: Wakes up a single thread that is waiting on this object monitor. -- --CS: ObjId.notify(); --PC: A check is done to be sure that the given object is locked by the --PC: current executing thread The oldest dormant thread of the wait set --PC: is taken, its status becomes blocked on 'ObjId' instead of --PC: dormant=> waiting for nb locks on 'ObjId'. getObjectLockInformation( ObjId |- ObjL1 -> OThId, nb ) & diff( nb, 0 ) & makeBlockedTheOldestDormantThread( ObjId |- ObjL1 -> ObjL1_1 ) -------------------------------- ObjL1, ClVarL, OThId, ObjId |- identifier "notify", vals[] -> ObjL1_1, ClVarL, insts[], runnable() ; Notify_Exception: --RC: An exception is thrown because the current object is not locked by --RC: the current thread. So the Notify() method cannot be executed. -- --CS: ObjId1.notify(); getObjectLockInformation( ObjId1 |- ObjL1 -> OThId2, _ ) & diff( OThId1, OThId2 ) & createExceptionObject( ObjL1, OThId1 |- identifier "IllegalMonitorStateException", exceptText "Method 'notify' called on a non locked object." -> _, ObjL1_1, InstL ) -------------------------------- ObjL1, ClVarL, OThId1, ObjId1 |- identifier "notify", vals[] -> ObjL1_1, ClVarL, InstL, runnable() ; NotifyAll: --RC: Wakes up all threads that are waiting on this object monitor. -- --CS: ObjId.notifyAll(); --PC: checks that the given object is locked by the current executing --PC: thread 'OThId'. Takes all the threads which are in the wait set of --PC: the object 'ObjId'. Also makes their status blocked on 'ObjId' --PC: instead of dormant=> waiting for nb locks on 'ObjId'. getObjectLockInformation( ObjId |- ObjL1 -> OThId, nb ) & diff( nb, 0 ) & makeBlockedAllDormantThreads( ObjId |- ObjL1 -> ObjL1_1 ) -------------------------------- ObjL1, ClVarL, OThId, ObjId |- identifier "notifyAll", vals[] -> ObjL1_1, ClVarL, insts[], runnable() ; NotifyAll_Exception: --RC: An exception is thrown because the current object is not locked by --RC: the current thread. -- --CS : ObjId1.notifyAll(); getObjectLockInformation( ObjId1 |- ObjL1 -> OThId2, 0 ) & diff( OThId1, OThId2 ) & createExceptionObject( ObjL1, OThId1 |- identifier "IllegalMonitorStateException", exceptText "Method 'notifyAll' called on a non locked object." -> _, ObjL1_1, InstL ) -------------------------------- ObjL1, ClVarL, OThId1, ObjId1 |- identifier "notifyAll", vals[] -> ObjL1_1, ClVarL, InstL, runnable() ; Wait: --RC: Makes the current thread "dormant", adds it to the wait set of the current --RC: object and releases the locks on the current object. The current thread is --RC: disabled for thread scheduling until another thread call the notifyAll method --RC: on the current object (or the notify method). -- --CS: ObjId.wait(); --PC: Checks that the object 'ObjId' is locked by the current executing --PC: thread 'OThId' and determines how many times the object is locked --PC: (nb times). --PC: Adds the thread identifier 'OThId' to the wait set of the object 'ObjId'. --PC: Releases the nb locks on the object 'ObjId'. getObjectLockInformation( ObjId |- ObjL1 -> OThId, nb ) & diff( nb, 0 ) & addThreadToTheObjectWaitSet( OThId, ObjId |- ObjL1 -> ObjL1_1 ) & releaseObjectLock( ObjId |- ObjL1_1 -> ObjL1_2 ) -------------------------------- ObjL1, ClVarL, OThId, ObjId |- identifier "wait", vals[] -> ObjL1_2, ClVarL, insts[synchroWaitEndRelock(ObjId, integer nb)], dormant(ObjId, integer nb) ; do ENVchangeObjectStatusInStatusList( ObjId ); Wait_Exception: --RC: An exception is thrown because the current object is not locked by --RC: the current thread. -- --CS : ObjId1.wait(); getObjectLockInformation( ObjId1 |- ObjL1 -> _, 0 ) & createExceptionObject( ObjL1, OThId1 |- identifier "IllegalMonitorStateException", exceptText "Method 'wait' called on a non locked object." -> _, ObjL1_1, InstL ) -------------------------------- ObjL1, ClVarL, OThId1, ObjId1 |- identifier "wait", vals[] -> ObjL1_1, ClVarL, InstL, runnable() ; end ObjectAPI; set makeBlockedTheOldestDormantThread is --SC: Changes the status of the oldest dormant thread of the wait set of the --SC: given object into blocked -- --JC: object reference (for which the wait set needs to be changed) --JC: |- objects of the program --JC: -> updated object list --JC: (i.e. the wait set of the given object has changed) judgement ObjectId |- Objects -> Objects; --iJC: objects, object reference, the Wait set --iJC: |- the new Wait Set (empty at the beginning) --iJC: => updated object list judgement Objects, ObjectId, Waits |- Waits => Objects; GetTheWaitSetOfTheGivenObject: getObject( ObjId |- ObjL1 -> object(ObjId, _, _, _, WaitSet, _) ) & ObjL1, ObjId, waits[] |- WaitSet => ObjL1_1 -------------------------------- ObjId |- ObjL1 -> ObjL1_1 ; EmptyWaitSet: ObjL, _, waits[] |- waits[] => ObjL ; IsTheOldestDormantThread: setNewThreadStatus( OThId, blocked(ObjId), classVariablesL[] |- ObjL1 -> ObjL1_1 ) & setNewWaitSet( ObjL1_1, WaitL |- ObjId -> ObjL1_2 ) -------------------------------- ObjL1, ObjId, WaitL |- waits[OThId] => ObjL1_2 ; RecursiveRule_NotTheOldestDormantThreadOfTheWaitSet: appendtree( WaitL1, waits[OThId], WaitL1_1 ) & ObjL1, ObjId, WaitL1_1 |- OThIdL => ObjL1_1 -------------------------------- ObjL1, ObjId, WaitL1 |- waits[OThId.OThIdL] => ObjL1_1 ; end makeBlockedTheOldestDormantThread; set makeBlockedAllDormantThreads is --SC: Changes the status of all the "dormant" threads of the wait set of the --SC: given object into blocked. Updates the status list and the --SC: interpretation environment. -- --JC1: Object reference --JC1: |- objects --JC1: -> updated object list (i.e. all the objects contained in the wait set --JC1: of the given object have changed their status into blocked) judgement ObjectId |- Objects -> Objects; --JC2: Objects, Object reference --JC2: |- Wait set of the given object --JC2: => updated object list judgement Objects, ObjectId |- Waits => Objects; GetTheObject: getObject( ObjId1 |- ObjL1 -> object(ObjId1, _, _, _, WaitSet, _) ) & ObjL1, ObjId1 |- WaitSet => ObjL1_1 & setNewWaitSet( ObjL1_1, waits[] |- ObjId1 -> ObjL1_2 ) -------------------------------- ObjId1 |- ObjL1 -> ObjL1_2 ; EmptyWaitSet: ObjL, _ |- waits[] => ObjL ; RecursiveRule_SetBlockedAsStatusInTheWaitSet: setNewThreadStatus( OThId, blocked(ObjId), classVariablesL[] |- ObjL1 -> ObjL1_1 ) & ObjL1_1, ObjId |- OThIdL => ObjL1_2 -------------------------------- ObjL1, ObjId |- waits[OThId.OThIdL] => ObjL1_2 ; end makeBlockedAllDormantThreads; set addThreadToTheObjectWaitSet is --SC: Adds a new thread in the wait set of an object. Updates the object list -- --JC: Thread reference that needs to be added in the wait set, --JC: Reference of the object on which this thread wants to set a lock --JC: |- objects --JC: -> Updated object list (i.e the wait set of the given object will --JC: contain the reference of the given thread) judgement ObjectId, ObjectId |- Objects -> Objects; GetObject_AddNewThreadInItsWaitSet: getObject( ObjId |- ObjL1 -> object(ObjId, _, _, _, WaitSet, _) ) & setNewWaitSet( ObjL1, waits[OThId.WaitSet] |- ObjId -> ObjL1_1 ) -------------------------------- OThId, ObjId |- ObjL1 -> ObjL1_1 ; end addThreadToTheObjectWaitSet; set setNewWaitSet is --SC: Updates the wait set of the given object -- --JC: Objects, New wait set --JC: |- Object reference for which the wait set needs to be changed --JC: -> Modified object list judgement Objects, Waits |- ObjectId -> Objects; --iJC: judgement Objects, Waits |- ObjectId => Objects; EntryPoint_SendInfoToEnv: ObjL1, WaitSet |- ObjId => ObjL1_1 -------------------------------- ObjL1, WaitSet |- ObjId -> ObjL1_1 ; do ENVsendObjectList( ObjL1_1 ); FindTheObject_ChangeItsWaitSet: objects[object(ObjId, ClName, AttrL, Lock, _, Act).ObjL], WaitSet |- ObjId => objects[object(ObjId, ClName, AttrL, Lock, WaitSet, Act).ObjL] ; LookForTheObject: ObjL1, WaitSet1 |- ObjId1 => ObjL1_1 -------------------------------- objects[object(ObjId2, ClName, AttrL, Lock, WaitSet2, Act).ObjL1], WaitSet1 |- ObjId1 => objects[object(ObjId2, ClName, AttrL, Lock, WaitSet2, Act).ObjL1_1] ; provided diff( ObjId1, ObjId2 ); end setNewWaitSet; end java_object_api