"======================================================================
|
|   MethodDictionary Method Definitions
|
|   $Revision: 1.7.5$
|   $Date: 2000/05/28 16:56:52$
|   $Author: pb$
|
 ======================================================================"


"======================================================================
|
| Copyright 1988-92, 1994-95, 1999, 2000 Free Software Foundation, Inc.
| Written by Paolo Bonzini.
|
| This file is part of the GNU Smalltalk class library.
|
| The GNU Smalltalk class library is free software; you can redistribute it
| and/or modify it under the terms of the GNU Lesser General Public License
| as published by the Free Software Foundation; either version 2.1, or (at
| your option) any later version.
| 
| The GNU Smalltalk class library is distributed in the hope that it will be
| useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser
| General Public License for more details.
| 
| You should have received a copy of the GNU Lesser General Public License
| along with the GNU Smalltalk class library; see the file COPYING.LESSER.
| If not, write to the Free Software Foundation, 59 Temple Place - Suite
| 330, Boston, MA 02111-1307, USA.  
|
 ======================================================================"


IdentityDictionary variableSubclass: #MethodDictionary
	   instanceVariableNames: ''
	   classVariableNames: ''
	   poolDictionaries: ''
	   category: 'Language-Implementation'
!

IdentityDictionary comment:
'I am similar to an IdentityDictionary, except that removal and
rehashing operations inside my instances look atomic to the
interpreter.' !


!MethodDictionary methodsFor: 'adding'!

at: key put: value
    "Store value as associated to the given key"
    super at: key put: value.
    Behavior flushCache.
    ^value
! !


!MethodDictionary methodsFor: 'removing'!

removeAssociation: anAssociation
    "Remove anAssociation's key from the dictionary"

    "The interpreter might be using this MethodDictionary while
    this method is running!!  Therefore we perform the removal
    in a copy, and then atomically become that copy"
    | copy result |
    (self includesKey: anAssociation key) ifFalse: [ ^self error: 'key not found' ].
    copy := self copy.
    result := copy dangerouslyRemoveAssociation: anAssociation.
    self become: copy.
    Behavior flushCache.
    ^result
!

removeKey: anElement ifAbsent: aBlock
    "Remove the passed key from the dictionary, answer the result of
     evaluating aBlock if it is not found"

    "The interpreter might be using this MethodDictionary while
    this method is running!!  Therefore we perform the removal
    in a copy, and then atomically become that copy"
    | copy result |
    (self includesKey: anElement) ifFalse: [ ^aBlock value ].
    copy := self copy.
    result := copy dangerouslyRemoveKey: anElement ifAbsent: aBlock.
    self become: copy.
    Behavior flushCache.
    ^result
! !


!MethodDictionary methodsFor: 'rehashing'!

rehash
    "Rehash the receiver"
    "The interpreter might be using this MethodDictionary while
    this method is running!!  Therefore we create a copy that
    has correct hashing (it is built on the fly), then atomically
    become that copy"
    self growBy: 0
! !


!MethodDictionary methodsFor: 'private methods'!

dangerouslyRemoveAssociation: anAssociation
    "This is not really dangerous.  But if normal removal
    were done WHILE a MethodDictionary were being used, the
    system might crash.  So instead we make a copy, then do
    this operation (which is NOT dangerous in a copy that is
    not being used), and then use the copy after the removal."

    ^super removeAssociation: anAssociation
!

dangerouslyRemoveKey: anElement ifAbsent: aBlock
    "This is not really dangerous.  But if normal removal
    were done WHILE a MethodDictionary were being used, the
    system might crash.  So instead we make a copy, then do
    this operation (which is NOT dangerous in a copy that is
    not being used), and then use the copy after the removal."

    ^super removeKey: anElement ifAbsent: aBlock
! !