Office Hours — Today, September 30

Thursday, September 28

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!
how can I help you today?
Steve S.
Let me paste in my question:
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:
View paste (1 more line)
public class Outer {
    private int mField;
    private static class SampleThread extends Thread {
        private final WeakReference<Outer> mOuter;

        SampleThread(Outer outer) {
            mOuter = new WeakReference<Outer>(outer);
        }

        @Override
        public void run() {
            if (mOuter.get() != null)
                mOuter.get().mField = 1;
        }
    }
...
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
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
only SampleThread has access to the mOuter field
and it's not setting mOuter to null anywhere
7:30 PM
Steve S.
ok. what i means is that mOuter.get() would return null
*meant
Mark M.
ah
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
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
In the version I have now, the classes are genuine inner classes (i.e. not static).
but I know it would be better to make them static
for one of them i need access to the service instance (to call stopSelf())
so i'm trying to figure out a reasonable approach
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?
7:35 PM
Mark M.
you will briefly leak the Service instance
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?
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
I wan't to disable simultaneous motion and key events
e.g. don't allow to go back using ESC key while some button is pressed
for MotionEvents themselves there are flags
7:40 PM
koral
windowEnableSplitTouch and splitMotionEvents
is there anything similar for combination of MotionEvent and KeyEvent
?
Mark M.
not that I am aware of
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
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:
View paste
	@Override
	public boolean dispatchTouchEvent(final MotionEvent ev) {
		final int actionMasked = ev.getActionMasked();
		isKeyEventBlocked = !(actionMasked == ACTION_CANCEL || actionMasked == ACTION_UP);
		return super.dispatchTouchEvent(ev);
	}

	@Override
	public boolean onKeyDown(final int keyCode, final KeyEvent event) {
		return isKeyEventBlocked || super.onKeyDown(keyCode, event);
	}
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
but otherwise, AFAIK, what you have is a likely approach
let me take another question from Steve, and I'll return to you in a bit
Steve: your turn! do you have another question?
Steve S.
Following up, on my earlier question:
What would be a reasonable approach to calling mService.stopSelf() from a static nested class, where mService refers to the service instance?
7:45 PM
Mark M.
um, the only way to call stopSelf() on mService is mService.stopSelf()
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
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
7:50 PM
Steve S.
ok
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
that's my point about too many things trying to manage your service's state
Steve S.
i see
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
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
(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?
7:55 PM
koral
No more questions from me
Mark M.
OK
if you come up with another one while you're still here, let me know
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
for this particular method (stopSelf()), the specific thread should not matter
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
thanks, Mark. this has been very helpful.
no more questions today
Mark M.
happy to be useful!
OK
Steve S.
have a great rest of the day!
Mark M.
you too!
Steve S.
has left the room
8:30 PM
Mark M.
that'
er, that's a wrap for today's chat
the transcript will be posted to https://commonsware.com/office-hours/ shortly
the next chat is Tuesday at 4pm US Eastern
have a pleasant day!
koral
has left the room
Mark M.
turned off guest access

Thursday, September 28

 

Office Hours

People in this transcript

  • koral
  • Mark Murphy
  • Steve S