'From Squeak3.7alpha of ''11 September 2003'' [latest update: #5526] on 6 November 2003 at 12:47:08 pm'! "Change Set: CollectionAtRandom Date: 6 November 2003 Author: Lukas Renggli md: Just the latest version with a correct chanset preamble... ;-) -additional changes (and [et] [er]) from stepane. The message #atRandom is not thread-save when being used concurrently on different collections or integers. As a test try to evaluate the following expressions in your image, the random generator provided by Collection gets corrupted: [ [ (1 to: 100) atRandom ] repeat ] forkAt: 30. [ [ 100 atRandom ] repeat ] forkAt: 30. This is a critical bug!! As an example the superb web-framework Seaside uses random key-generation to identify its sessions. If other threads in your image use #atRandom problems might arise. The attached change-set solves the problem by introducing a critical section to the Collection class providing the random generator."! Object subclass: #Collection instanceVariableNames: '' classVariableNames: 'MutexForPicking RandomForPicking ' poolDictionaries: '' category: 'Collections-Abstract'! !Collection methodsFor: 'accessing' stamp: 'sd 11/4/2003 22:05'! atRandom "Answer a random element of the receiver. Uses a shared random number generator owned by class Collection. If you use this a lot, define your own instance of Random and use #atRandom:. Causes an error if self has no elements." ^ self class mutexForPicking critical: [ self atRandom: self class randomForPicking ] "Examples: #('one' 'or' 'the' 'other') atRandom (1 to: 10) atRandom 'Just pick one of these letters at random' atRandom #(3 7 4 9 21) asSet atRandom (just to show it also works for Sets) "! ! !Collection class methodsFor: 'private' stamp: 'lr 11/4/2003 12:07'! initialize "Set up a Random number generator to be used by atRandom when the user does not feel like creating his own Random generator." RandomForPicking _ Random new. MutexForPicking _ Semaphore forMutualExclusion! ! !Collection class methodsFor: 'private' stamp: 'lr 11/4/2003 12:08'! mutexForPicking ^ MutexForPicking! ! !Integer methodsFor: 'truncation and round off' stamp: 'lr 11/4/2003 12:14'! atRandom "Answer a random integer from 1 to self. This implementation uses a shared generator. Heavy users should their own implementation or use Interval>atRandom: directly." self = 0 ifTrue: [ ^0 ]. self < 0 ifTrue: [ ^self negated atRandom negated ]. ^Collection mutexForPicking critical: [ self atRandom: Collection randomForPicking ]! ! Collection initialize!