On 25 Sep 2014, at 6:23 , Eliot Miranda <[email protected]> wrote:
> Hi Henry, > > On Thu, Sep 25, 2014 at 8:25 AM, Henrik Johansen > <[email protected]> wrote: > Just read an old blogpost of Nicolas Cellier's today that suggested something > like this, and thought it sounded interesting. > It's use would be for parallell operations that involve IO delays (the > example in the post was MCRepositoryGroup >> #includesVersionNamed:) > An important assumption would be that the blocks are free of side-effects, so > evaluation completion/order is not relied upon for further correct operation. > > The goal would be to be able to write the method in question like this: > > includesVersionNamed: aString > " check for existing version name in parallel over all repositories " > > ^self repositories threadedAnySatisfy: [:repository | repository > includesVersionNamed: aString ] > > while preserving the important property of anySatisfy: that is returns as > soon as an element evaluates true. > > Here's a sample implementation: > > Collection >> #threadedAnySatisfy: aBlock > Cool. But please call it parallelAnySatisfy: or anySatisfyInParallel:. I agree, parallelAnySatisfy: is a better name. (In Norwegian it's written parallell , I guess I was subconsciously trying to prevent a high rate of spelling errors, at the cost of an inferior name ;) ) > Are you sure there are no parallel hazards in the includesVersionNamed code? Good question, I would imagine it might do some caching that could lead to inconsistent state if arbitrarily terminated as in the example implementation, but I haven't checked closely*... Cheers, Henry * I'm don't think it's used, but this might be a candidate: cacheAllFileNamesDuring: aBlock cacheFileNames == true ifTrue: [ ^ aBlock value ]. allFileNames := nil. cacheFileNames := true. <-- If this is a suspension point, if terminated, the file names would be static from the next call to allFileNames until the next time cacheAllFiles... is used --> ^ aBlock ensure: [ allFileNames := nil. cacheFileNames := false] If the need is guarding against arbitrary termination, not just errors in the block itself, I think it would have to be: ^[allFileNames := nil. cacheFileNames := true. aBlock value ] ensure: [allFileNames := nil. cacheFileNames := false] Of the actually called methods from includesVersionNamed:, I stopped checking after stumbling into, and spending too much time wondering why the code did what it did: MCFileBasedRepository >> #readableFileNames | all cached new emptyFilenamelength | "<hyphenated-package-name>.<dotted.branch.tag>-<initials>.<count>.mcz" emptyFilenamelength := 'P-i.c.mcz' size. all := self allFileNames. "from repository" all := all reject: [ :each | each size < emptyFilenamelength]. "first stupid way to filter first level broken files. Ideally we should remove any files not following the naming pattern: PackageName-author.number[(branch)].mcz" cached := self cachedFileNames. "in memory" new := all difference: cached. ^ (cached asArray, new) select: [:ea | self canReadFileNamed: ea] Removing cached entries from all entries, then iterating on the remaining + cached? That's an aweful lot of nonsense for the clearly essential capability to say you are able to read files that have recently been deleted from the file system...
signature.asc
Description: Message signed with OpenPGP using GPGMail
