SynchronizedObject.st
changeset 2888 67cd09a723a0
equal deleted inserted replaced
2887:935939d19c75 2888:67cd09a723a0
       
     1 "{ Package: 'stx:libbasic2' }"
       
     2 
       
     3 Object subclass:#SynchronizedObject
       
     4 	instanceVariableNames:'lock'
       
     5 	classVariableNames:'AccessLock'
       
     6 	poolDictionaries:''
       
     7 	category:'Kernel-Processes'
       
     8 !
       
     9 
       
    10 !SynchronizedObject class methodsFor:'documentation'!
       
    11 
       
    12 documentation
       
    13 "
       
    14     synchronized objects execute incoming messages in a serialized, synchronous manner,
       
    15     locking out other messages while executing any synchronized method.
       
    16     Synchronized methods are marked with a synchronized pragma; i.e. with '<synchronized>'.
       
    17     Non-synchronized methods behave as usual.
       
    18 
       
    19     Normally, I am subclassed, but see the example for an anonymous class example.
       
    20 
       
    21 
       
    22     [Author:]
       
    23         Claus Gittinger
       
    24 "
       
    25 !
       
    26 
       
    27 examples
       
    28 "
       
    29   normally, one would subclass SynchronizedObject and put protocol into it;
       
    30   here, for the example, an anon Printer is defined. It is slow printing to the Transcript for a demo.
       
    31   The interesting thing is the error handling which is demonstrated in printWithError:
       
    32   Any exception inside the worker object is returned back and raised in the active-object's client,
       
    33   not in the worker (take a look at the call-chain, when running the example below).
       
    34 
       
    35 
       
    36     |workerClass worker|
       
    37 
       
    38     workerClass := SynchronizedObject 
       
    39                         subclass:#Printer
       
    40                         instanceVariableNames:''
       
    41                         classVariableNames:''
       
    42                         poolDictionaries:''
       
    43                         category:nil
       
    44                         inEnvironment:nil.
       
    45 
       
    46     workerClass compile:'print:aLine
       
    47     <synchronized>
       
    48 
       
    49     aLine do:[:ch |
       
    50         Transcript show:ch.
       
    51         Delay waitForSeconds:0.2.
       
    52     ].
       
    53     Transcript cr.
       
    54 '.
       
    55 
       
    56     workerClass compile:'printWithError:aLine
       
    57     <synchronized>
       
    58 
       
    59     aLine do:[:ch |
       
    60         Transcript show:ch.
       
    61         ch == $l ifTrue:[ self foo ].
       
    62         Delay waitForSeconds:0.2.
       
    63     ].
       
    64     Transcript cr.
       
    65 '.
       
    66 
       
    67     worker := workerClass new.
       
    68     'now ready for printing'.
       
    69     worker printWithError:'abcdef'.
       
    70     worker printWithError:'hello world'.
       
    71 "
       
    72 ! !
       
    73 
       
    74 !SynchronizedObject class methodsFor:'initialization'!
       
    75 
       
    76 initialize
       
    77     AccessLock := Semaphore forMutualExclusion.
       
    78 ! !
       
    79 
       
    80 !SynchronizedObject class methodsFor:'instance creation'!
       
    81 
       
    82 new
       
    83     ^ self basicNew initializeLock initialize.
       
    84 ! !
       
    85 
       
    86 !SynchronizedObject class methodsFor:'utilities'!
       
    87 
       
    88 addSelector: selector withMethod: aMethod
       
    89     (aMethod hasAnnotation: #synchronized) ifTrue:[
       
    90         ^ super addSelector: selector withMethod: (self makeSynchronizedMethod: aMethod selector: selector)
       
    91     ].
       
    92     ^ super addSelector: selector withMethod: aMethod
       
    93 !
       
    94 
       
    95 makeSynchronizedMethod: originalMethod selector:selector
       
    96     |realMethod i|
       
    97 
       
    98     realMethod := Compiler 
       
    99                     compile: ('%1 |args|  args := thisContext args. lock critical:[ #placeHolder valueWithReceiver:self arguments:args selector:#''%2'' search: nil sender: nil ]. ^  self' 
       
   100                                 bindWith:(Compiler methodSpecificationForSelector: selector)
       
   101                                 with: selector)
       
   102                     forClass: self
       
   103                     install: false.
       
   104     realMethod category:(originalMethod category).
       
   105     realMethod source:(originalMethod source).
       
   106     i := realMethod literals indexOf: #placeHolder.
       
   107     realMethod literalAt:i put: originalMethod.
       
   108     ^ realMethod
       
   109 ! !
       
   110 
       
   111 !SynchronizedObject methodsFor:'initialization'!
       
   112 
       
   113 initializeLock
       
   114     lock := RecursionLock new.
       
   115 ! !
       
   116 
       
   117 !SynchronizedObject class methodsFor:'documentation'!
       
   118 
       
   119 version
       
   120     ^ '$Header: /cvs/stx/stx/libbasic2/SynchronizedObject.st,v 1.1 2013-01-24 15:52:14 cg Exp $'
       
   121 !
       
   122 
       
   123 version_CVS
       
   124     ^ '$Header: /cvs/stx/stx/libbasic2/SynchronizedObject.st,v 1.1 2013-01-24 15:52:14 cg Exp $'
       
   125 ! !
       
   126 
       
   127 
       
   128 SynchronizedObject initialize!