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

Attachment: signature.asc
Description: Message signed with OpenPGP using GPGMail

Reply via email to