Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » EMF » Threading issue in ResourceImpl::load(InputStream, Map)
Threading issue in ResourceImpl::load(InputStream, Map) [message #429084] Tue, 07 April 2009 21:50 Go to next message
Ryan Hollom is currently offline Ryan HollomFriend
Messages: 27
Registered: July 2009
Junior Member
Hi there,

I've run into a multi-threading issue while resolving the same proxyURI
from two different threads. In ResourceImpl::load(InputStream, Map),
first, the isLoaded flag is checked to determine whether to load from the
inputStream. However, the next line sets the isLoaded flag to true,
before the resource is loaded.

Thus, a 2nd thread that comes in before the first thread is able to
complete the load will think that the resource is loaded (as the isLoaded
flag is true), and simply return. So, access of the loaded object from
that 2nd thread will fail since it is still a proxy.

Is this a known issue? I am using v. 2.4.1.

Thanks!
-Ryan
Re: Threading issue in ResourceImpl::load(InputStream, Map) [message #429085 is a reply to message #429084] Tue, 07 April 2009 22:33 Go to previous messageGo to next message
Eclipse UserFriend
Originally posted by: richkulp.us.NO_SPAM.ibm.com

Hi,

The simple answer is that EMF is not thread safe, nor is it intended to
be. Thread safety is too complicated an issue to solve by putting it
down at the EMF level. It must be done at the application level. You
must put the necessary locks in your self because only you know when EMF
objects resources could be used in more than one thread at a time.

For example even the "synchronized" collections in java are not really
thread safe. they may sync and you won't get exceptions, but the data
itself is not guaranteed to be consistent because multiple changes from
different threads can be made to the collection at the same time and the
result wouldn't be what was wanted if the threads were controlled.

Ryan Hollom wrote:
> Hi there,
>
> I've run into a multi-threading issue while resolving the same proxyURI
> from two different threads. In ResourceImpl::load(InputStream, Map),
> first, the isLoaded flag is checked to determine whether to load from
> the inputStream. However, the next line sets the isLoaded flag to true,
> before the resource is loaded.
>
> Thus, a 2nd thread that comes in before the first thread is able to
> complete the load will think that the resource is loaded (as the
> isLoaded flag is true), and simply return. So, access of the loaded
> object from that 2nd thread will fail since it is still a proxy.
>
> Is this a known issue? I am using v. 2.4.1.
>
> Thanks!
> -Ryan
>
>

--
Thanks,
Rich Kulp
Re: Threading issue in ResourceImpl::load(InputStream, Map) [message #429086 is a reply to message #429085] Tue, 07 April 2009 22:50 Go to previous messageGo to next message
Ryan Hollom is currently offline Ryan HollomFriend
Messages: 27
Registered: July 2009
Junior Member
In this case, I am simply accessing a non-contained child object, which,
until loaded, is a proxy:

myEMFObject.getEntity()

It is in the generated code for getEntity() that turns around and calls
eResolveProxy, which attempts to load the object.

So, what I hear you saying is that either every piece of generated code
that calls eResolveProxy needs to be locked, or every single call to
"getEntity()" needs to be locked. Unfortunately this will results in
hundreds of changes, and I wonder what kind of performance hit there will
be by constantly synchronizing.

As Eclipse is inherently multi-threaded, it is very difficult to know
exactly which threads will access the EMF model, as even getters can
result in resource loads.

If this is the way it must be, then I will look at changing the generated
code. It seems to me that it might be a nice code generation option to at
least sync the proxy resolution.

Thanks,
Ryan
Re: Threading issue in ResourceImpl::load(InputStream, Map) [message #429087 is a reply to message #429086] Tue, 07 April 2009 23:53 Go to previous messageGo to next message
Eclipse UserFriend
Originally posted by: richkulp.us.NO_SPAM.ibm.com

Hi,

Not really. The problem in your case is they are all using the same
resource set. If you didn't share resource sets then you could have
multiple proxy resolves because they would go to different resources in
the different resource sets.

Ed can chime in, but the answer has always been the 80% rule. Don't slow
down 80% of the users which are not multi-threaded for the rest that
are. Multi-threading is inherently tricky and sticking a sync in without
understanding the entire application rarely works.

Ryan Hollom wrote:
> In this case, I am simply accessing a non-contained child object, which,
> until loaded, is a proxy:
>
> myEMFObject.getEntity()
>
> It is in the generated code for getEntity() that turns around and calls
> eResolveProxy, which attempts to load the object.
>
> So, what I hear you saying is that either every piece of generated code
> that calls eResolveProxy needs to be locked, or every single call to
> "getEntity()" needs to be locked. Unfortunately this will results in
> hundreds of changes, and I wonder what kind of performance hit there
> will be by constantly synchronizing.
>
> As Eclipse is inherently multi-threaded, it is very difficult to know
> exactly which threads will access the EMF model, as even getters can
> result in resource loads.
>
> If this is the way it must be, then I will look at changing the
> generated code. It seems to me that it might be a nice code generation
> option to at least sync the proxy resolution.
>
> Thanks,
> Ryan
>

--
Thanks,
Rich Kulp
Re: Threading issue in ResourceImpl::load(InputStream, Map) [message #429089 is a reply to message #429087] Wed, 08 April 2009 00:20 Go to previous messageGo to next message
Ed Merks is currently offline Ed MerksFriend
Messages: 33142
Registered: July 2009
Senior Member
This is a multi-part message in MIME format.
--------------000905060207090205070607
Content-Type: text/plain; charset=ISO-8859-15; format=flowed
Content-Transfer-Encoding: 7bit

Rich,

Thanks for pointing out that there isn't a panacea thread safety
solution which EMF ought to support but just didn't get around to
providing. I.e., let's sprinkle just the right number of synchronized
calls into the EMF runtime or into the generated code. In the end,
when you share modifiable data structures across threads, a high level
threading policy for managing safety and coherence will definitely be
needed. Ryan is right to be concerned about performance, but he still
seems to believe that sprinkling locks into the mix will solve his
problems. I suppose he's not discovered deadlocks yet, but if he adds
enough synchronized calls to the generated code, he's bound to discover
that side of the coin. Good luck to those who think that sprinkling
synchronize calls will solve all their problems.

Ryan,

Here's something to consider. Even if "list" is thread safe, the
following two lines of code are not thread safe:

int index = list.indexOf(x);
list.remove(index);

In other words, thread safe primitives don't automatically produce
thread safe higher level behavior when using those primitives.


Rich Kulp wrote:
> Hi,
>
> Not really. The problem in your case is they are all using the same
> resource set. If you didn't share resource sets then you could have
> multiple proxy resolves because they would go to different resources
> in the different resource sets.
>
> Ed can chime in, but the answer has always been the 80% rule. Don't
> slow down 80% of the users which are not multi-threaded for the rest
> that are. Multi-threading is inherently tricky and sticking a sync in
> without understanding the entire application rarely works.
>
> Ryan Hollom wrote:
>> In this case, I am simply accessing a non-contained child object,
>> which, until loaded, is a proxy:
>>
>> myEMFObject.getEntity()
>>
>> It is in the generated code for getEntity() that turns around and
>> calls eResolveProxy, which attempts to load the object.
>>
>> So, what I hear you saying is that either every piece of generated
>> code that calls eResolveProxy needs to be locked, or every single
>> call to "getEntity()" needs to be locked. Unfortunately this will
>> results in hundreds of changes, and I wonder what kind of performance
>> hit there will be by constantly synchronizing.
>>
>> As Eclipse is inherently multi-threaded, it is very difficult to know
>> exactly which threads will access the EMF model, as even getters can
>> result in resource loads.
>>
>> If this is the way it must be, then I will look at changing the
>> generated code. It seems to me that it might be a nice code
>> generation option to at least sync the proxy resolution.
>>
>> Thanks,
>> Ryan
>>
>

--------------000905060207090205070607
Content-Type: text/html; charset=ISO-8859-15
Content-Transfer-Encoding: 8bit

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta content="text/html;charset=ISO-8859-15"
http-equiv="Content-Type">
</head>
<body bgcolor="#ffffff" text="#000000">
Rich,<br>
<br>
Thanks for pointing out that there isn't a panacea thread safety
solution which EMF ought to support but just didn't get around to
providing.


Ed Merks
Professional Support: https://www.macromodeling.com/
Re: Threading issue in ResourceImpl::load(InputStream, Map) [message #429100 is a reply to message #429087] Wed, 08 April 2009 13:55 Go to previous messageGo to next message
Ryan Hollom is currently offline Ryan HollomFriend
Messages: 27
Registered: July 2009
Junior Member
In this case it is the same object that is being accessed by two threads
(myEMFObject == myEMFObject), so of course the resource set is going to be
the same. This is not a problem if myEMFObject != myEMFObject.

This is purely read-only access at this point, and I wouldn't dare
endeavor to make all modifications thread-safe. I guess you could argue
that this is modifying the EObject, as it is being loaded and populated.
But it is certainly an issue that I need to solve where
myEMFObject.getEntity() returns an unresolved EObject.

Thanks for the advice and cautions.
-Ryan

Rich Kulp wrote:

> Hi,

> Not really. The problem in your case is they are all using the same
> resource set. If you didn't share resource sets then you could have
> multiple proxy resolves because they would go to different resources in
> the different resource sets.

> Ed can chime in, but the answer has always been the 80% rule. Don't slow
> down 80% of the users which are not multi-threaded for the rest that
> are. Multi-threading is inherently tricky and sticking a sync in without
> understanding the entire application rarely works.

> Ryan Hollom wrote:
>> In this case, I am simply accessing a non-contained child object, which,
>> until loaded, is a proxy:
>>
>> myEMFObject.getEntity()
>>
>> It is in the generated code for getEntity() that turns around and calls
>> eResolveProxy, which attempts to load the object.
>>
>> So, what I hear you saying is that either every piece of generated code
>> that calls eResolveProxy needs to be locked, or every single call to
>> "getEntity()" needs to be locked. Unfortunately this will results in
>> hundreds of changes, and I wonder what kind of performance hit there
>> will be by constantly synchronizing.
>>
>> As Eclipse is inherently multi-threaded, it is very difficult to know
>> exactly which threads will access the EMF model, as even getters can
>> result in resource loads.
>>
>> If this is the way it must be, then I will look at changing the
>> generated code. It seems to me that it might be a nice code generation
>> option to at least sync the proxy resolution.
>>
>> Thanks,
>> Ryan
>>
Re: Threading issue in ResourceImpl::load(InputStream, Map) [message #429101 is a reply to message #429100] Wed, 08 April 2009 15:08 Go to previous messageGo to next message
Ed Merks is currently offline Ed MerksFriend
Messages: 33142
Registered: July 2009
Senior Member
Ryan,

Comments below.

Ryan Hollom wrote:
> In this case it is the same object that is being accessed by two
> threads (myEMFObject == myEMFObject), so of course the resource set is
> going to be the same. This is not a problem if myEMFObject !=
> myEMFObject.
Oh really. So you think the resource set trying to load the same
resource on two different threads at the same time will work well?
>
> This is purely read-only access at this point, and I wouldn't dare
> endeavor to make all modifications thread-safe. I guess you could
> argue that this is modifying the EObject, as it is being loaded and
> populated. But it is certainly an issue that I need to solve where
> myEMFObject.getEntity() returns an unresolved EObject.
>
> Thanks for the advice and cautions.
Your best is likely to be to make ResourceSetImpl.getResource
synchronized for this type of scenario. That should handle a great many
cases.
> -Ryan
>
> Rich Kulp wrote:
>
>> Hi,
>
>> Not really. The problem in your case is they are all using the same
>> resource set. If you didn't share resource sets then you could have
>> multiple proxy resolves because they would go to different resources
>> in the different resource sets.
>
>> Ed can chime in, but the answer has always been the 80% rule. Don't
>> slow down 80% of the users which are not multi-threaded for the rest
>> that are. Multi-threading is inherently tricky and sticking a sync in
>> without understanding the entire application rarely works.
>
>> Ryan Hollom wrote:
>>> In this case, I am simply accessing a non-contained child object,
>>> which, until loaded, is a proxy:
>>>
>>> myEMFObject.getEntity()
>>>
>>> It is in the generated code for getEntity() that turns around and
>>> calls eResolveProxy, which attempts to load the object.
>>>
>>> So, what I hear you saying is that either every piece of generated
>>> code that calls eResolveProxy needs to be locked, or every single
>>> call to "getEntity()" needs to be locked. Unfortunately this will
>>> results in hundreds of changes, and I wonder what kind of
>>> performance hit there will be by constantly synchronizing.
>>>
>>> As Eclipse is inherently multi-threaded, it is very difficult to
>>> know exactly which threads will access the EMF model, as even
>>> getters can result in resource loads.
>>>
>>> If this is the way it must be, then I will look at changing the
>>> generated code. It seems to me that it might be a nice code
>>> generation option to at least sync the proxy resolution.
>>>
>>> Thanks,
>>> Ryan
>>>
>
>
>


Ed Merks
Professional Support: https://www.macromodeling.com/
Re: Threading issue in ResourceImpl::load(InputStream, Map) [message #429104 is a reply to message #429101] Wed, 08 April 2009 15:42 Go to previous messageGo to next message
Ryan Hollom is currently offline Ryan HollomFriend
Messages: 27
Registered: July 2009
Junior Member
> Oh really. So you think the resource set trying to load the same
> resource on two different threads at the same time will work well?
No, that's my point. The problem is that the resource is being loaded on
two different threads, with no locking.

Let me back up a bit. I am not explicitly loading the resource on two
different threads. I am calling a getter on an EObject that has a
reference to another EObject that is a proxy, which results in the
loading. In other words, myEObj.getReferenceEObj() is being called on two
different threads, for read only access. This getter is returning a
different result/EObject on Thread1 vs Thread2. Thread1 returns the
resolved/loaded EObject, but Thread2 returns the proxy, as it thinks the
object has been loaded, but it hasn't. So, merely calling
myEObj.getReferenceEObj().getName() could return 'null' on one thread and
'myName' on the other.

For memory consumption reasons, I chose to make the reference a
non-containment one. So what I am hearing is that I could either change
the base EMF code (ResourceSetImpl::getResource), or synchronize all 'high
risk' proxy resolution.

-Ryan

Ed Merks wrote:

> Ryan,

> Comments below.

> Ryan Hollom wrote:
>> In this case it is the same object that is being accessed by two
>> threads (myEMFObject == myEMFObject), so of course the resource set is
>> going to be the same. This is not a problem if myEMFObject !=
>> myEMFObject.
> Oh really. So you think the resource set trying to load the same
> resource on two different threads at the same time will work well?
>>
>> This is purely read-only access at this point, and I wouldn't dare
>> endeavor to make all modifications thread-safe. I guess you could
>> argue that this is modifying the EObject, as it is being loaded and
>> populated. But it is certainly an issue that I need to solve where
>> myEMFObject.getEntity() returns an unresolved EObject.
>>
>> Thanks for the advice and cautions.
> Your best is likely to be to make ResourceSetImpl.getResource
> synchronized for this type of scenario. That should handle a great many
> cases.
>> -Ryan
>>
>> Rich Kulp wrote:
>>
>>> Hi,
>>
>>> Not really. The problem in your case is they are all using the same
>>> resource set. If you didn't share resource sets then you could have
>>> multiple proxy resolves because they would go to different resources
>>> in the different resource sets.
>>
>>> Ed can chime in, but the answer has always been the 80% rule. Don't
>>> slow down 80% of the users which are not multi-threaded for the rest
>>> that are. Multi-threading is inherently tricky and sticking a sync in
>>> without understanding the entire application rarely works.
>>
>>> Ryan Hollom wrote:
>>>> In this case, I am simply accessing a non-contained child object,
>>>> which, until loaded, is a proxy:
>>>>
>>>> myEMFObject.getEntity()
>>>>
>>>> It is in the generated code for getEntity() that turns around and
>>>> calls eResolveProxy, which attempts to load the object.
>>>>
>>>> So, what I hear you saying is that either every piece of generated
>>>> code that calls eResolveProxy needs to be locked, or every single
>>>> call to "getEntity()" needs to be locked. Unfortunately this will
>>>> results in hundreds of changes, and I wonder what kind of
>>>> performance hit there will be by constantly synchronizing.
>>>>
>>>> As Eclipse is inherently multi-threaded, it is very difficult to
>>>> know exactly which threads will access the EMF model, as even
>>>> getters can result in resource loads.
>>>>
>>>> If this is the way it must be, then I will look at changing the
>>>> generated code. It seems to me that it might be a nice code
>>>> generation option to at least sync the proxy resolution.
>>>>
>>>> Thanks,
>>>> Ryan
>>>>
>>
>>
>>
Re: Threading issue in ResourceImpl::load(InputStream, Map) [message #429105 is a reply to message #429104] Wed, 08 April 2009 16:05 Go to previous messageGo to next message
Ed Merks is currently offline Ed MerksFriend
Messages: 33142
Registered: July 2009
Senior Member
Ryan,

Comments below.

Ryan Hollom wrote:
>> Oh really. So you think the resource set trying to load the same
>> resource on two different threads at the same time will work well?
> No, that's my point. The problem is that the resource is being loaded
> on two different threads, with no locking.
>
> Let me back up a bit. I am not explicitly loading the resource on two
> different threads. I am calling a getter on an EObject that has a
> reference to another EObject that is a proxy, which results in the
> loading.
I got that part.
> In other words, myEObj.getReferenceEObj() is being called on two
> different threads, for read only access
My point is that two different objects could try to resolve two
different reference that happen to point at the same resource. So a
lock within getReferenceEObj will not solve the problem.
> . This getter is returning a different result/EObject on Thread1 vs
> Thread2. Thread1 returns the resolved/loaded EObject, but Thread2
> returns the proxy, as it thinks the object has been loaded, but it
> hasn't. So, merely calling myEObj.getReferenceEObj().getName() could
> return 'null' on one thread and 'myName' on the other.
>
> For memory consumption reasons, I chose to make the reference a
> non-containment one. So what I am hearing is that I could either
> change the base EMF code (ResourceSetImpl::getResource), or
> synchronize all 'high risk' proxy resolution.
I'm not suggesting you change ResourceSetImpl in the base! Create a
derive one and do your specialization there...
>
> -Ryan
>
> Ed Merks wrote:
>
>> Ryan,
>
>> Comments below.
>
>> Ryan Hollom wrote:
>>> In this case it is the same object that is being accessed by two
>>> threads (myEMFObject == myEMFObject), so of course the resource set
>>> is going to be the same. This is not a problem if myEMFObject !=
>>> myEMFObject.
>> Oh really. So you think the resource set trying to load the same
>> resource on two different threads at the same time will work well?
>>>
>>> This is purely read-only access at this point, and I wouldn't dare
>>> endeavor to make all modifications thread-safe. I guess you could
>>> argue that this is modifying the EObject, as it is being loaded and
>>> populated. But it is certainly an issue that I need to solve where
>>> myEMFObject.getEntity() returns an unresolved EObject.
>>>
>>> Thanks for the advice and cautions.
>> Your best is likely to be to make ResourceSetImpl.getResource
>> synchronized for this type of scenario. That should handle a great
>> many cases.
>>> -Ryan
>>>
>>> Rich Kulp wrote:
>>>
>>>> Hi,
>>>
>>>> Not really. The problem in your case is they are all using the same
>>>> resource set. If you didn't share resource sets then you could have
>>>> multiple proxy resolves because they would go to different
>>>> resources in the different resource sets.
>>>
>>>> Ed can chime in, but the answer has always been the 80% rule. Don't
>>>> slow down 80% of the users which are not multi-threaded for the
>>>> rest that are. Multi-threading is inherently tricky and sticking a
>>>> sync in without understanding the entire application rarely works.
>>>
>>>> Ryan Hollom wrote:
>>>>> In this case, I am simply accessing a non-contained child object,
>>>>> which, until loaded, is a proxy:
>>>>>
>>>>> myEMFObject.getEntity()
>>>>>
>>>>> It is in the generated code for getEntity() that turns around and
>>>>> calls eResolveProxy, which attempts to load the object.
>>>>>
>>>>> So, what I hear you saying is that either every piece of generated
>>>>> code that calls eResolveProxy needs to be locked, or every single
>>>>> call to "getEntity()" needs to be locked. Unfortunately this will
>>>>> results in hundreds of changes, and I wonder what kind of
>>>>> performance hit there will be by constantly synchronizing.
>>>>>
>>>>> As Eclipse is inherently multi-threaded, it is very difficult to
>>>>> know exactly which threads will access the EMF model, as even
>>>>> getters can result in resource loads.
>>>>>
>>>>> If this is the way it must be, then I will look at changing the
>>>>> generated code. It seems to me that it might be a nice code
>>>>> generation option to at least sync the proxy resolution.
>>>>>
>>>>> Thanks,
>>>>> Ryan
>>>>>
>>>
>>>
>>>
>
>


Ed Merks
Professional Support: https://www.macromodeling.com/
Re: Threading issue in ResourceImpl::load(InputStream, Map) [message #429106 is a reply to message #429105] Wed, 08 April 2009 16:14 Go to previous messageGo to next message
Ryan Hollom is currently offline Ryan HollomFriend
Messages: 27
Registered: July 2009
Junior Member
> My point is that two different objects could try to resolve two
> different reference that happen to point at the same resource. So a
> lock within getReferenceEObj will not solve the problem.
This is actually a non-issue in my specific case, but I understand what
you're saying.

> Create a
> derive one and do your specialization there...
I'll give this a shot. Thanks.

Ed Merks wrote:

> Ryan,

> Comments below.

> Ryan Hollom wrote:
>>> Oh really. So you think the resource set trying to load the same
>>> resource on two different threads at the same time will work well?
>> No, that's my point. The problem is that the resource is being loaded
>> on two different threads, with no locking.
>>
>> Let me back up a bit. I am not explicitly loading the resource on two
>> different threads. I am calling a getter on an EObject that has a
>> reference to another EObject that is a proxy, which results in the
>> loading.
> I got that part.
>> In other words, myEObj.getReferenceEObj() is being called on two
>> different threads, for read only access
> My point is that two different objects could try to resolve two
> different reference that happen to point at the same resource. So a
> lock within getReferenceEObj will not solve the problem.
>> . This getter is returning a different result/EObject on Thread1 vs
>> Thread2. Thread1 returns the resolved/loaded EObject, but Thread2
>> returns the proxy, as it thinks the object has been loaded, but it
>> hasn't. So, merely calling myEObj.getReferenceEObj().getName() could
>> return 'null' on one thread and 'myName' on the other.
>>
>> For memory consumption reasons, I chose to make the reference a
>> non-containment one. So what I am hearing is that I could either
>> change the base EMF code (ResourceSetImpl::getResource), or
>> synchronize all 'high risk' proxy resolution.
> I'm not suggesting you change ResourceSetImpl in the base! Create a
> derive one and do your specialization there...
>>
>> -Ryan
>>
>> Ed Merks wrote:
>>
>>> Ryan,
>>
>>> Comments below.
>>
>>> Ryan Hollom wrote:
>>>> In this case it is the same object that is being accessed by two
>>>> threads (myEMFObject == myEMFObject), so of course the resource set
>>>> is going to be the same. This is not a problem if myEMFObject !=
>>>> myEMFObject.
>>> Oh really. So you think the resource set trying to load the same
>>> resource on two different threads at the same time will work well?
>>>>
>>>> This is purely read-only access at this point, and I wouldn't dare
>>>> endeavor to make all modifications thread-safe. I guess you could
>>>> argue that this is modifying the EObject, as it is being loaded and
>>>> populated. But it is certainly an issue that I need to solve where
>>>> myEMFObject.getEntity() returns an unresolved EObject.
>>>>
>>>> Thanks for the advice and cautions.
>>> Your best is likely to be to make ResourceSetImpl.getResource
>>> synchronized for this type of scenario. That should handle a great
>>> many cases.
>>>> -Ryan
>>>>
>>>> Rich Kulp wrote:
>>>>
>>>>> Hi,
>>>>
>>>>> Not really. The problem in your case is they are all using the same
>>>>> resource set. If you didn't share resource sets then you could have
>>>>> multiple proxy resolves because they would go to different
>>>>> resources in the different resource sets.
>>>>
>>>>> Ed can chime in, but the answer has always been the 80% rule. Don't
>>>>> slow down 80% of the users which are not multi-threaded for the
>>>>> rest that are. Multi-threading is inherently tricky and sticking a
>>>>> sync in without understanding the entire application rarely works.
>>>>
>>>>> Ryan Hollom wrote:
>>>>>> In this case, I am simply accessing a non-contained child object,
>>>>>> which, until loaded, is a proxy:
>>>>>>
>>>>>> myEMFObject.getEntity()
>>>>>>
>>>>>> It is in the generated code for getEntity() that turns around and
>>>>>> calls eResolveProxy, which attempts to load the object.
>>>>>>
>>>>>> So, what I hear you saying is that either every piece of generated
>>>>>> code that calls eResolveProxy needs to be locked, or every single
>>>>>> call to "getEntity()" needs to be locked. Unfortunately this will
>>>>>> results in hundreds of changes, and I wonder what kind of
>>>>>> performance hit there will be by constantly synchronizing.
>>>>>>
>>>>>> As Eclipse is inherently multi-threaded, it is very difficult to
>>>>>> know exactly which threads will access the EMF model, as even
>>>>>> getters can result in resource loads.
>>>>>>
>>>>>> If this is the way it must be, then I will look at changing the
>>>>>> generated code. It seems to me that it might be a nice code
>>>>>> generation option to at least sync the proxy resolution.
>>>>>>
>>>>>> Thanks,
>>>>>> Ryan
>>>>>>
>>>>
>>>>
>>>>
>>
>>
Re: Threading issue in ResourceImpl::load(InputStream, Map) [message #429107 is a reply to message #429106] Wed, 08 April 2009 16:22 Go to previous message
Ed Merks is currently offline Ed MerksFriend
Messages: 33142
Registered: July 2009
Senior Member
Ryan,

Note that EcoreUtil.resolveAll on the resource set before
multi-threading starts is a brute force way to ensure there are no
proxies left to resolve...


Ryan Hollom wrote:
>> My point is that two different objects could try to resolve two
>> different reference that happen to point at the same resource. So a
>> lock within getReferenceEObj will not solve the problem.
> This is actually a non-issue in my specific case, but I understand
> what you're saying.
>
>> Create a derive one and do your specialization there...
> I'll give this a shot. Thanks.
>
> Ed Merks wrote:
>
>> Ryan,
>
>> Comments below.
>
>> Ryan Hollom wrote:
>>>> Oh really. So you think the resource set trying to load the same
>>>> resource on two different threads at the same time will work well?
>>> No, that's my point. The problem is that the resource is being
>>> loaded on two different threads, with no locking.
>>>
>>> Let me back up a bit. I am not explicitly loading the resource on
>>> two different threads. I am calling a getter on an EObject that has
>>> a reference to another EObject that is a proxy, which results in the
>>> loading.
>> I got that part.
>>> In other words, myEObj.getReferenceEObj() is being called on two
>>> different threads, for read only access
>> My point is that two different objects could try to resolve two
>> different reference that happen to point at the same resource. So a
>> lock within getReferenceEObj will not solve the problem.
>>> . This getter is returning a different result/EObject on Thread1 vs
>>> Thread2. Thread1 returns the resolved/loaded EObject, but Thread2
>>> returns the proxy, as it thinks the object has been loaded, but it
>>> hasn't. So, merely calling myEObj.getReferenceEObj().getName()
>>> could return 'null' on one thread and 'myName' on the other.
>>>
>>> For memory consumption reasons, I chose to make the reference a
>>> non-containment one. So what I am hearing is that I could either
>>> change the base EMF code (ResourceSetImpl::getResource), or
>>> synchronize all 'high risk' proxy resolution.
>> I'm not suggesting you change ResourceSetImpl in the base! Create a
>> derive one and do your specialization there...
>>>
>>> -Ryan
>>>
>>> Ed Merks wrote:
>>>
>>>> Ryan,
>>>
>>>> Comments below.
>>>
>>>> Ryan Hollom wrote:
>>>>> In this case it is the same object that is being accessed by two
>>>>> threads (myEMFObject == myEMFObject), so of course the resource
>>>>> set is going to be the same. This is not a problem if myEMFObject
>>>>> != myEMFObject.
>>>> Oh really. So you think the resource set trying to load the same
>>>> resource on two different threads at the same time will work well?
>>>>>
>>>>> This is purely read-only access at this point, and I wouldn't dare
>>>>> endeavor to make all modifications thread-safe. I guess you could
>>>>> argue that this is modifying the EObject, as it is being loaded
>>>>> and populated. But it is certainly an issue that I need to solve
>>>>> where myEMFObject.getEntity() returns an unresolved EObject.
>>>>>
>>>>> Thanks for the advice and cautions.
>>>> Your best is likely to be to make ResourceSetImpl.getResource
>>>> synchronized for this type of scenario. That should handle a great
>>>> many cases.
>>>>> -Ryan
>>>>>
>>>>> Rich Kulp wrote:
>>>>>
>>>>>> Hi,
>>>>>
>>>>>> Not really. The problem in your case is they are all using the
>>>>>> same resource set. If you didn't share resource sets then you
>>>>>> could have multiple proxy resolves because they would go to
>>>>>> different resources in the different resource sets.
>>>>>
>>>>>> Ed can chime in, but the answer has always been the 80% rule.
>>>>>> Don't slow down 80% of the users which are not multi-threaded for
>>>>>> the rest that are. Multi-threading is inherently tricky and
>>>>>> sticking a sync in without understanding the entire application
>>>>>> rarely works.
>>>>>
>>>>>> Ryan Hollom wrote:
>>>>>>> In this case, I am simply accessing a non-contained child
>>>>>>> object, which, until loaded, is a proxy:
>>>>>>>
>>>>>>> myEMFObject.getEntity()
>>>>>>>
>>>>>>> It is in the generated code for getEntity() that turns around
>>>>>>> and calls eResolveProxy, which attempts to load the object.
>>>>>>>
>>>>>>> So, what I hear you saying is that either every piece of
>>>>>>> generated code that calls eResolveProxy needs to be locked, or
>>>>>>> every single call to "getEntity()" needs to be locked.
>>>>>>> Unfortunately this will results in hundreds of changes, and I
>>>>>>> wonder what kind of performance hit there will be by constantly
>>>>>>> synchronizing.
>>>>>>>
>>>>>>> As Eclipse is inherently multi-threaded, it is very difficult to
>>>>>>> know exactly which threads will access the EMF model, as even
>>>>>>> getters can result in resource loads.
>>>>>>>
>>>>>>> If this is the way it must be, then I will look at changing the
>>>>>>> generated code. It seems to me that it might be a nice code
>>>>>>> generation option to at least sync the proxy resolution.
>>>>>>>
>>>>>>> Thanks,
>>>>>>> Ryan
>>>>>>>
>>>>>
>>>>>
>>>>>
>>>
>>>
>
>


Ed Merks
Professional Support: https://www.macromodeling.com/
Previous Topic:How to notify parent edit providers when children are being wrapped
Next Topic:XML tranformations
Goto Forum:
  


Current Time: Fri Apr 26 15:52:40 GMT 2024

Powered by FUDForum. Page generated in 0.04278 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software

Back to the top