Hi Richard- I have a embedded jetty OSGi component that exposes the conglomeration of OSGi services to the outside world. Felix would need to set these service references in a thread-safe way. You appear to be suggesting that Felix can be only consumed by the Felix threads themselves, as only that would not bypass 'the hidden synchronization inside the framework' - whatever that is.
Let me try one more time: a while back, Felix mandated that DYNAMIC @References be volatile. Presumably that decision was made by someone who knows the JMM, and thus could provide a response to the question in my initial post: Perhaps an explanation as to why a DYNAMIC @Reference does need to be volatile would be helpful - e.g. why does component de-activation/re-activation provide memory visibility guarantees for STATIC references? I don't mean to be contentious, and there is nothing preventing me from declaring my @References volatile. I just was hoping that there was JMM-knowledge active in this forum which could provide an answer to my original question. I may well have my answer. Thanks Dirk On Tue, May 2, 2017 at 2:29 PM, Richard S. Hall <he...@ungoverned.org> wrote: > Dirk, > > Allow I'm not well versed on the details of JMM. I think this boils down > to typical OSGi component code will be going through the hidden barriers in > the the framework when they try to retrieve and access the service objects. > You appear to be concocting a situation where you have threads from outside > that you have given access to OSGi service components and bypassing the > hidden synchronization inside the framework. If you can create such a > scenario, then it is up to you to safely publish these objects when you > hand them off to this other thread. And the only way this is really > problematic is if your handoff is done in such a way that you bypass all > barriers to begin with. > > -> richard > > > > On 5/2/17 16:27 , Dirk Hogan wrote: > >> Hi Neil- >> OK - now we are getting somewhere. >> >> You need to dig a bit deeper to see what establishes a happens-before >> relationship. For within a single thread, it is the Program Order: the >> underlying virtual machine cannot allow the visibility of memory effects >> which contradict the sequence of instructions defined in your .java file, >> even though these commands will be re-ordered by the compiler, and >> pipelined and executed concurrently by machine cores. >> >> Between threads, it is the Synchronization Order, which is NOT Program >> Order. Between threads, the memory effects of your .java file writes/reads >> do NOT have to be honored. So if you say 'But Felix writes the reference >> before publishing the service', and thus concluding that the reference >> will >> always be present in the service, you are correct, but ONLY from the >> perspective of the thread which wrote the reference and published the >> service. For ALL other threads, all bets are off, unless there is a >> Synchronization Action (volatile reference read/write, monitor lock/unlock >> on the same monitor) which dictates a Synchronization Order of the >> visibility of memory effects between DISTINCT threads. >> >> The definition of Synchronization Actions, how they combine to create a >> Synchronization Order, and how this, in turn, allows a happens-before >> relationship to be established, is a formal set of rules defined in the >> JMM. There is no ambiguity here. A read of section 17.4 will illuminate as >> much. It is very dense - that is why I turned to the other references I >> provided in the links above. They are not a quick/easy read, but are >> necessary to coherently reason about memory visibility across threads. >> >> Thanks >> >> Dirk >> >> On Tue, May 2, 2017 at 1: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. >>> >>> 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. >>> >>> >>> 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) >>>>>> >>>>>> >>> >