Hi Neil

On Tue, May 2, 2017 at 10:10 PM, Neil Bartlett <njbartl...@gmail.com> wrote:
> I think I get what Dirk is saying, and although I disagree with some of his 
> analysis there is arguably a gap in the DS specification that makes this 
> unclear. I hope somebody can point at the vital sentence I have missed, but 
> here is my analysis:
>
> The JLS defines happens-before thus: "Two actions can be ordered by a 
> happens-before relationship. If one action happens-before another, then the 
> first is visible to and ordered before the second.” 
> (https://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.4.5 
> <https://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.4.5>).
>
> Define two actions, A1 and A2. A1 is the setting of an @Reference field in a 
> component. A2 is reading the value of that field. It is Dirk’s contention 
> that no provable happens-before relationship edge exists between A1 and A2, 
> and therefore it’s possible for A2 to access the value of the @Reference 
> field that obtained before A1. Let’s see.
>
> A1 is an action that is taken by SCR on an object that it creates (the 
> component instance). A2 can only occur in the following circumstances:
>
> 1. SCR itself reads the field.
> SCR is in full control of its own code and I am assuming a correct SCR 
> implementation.
>
> 2. The activate method of the component uses the value of the field.
> Section 112.3.8.1 of OSGi Compendium R6 states "there is a happens-before 
> relationship between setting the field and activating the component 
> instance”. Also section 112.3.6.1 states “The bind method is called and/or 
> the field is set before the component instance is activated”, which is less 
> clear about the happens-before but I think the intent is there, and it also 
> clarifies that this applies to bind methods as well as injected fields. 
> Therefore action A1 happens-before A2 in this case.
>
> Note that the spec does not tell the implementation HOW to achieve this 
> happens-before edge. As Dirk points out, if it is done with a synchronized 
> block then it would have to be on the same monitor. For example, the 
> implementation can achieve this by synchronizing on the component instance 
> itself when binding fields and calling the activate method.
>
> 3. The activate method starts a thread which uses the value of the field (I 
> think this maps to Dirk’s HTTP-serving example).
> From point 2 above, we know that A1 happens-before the activate method is 
> invoked. JLS 17.4.5 states that “a call to start() on a thread happens-before 
> any actions in the started thread”. JLS also states that happens-before is 
> transitive, i.e. if X happens-before Y and Y happens-before Z then X 
> happens-before Z.
>
> Therefore A1 happens-before A2 in this case.
>
> 4. Service method(s) on the component use the value of the field.
> The analysis here diverges for immediate vs delayed components.
>
> For immediate components, Compendium section 112.5.3 states: "If an immediate 
> component configuration is satisfied and specifies a service, SCR must 
> register the component configuration as a service in the service registry and 
> then activate the component configuration”. This does NOT state that the 
> registration of the service must happen after the binding of the reference 
> fields. So it seems an implementation is free to hand the service object to a 
> consumer before the static references are bound. This surprised me.

Agreed, I am especially surprised at the order of "[...] register the
component configuration as a service in the service registry and then
activate the component configuration [...]". I would have expected it
is first activated and then registered as a service.

>
> For delayed components, Compendium section 112.5.4 states: "When the service 
> is requested … SCR must create and activate a [unique] component 
> configuration”. It does NOT explicitly state that the static references must 
> be bound before the service object is handed to the caller of getService(). 
> Again this surprised me.
>

I think "112.5.6 Activation" clarifies that "activation" means more
than just calling the activate method. It summarizes the following
steps with the term "activation":

1. Load the component implementation class.
2. Create the component instance and component context.
3. Bind the target services.
4. Call the activate method, if present.

So you could even consider section 112.5.4 a bit verbose, it could be
reduced to "... SCR must activate a [unique] component configuration"
;)

On a more serious note: I think due to the definition of "activation",
it is clear that all references must be set before the caller gets the
object.

Regards
Julian

>
> In summary, it’s clear to me that the *intention* of the specification is for 
> static references to be bound before the service becomes accessible, and that 
> component writers should not have to declare those fields volatile, but this 
> intention is not adequately spelled out. The best statement I could find is 
> in section 112.3.6.1: "A component instance never sees any of the dynamics of 
> the static reference”, which is very vague.
>
> Again, I may well have missed something or made an error in my analysis. I 
> look forward to be being corrected.
>
>
> Neil
>
>
>> On 2 May 2017, at 19:56, David Jencks <david.a.jen...@gmail.com> wrote:
>>
>> I don’t understand your example or I don’t understand how your example 
>> relates to an osgi or ds problem.
>>
>> I think you are proposing that the DS component is an http server and starts 
>> threads etc.  If so, it’s that components responsibility to make sure its’ 
>> internal operations are thread safe, and this has little to do with osgi or 
>> ds.
>>
>> If you are asking about osgi, for instance if the component exposes 
>> HttpServlet and is registered with the whiteboard http service and receives 
>> calls from it, then the whiteboard had to call getService to get the DS 
>> component instance. In this case I think that there are plenty of 
>> synchronization barriers in the service registry and in e.g. 
>> SingleComponentManager.getService to assure that the view a request thread 
>> has of the component is the same as the view the activation thread had.
>>
>> I could be wrong about whether there are actually enough synchronization 
>> barriers.  Have you looked at the code to see?
>>
>> thanks
>> david jencks
>>
>>> On May 2, 2017, at 10:45 AM, Dirk Hogan <dirk.ho...@forgerock.com> wrote:
>>>
>>> Hi Raymond-
>>> Assume Felix does it's thing: sets all @References, activates all
>>> components, publishes all services. It has resolved all dependencies, and
>>> set references accordingly.
>>>
>>> Thus, in the example above, myOSGiComponent has its @Reference to
>>> SomeOtherOSGiService resolved - Felix has set this reference. At the
>>> conclusion of the activate method, myOSGiComponent has exposed some
>>> functionality via http, even successfully dereferenced myOSGiComponent, and
>>> now requests start to come it, serviced by the http-server's thread-pool.
>>> Part of servicing this request involves dereferencing (reading) the
>>> @Reference myServiceReference, which, I agree has been set (written) by a
>>> Felix thread.
>>>
>>> The point of the Java Memory Model is that memory state, including
>>> references, read and written across threads, do not have to have
>>> determinate state, unless there is a Synchronization Action which ensures
>>> that the state written by thread A is visible to any other thread - a
>>> volatile reference provides such a Synchronization Action. So code in
>>> myOSGiComponent activate method can successfully dereference the
>>> SomeOtherOSGiService reference, because the same thread which set the
>>> reference is calling activate. But this does NOT mean that another thread,
>>> reading the SAME reference, will see a properly initialized reference.
>>>
>>> Again, this should be self-evident, and the various rules of the JMM model
>>> are defined in section 17.4 of the Java Language Specification. If it is
>>> not clear, then an understanding if the JMM is required. This understanding
>>> can be gained by reading the JLS, reading the links above, the chapter
>>> in *Concurrency
>>> in Practice* on the JMM,  or http://gee.cs.oswego.edu/dl/cpj/jmm.html
>>> provides a good intro.
>>>
>>> The bottom line: memory state, including references, shared among multiple
>>> threads can have indeterminate state when written/read, unless explicit
>>> steps, defined in the JMM, are taken to ensure this visibility and thus
>>> coherent state. This is not an opinion.
>>>
>>> Thanks
>>>
>>> Dirk
>>>
>>>
>>>
>>> On Tue, May 2, 2017 at 10:23 AM, Raymond Auge <raymond.a...@liferay.com>
>>> wrote:
>>>
>>>> On Tue, May 2, 2017 at 1:18 PM, Raymond Auge <raymond.a...@liferay.com>
>>>> wrote:
>>>>
>>>>>
>>>>>
>>>>> On Tue, May 2, 2017 at 1:14 PM, Raymond Auge <raymond.a...@liferay.com>
>>>>> wrote:
>>>>>
>>>>>>
>>>>>> On Tue, May 2, 2017 at 11:46 AM, Dirk Hogan <dirk.ho...@forgerock.com>
>>>>>> wrote:
>>>>>>
>>>>>>> But no similar guarantee applies when another thread hits the
>>>>>>> component,
>>>>>>>
>>>>>>
>>>>>> I believe the discussion boils down to why you believe the above is
>>>>>> possible?
>>>>>>
>>>>>> If SCR has not yet made the component available to other threads (which,
>>>>>> to my knowledge, it only does by registering it as a service to the
>>>> service
>>>>>> registry) how can _another_ thread access the component at all?
>>>>>>
>>>>>> I don't even see a way for components within the same DS bundle to
>>>>>> interact with each other other than via the service registry because
>>>>>> @Reference only works through the registry.
>>>>>>
>>>>>
>>>>> Correction, components could interact with each other via the
>>>>> ComponentContext.. but I guess we'd have to know if that's part of your
>>>> use
>>>>> case.
>>>>>
>>>>
>>>> Actually, no, it's not even possible via the ComponentContext. It only
>>>> allows access to Services.
>>>>
>>>>>
>>>>> - Ray
>>>>>
>>>>>
>>>>>>
>>>>>> Please, can you explain in more detail what case might allow for the
>>>>>> above? Because I believe the assumption is that it's not currently
>>>>>> possible. Certainly there could be a bug and I'm certain everyone would
>>>>>> want to see that fixed.
>>>>>>
>>>>>> --
>>>>>> *Raymond Augé* <http://www.liferay.com/web/raymond.auge/profile>
>>>>>> (@rotty3000)
>>>>>> Senior Software Architect *Liferay, Inc.* <http://www.liferay.com>
>>>>>> (@Liferay)
>>>>>> Board Member & EEG Co-Chair, OSGi Alliance <http://osgi.org>
>>>>>> (@OSGiAlliance)
>>>>>>
>>>>>
>>>>>
>>>>>
>>>>> --
>>>>> *Raymond Augé* <http://www.liferay.com/web/raymond.auge/profile>
>>>>> (@rotty3000)
>>>>> Senior Software Architect *Liferay, Inc.* <http://www.liferay.com>
>>>>> (@Liferay)
>>>>> Board Member & EEG Co-Chair, OSGi Alliance <http://osgi.org>
>>>>> (@OSGiAlliance)
>>>>>
>>>>
>>>>
>>>>
>>>> --
>>>> *Raymond Augé* <http://www.liferay.com/web/raymond.auge/profile>
>>>> (@rotty3000)
>>>> Senior Software Architect *Liferay, Inc.* <http://www.liferay.com>
>>>> (@Liferay)
>>>> Board Member & EEG Co-Chair, OSGi Alliance <http://osgi.org>
>>>> (@OSGiAlliance)
>>>>
>>
>

Reply via email to