Github user tliron commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/207#discussion_r153007941
  
    --- Diff: aria/parser/consumption/presentation.py ---
    @@ -86,52 +73,193 @@ def dump(self):
                 self.context.presentation.presenter._dump(self.context)
     
         def _handle_exception(self, e):
    -        if isinstance(e, AlreadyReadException):
    +        if isinstance(e, _Skip):
                 return
             super(Read, self)._handle_exception(e)
     
    -    def _present(self, location, origin_location, presenter_class, 
executor):
    +    def _present_all(self):
    +        location = self.context.presentation.location
    +
    +        if location is None:
    +            self.context.validation.report('Read consumer: missing 
location')
    +            return
    +
    +        executor = self.context.presentation.create_executor()
    +        try:
    +            # This call may recursively submit tasks to the executor if 
there are imports
    +            main = self._present(location, None, None, executor)
    +
    +            # Wait for all tasks to complete
    +            executor.drain()
    +
    +            # Handle exceptions
    +            for e in executor.exceptions:
    +                self._handle_exception(e)
    +
    +            results = executor.returns or []
    +        finally:
    +            executor.close()
    +
    +        results.insert(0, main)
    +
    +        return main, results
    +
    +    def _present(self, location, origin_canonical_location, 
origin_presenter_class, executor):
             # Link the context to this thread
             self.context.set_thread_local()
     
    -        raw = self._read(location, origin_location)
    +        # Canonicalize the location
    +        if self.context.reading.reader is None:
    +            loader, canonical_location = self._create_loader(location, 
origin_canonical_location)
    +        else:
    +            # If a reader is specified in the context then we skip loading
    +            loader = None
    +            canonical_location = location
    +
    +        # Skip self imports
    +        if canonical_location == origin_canonical_location:
    +            raise _Skip()
    +
    +        if self.context.presentation.cache:
    +            # Is the presentation in the global cache?
    +            try:
    +                presentation = PRESENTATION_CACHE[canonical_location]
    --- End diff --
    
    Yes there is. An "if" statement plus a retrieval statement are non-atomic, 
and since we are in a concurrent situation it's possible that between the if 
and the retrieval that the data will removed from the cache, causing the 
retrieval to fail with an exception even though the "if" succeeded. A single 
retrieval is atomic.
    
    (This is the generally the idiomatic "Python way" to do this -- always 
choose the atomic!)


---

Reply via email to