Mark M. | has entered the room |
Mark M. | turned on guest access |
Sep 30 | 7:25 PM |
Steve S. | has entered the room |
Steve S. |
Hi, Mark!
|
Mark M. |
hi, Steve!
|
Mark M. |
how can I help you today?
|
Steve S. |
Let me paste in my question:
|
Steve S. |
I am trying to understand how to use WeakReference. I have found an example in a book and have a question about the example. Here's the example:
|
Steve S. |
View paste
(1 more line)
|
Steve S. |
My question is this: what guarantees that there won't be a potential timing problem, where mOuter is set to null after checking it for null but before mField is set?
|
Mark M. |
I had to re-read your earlier comment, thinking that the code was from *my* book
|
Mark M. |
I gave up on Hungarian notation about 17 years ago :-)
|
Steve S. |
sorry - no!
|
Mark M. |
I don't see where mOuter can be set to null, though
|
Mark M. |
only SampleThread has access to the mOuter field
|
Mark M. |
and it's not setting mOuter to null anywhere
|
Sep 30 | 7:30 PM |
Steve S. |
ok. what i means is that mOuter.get() would return null
|
Steve S. |
*meant
|
Mark M. |
ah
|
Mark M. |
yes, there is a potential synchronization problem here
|
Steve S. |
ok
|
koral | has entered the room |
Mark M. |
if WeakReference were atomic, you could address this by temp=mOuter.get() and then working with temp
|
Mark M. |
but I don't see in the WeakReference JavaDocs anyplace that indicates that WeakReference is atomic
|
Steve S. |
ok
|
Mark M. |
(BTW, hello, koral -- I will be with you shortly!)
|
Steve S. |
The reason I'm looking into this is that I'm writing a service with inner thread classes
|
Steve S. |
In the version I have now, the classes are genuine inner classes (i.e. not static).
|
Steve S. |
but I know it would be better to make them static
|
Steve S. |
for one of them i need access to the service instance (to call stopSelf())
|
Steve S. |
so i'm trying to figure out a reasonable approach
|
Steve S. |
do you have any suggestions?
|
Mark M. |
the use case for a WeakReference is in the case where the thread might somehow outlive its parent
|
Steve S. |
ok
|
Mark M. |
in your scenario, so long as you're sure that your thread will not outlive the service, you do not need a WeakReference
|
Steve S. |
ok. what about if the threads might (briefly) outlive the service?
|
Sep 30 | 7:35 PM |
Mark M. |
you will briefly leak the Service instance
|
Mark M. |
and if you try calling methods on the Service instance, you could run into problems, as the service will be destroyed
|
Steve S. |
so that wouldn't be a real problem since the leak would be brief?
|
Steve S. |
ok
|
Mark M. |
that depends entirely upon how you define a "real problem"
|
Steve S. |
right
|
Mark M. |
let me take a question from koral, and I will be with you in a bit
|
Steve S. |
sure
|
Mark M. |
koral: your turn! do you have a question?
|
koral |
Hi
|
koral |
I wan't to disable simultaneous motion and key events
|
koral |
e.g. don't allow to go back using ESC key while some button is pressed
|
koral |
for MotionEvents themselves there are flags
|
Sep 30 | 7:40 PM |
koral |
windowEnableSplitTouch and splitMotionEvents
|
koral |
is there anything similar for combination of MotionEvent and KeyEvent
|
koral |
?
|
Mark M. |
not that I am aware of
|
Mark M. |
my guess is that you would need to keep track of your state ("is the button pressed?") and then consume the key event in those cases
|
Mark M. |
but, I have not tried doing anything like that, so I do not know how practical it will be
|
koral |
yep, currently I'm using something like that:
|
koral |
View paste
|
koral |
but I wondered if there is a cleaner/better way
|
Mark M. |
nothing that I know of
|
koral |
OK, thanks anyway
|
Mark M. |
if you're into RxJava, you could look at using RxBindings and try to manage the event stream appropriately
|
Mark M. |
but otherwise, AFAIK, what you have is a likely approach
|
Mark M. |
let me take another question from Steve, and I'll return to you in a bit
|
Mark M. |
Steve: your turn! do you have another question?
|
Steve S. |
Following up, on my earlier question:
|
Steve S. |
What would be a reasonable approach to calling mService.stopSelf() from a static nested class, where mService refers to the service instance?
|
Sep 30 | 7:45 PM |
Mark M. |
um, the only way to call stopSelf() on mService is mService.stopSelf()
|
Mark M. |
which suggests that I do not understand your question
|
Steve S. |
I could avoid a memory leak if I use a WeakReference. But then there is the race condition, and mService could become null after i cehck it. Is there an alternative?
|
Mark M. |
the code sample you posted has a race condition
|
Mark M. |
but that's because the code sample is trying to look *inside* mOuter
|
Steve S. |
ok
|
Mark M. |
if you have a WeakReference<Service>, and the only thing that can reach that WeakReference is the thread, you can't have a race condition on the Service instance itself
|
Steve S. |
sorry - i think i'm being dense. is there a way that the code above could be modified to make it correct?
|
Mark M. |
in your code sample, mOuter cannot be null, but things inside of mOuter are what they are
|
Sep 30 | 7:50 PM |
Steve S. |
ok
|
Sep 30 | 7:50 PM |
Mark M. |
yes, stop trying to work with mField
|
Steve S. |
i see
|
Mark M. |
and be very careful about too many cooks spoiling the broth (i.e., too many things trying to manage your service's state)
|
Steve S. |
so the parallel for my case would be: don't call mService.stopSelf() from the nested class?
|
Mark M. |
that should be fine, so long as nothing else is trying to stop the service
|
Mark M. |
that's my point about too many things trying to manage your service's state
|
Steve S. |
i see
|
Steve S. |
but couldn't the OS call onDestroy() at any time?
|
Mark M. |
only if your process is being terminated, or something else stopped the service
|
Mark M. |
hence, once again, that's my point about too many things trying to manage your service's state
|
Steve S. |
ok. that's the only other way the service would be stopped
|
Mark M. |
if the *only* place in *your* code where the service is stopped is in that thread, then you should be in OK shape... at least prior to Android 8.0
|
Mark M. |
(and even there, if this is a foreground service)
|
Steve S. |
ok
|
Mark M. |
let me take another question from koral, and I'll return to you in a bit
|
Steve S. |
sure
|
Mark M. |
koral: back to you! do you have another question?
|
Sep 30 | 7:55 PM |
koral |
No more questions from me
|
Mark M. |
OK
|
Mark M. |
if you come up with another one while you're still here, let me know
|
Mark M. |
Steve: back to you!
|
Steve S. |
Following up: I could change the nested class so that mService.stopSelf() is called only from the main thread. Would that be a better approach or would it make any difference?
|
Mark M. |
that's difficult for me to answer in the abstract
|
Steve S. |
ok
|
Mark M. |
in general, you want *one* place managing this state
|
Mark M. |
for this particular method (stopSelf()), the specific thread should not matter
|
Sep 30 | 8:00 PM |
Steve S. |
my thinking was that if I were to call stopSelf() from the main thread, then i could avoid any race condition since onDestroy() is also called from the main thread
|
Mark M. |
that may help
|
Steve S. |
ok
|
Steve S. |
thanks, Mark. this has been very helpful.
|
Steve S. |
no more questions today
|
Mark M. |
happy to be useful!
|
Mark M. |
OK
|
Steve S. |
have a great rest of the day!
|
Mark M. |
you too!
|
Steve S. | has left the room |
Sep 30 | 8:30 PM |
Mark M. |
that'
|
Mark M. |
er, that's a wrap for today's chat
|
Mark M. |
the transcript will be posted to https://commonsware.com/office-hours/ shortly
|
Mark M. |
the next chat is Tuesday at 4pm US Eastern
|
Mark M. |
have a pleasant day!
|
koral | has left the room |
Mark M. | turned off guest access |