|
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! |