-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[feenkcom/gtoolkit#3771] Shutdown WeakArray finalization while saving…
… an image
- Loading branch information
Showing
1 changed file
with
130 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
Extension { #name : #WeakArray } | ||
|
||
{ #category : #'*GToolkit-Utility-System' } | ||
WeakArray class >> finalizationProcess [ | ||
"The finalization process arranges to send mourn to each element of the VM's finalization queue, | ||
which is accessed via primitiveFetchMourner. The VM signals FinalizationSemaphore whenever | ||
the queue is non-empty. This process loops, waiting on the semaphore, fetches the first element | ||
of the queue and then spawns a process at a higher priority to actually send the mourn messages. | ||
If an error occurs in the higher priority mourn loop process then this process will simply spawn | ||
another process, hence ensuring that errors in finalization methods don't break finalization. | ||
In addition this process also runs the old finalization scheme, supporting clients of the older, | ||
WeakRegistry based scheme. Hopefully this will go away when all clients have moved over." | ||
<gtPharoPatch: #Pharo11> | ||
| throttle firstMourner | | ||
throttle := Semaphore new. | ||
[true] whileTrue: [FinalizationSemaphore wait; initSignals. | ||
"Support the old scheme until things have changed over..." | ||
MournLoopProcess := [firstMourner := self primitiveFetchMourner. | ||
firstMourner notNil] whileTrue: | ||
[[throttle signal. | ||
self mournLoopWith: firstMourner] forkAt: Processor activePriority + 1. | ||
throttle wait]] | ||
] | ||
|
||
{ #category : #'*GToolkit-Utility-System' } | ||
WeakArray class >> gtSummaryFor: aView [ | ||
<gtView> | ||
<gtClassView> | ||
|
||
^ aView columnedList | ||
title: 'Summary'; | ||
priority: 10; | ||
items: [ { | ||
'FinalizationProcess' -> (FinalizationProcess isNotNil and: [ FinalizationProcess isTerminated not ]). | ||
'FinalizationSemaphore' -> FinalizationSemaphore size. | ||
'MournLoopProcess' -> (MournLoopProcess isNotNil and: [ MournLoopProcess isTerminated not ]). | ||
'StopRequested' -> StopRequested. | ||
'StoppedSemaphore' -> StoppedSemaphore size. } ]; | ||
column: 'Item' text: #key; | ||
column: 'Value' text: #value; | ||
actionUpdateButton. | ||
] | ||
|
||
{ #category : #'*GToolkit-Utility-System' } | ||
WeakArray class >> initialize [ | ||
"Do we need to initialize specialObjectsArray?" | ||
<gtPharoPatch: #Pharo11> | ||
|
||
Smalltalk specialObjectsArray size < 42 | ||
ifTrue: [Smalltalk recreateSpecialObjectsArray]. | ||
|
||
SessionManager default | ||
registerSystemClassNamed: self name. | ||
|
||
FinalizationSemaphore := Smalltalk specialObjectsArray at: 42. | ||
StopRequested := false. | ||
StoppedSemaphore := Semaphore new. | ||
] | ||
|
||
{ #category : #'*GToolkit-Utility-System' } | ||
WeakArray class >> mournLoopWith: firstMourner [ | ||
"Send mourn to all the objects available in the mourn queue, starting | ||
with firstMourner which the sender has already extracted for us. If | ||
an error occurs here, it will break this loop but the sender will spawn | ||
another mournLoopWith: so that finalization is not broken by errors in | ||
individual cases." | ||
<gtPharoPatch: #Pharo11> | ||
| mourner | | ||
mourner := firstMourner. | ||
[ StopRequested ifTrue: | ||
[ StoppedSemaphore signal. | ||
MournLoopProcess := nil. | ||
^ self ]. | ||
mourner mourn. | ||
(mourner := self primitiveFetchMourner) notNil] whileTrue. | ||
MournLoopProcess := nil. | ||
] | ||
|
||
{ #category : #'*GToolkit-Utility-System' } | ||
WeakArray class >> restartFinalizationProcess [ | ||
"kill any old process, just in case" | ||
<gtPharoPatch: #Pharo11> | ||
Stdio stdout | ||
<< 'WeakArray>>restartFinalizationProcess - restarting'; | ||
lf. | ||
self stopFinalizationProcess. | ||
|
||
FinalizationSemaphore := Smalltalk specialObjectsArray at: 42. | ||
StopRequested := false. | ||
StoppedSemaphore ifNil: | ||
[ StoppedSemaphore := Semaphore new ]. | ||
FinalizationProcess := [self finalizationProcess] | ||
forkAt: Processor userInterruptPriority. | ||
FinalizationProcess name: 'WeakArray Finalization Process' | ||
] | ||
|
||
{ #category : #'*GToolkit-Utility-System' } | ||
WeakArray class >> shutDown: quitting [ | ||
<gtPharoPatch: #Pharo11> | ||
|
||
self stopFinalizationProcess | ||
] | ||
|
||
{ #category : #'*GToolkit-Utility-System' } | ||
WeakArray class >> startUp: resuming [ | ||
<gtPharoPatch: #Pharo11> | ||
|
||
self restartFinalizationProcess | ||
] | ||
|
||
{ #category : #'*GToolkit-Utility-System' } | ||
WeakArray class >> stopFinalizationProcess [ | ||
<gtPharoPatch: #Pharo11> | ||
|
||
FinalizationProcess ifNotNil: | ||
[FinalizationProcess terminate. | ||
FinalizationProcess := nil]. | ||
|
||
MournLoopProcess ifNil: [ ^ self ]. | ||
self assert: StoppedSemaphore isSignaled not. | ||
StopRequested := true. | ||
Stdio stdout | ||
<< 'WeakArray>>stopFinalizationProcess - waiting for process shutdown'; | ||
lf. | ||
StoppedSemaphore wait. | ||
Stdio stdout | ||
<< 'WeakArray>>stopFinalizationProcess - shutdown complete'; | ||
lf. | ||
] |