In my problem, I create a pthread using pthread_create(), say myThread.
They both share a common variable "done" for the main thread to tell the myThread stops reading from the socket.
in my pthread, I have a loop:
// done is a common variable
while (!done && socket->read(&buffer) == OK) {
// do something....
}
Some times, I want to tell myThread to stop reading from socket, so I do:
done = true;
void *test;
pthread_join(myThread, &test);
Will this cause a race condition? i.e. will myThread not see my main thread update the value of 'done' before it blocks on the read call?
Writing a variable in one thread and reading it in another needs synchronization (such as a mutex) to avoid race conditions.
If this is a real socket and not a strange object, consider calling shutdown() to tear down the connection and wake up blocked threads while keeping the file descriptor valid, see Wake up thread blocked on accept() call. Once the read has failed, myThread locks the mutex and checks the done variable.
Other methods include calling poll() on the socket and a pipe for delivering the shutdown message.
Related
I'm developing an android application that at high frequency receives data from ble notify, print data on the screen and send data to other peripherall.
This is my situation :
onCharacteristicChanged callback receives a byte array called
"value" at 10hz and unpacks data in some float and int variables
an Handler associated with an handlerThread starts a Runnable
every 30hz. This runnable use the variables unpacked from value,
saves the new data in some variables and sendbroadcastmessage to the
UX
another thread every 10hz use the data saved in
step 1 and 2 does some math operation on this variables and write
data on the characteristic.
In the step above I save and use float, double and int variables.
I'm afraid to handles the concurrency and I'm thinking to resolve the concurrency problems using the same handlerthread in the step 2 and 3. But when the other notify arrives I think that there is a race condiction problem :/
other question : oncharacteristicchanged in what thread is executed ?
more information of my problem :
in oncharacteristicchanged arrives new byte array (at 10hz frequency), I unpack data in variables , in other thread B (at 30hz) use this data do some calculation: sendbroadcast to the ux and save the result in some other variables; the thread C use the result of the thread B, it does some other calculation and write on characteristic at 10hz.
oncharacteristicchanged -> Thread B -> Thread C
But I can't stop oncharacteristicchanged because I don't know in what thread it is executed..
Do you
I don't understand Android, but I do Java. I'll try to help you even not knowing Android, so let's go!
"In the step above I save and use float, double and int variables."
First of all, I'd start using thread safe variables, such as: AtomicInteger or declare them as volatile.
For all your methods that will be accessed by multi-threading, I'd say to make them thread safe. I don't know if in Android there is the class Lock or the keyword synchronized, but I'd start from there.
Example:
Lock lock = new ReentrantLock();
try {
lock.lock();
doYourWork();
} finally{
lock.unlock();
}
Thats the way to start... Hope I helped you a little bit even not knowing Android and sorry if I said anything wrong.
I'm using an InputStream to read data from my Arduino via bluetooth. I am using a separate thread to do this so as it does not block the UI thread. This thread has a while loop in this style:
while(!stop){
int instruction = InputStream.read();
switch(instruction){
... //processes data here
}
}
At points, I need to stop this thread, and it is vital that this is done quickly because I am calling for it to stop on the UI thread. To stop the thread, I change the variable stop to true, so logically the while loop should finish and the thread should exit.
When I hover my mouse over the read function, eclipse says that it will return -1 if the end of the stream is reached. My problem is that this is not happening. If an instruction is not received from the sensor, the read function stalls until something is received. Shouldn't it return a -1 because the stream is finished?
Because the read() function is stalling, I am unable to stop the thread. I would use thread.stop(); but this is deprecated and unstable so I want to avoid it. I've also tried using InputStream.available() to see if there is anything available before performing a read, but this returns a 0, even when there are bytes available to be read. Has anybody got any suggestions?
The read() method you chose will block until it reads a byte. You can cause it to exit by closing the socket or stream. This will cause an exception (which you need to catch). FYI - You should use the other read() method which returns how many bytes read. The simpler read() method you're using will return -1 for a data byte of 0xff and a bad read.
I have a C thread that is making requests and receiving updates from a server. The updates are sent to Java through JNI calls. My problem happens when I'm receiving a player's inventory which can contain up to 100 items (100 responses from the server, I cannot modify this part). Sometimes the problem happens, sometimes not but the bigger the inventory is, the more often I have this issue.
I don't get any exception in the logcat except the following message :
06-10 10:09:46.085: I/Choreographer(23815): Skipped 87 frames! The application may be doing too much work on its main thread.
And then my app closes. I also need to say that even when I comment the lines where I update the UI with runOnUiThread the app crash.
I tried to check if I'm on the UI Thread when I return to Java with JNI but Looper.myLooper() == Looper.getMainLooper() return false.
Anyone experienced the same problem ? Are the C threads related to the main thread somehow ? Thanks
EDIT
When I receive an update from the server the following calls are made :
From a Java Thread (not the UI thread) : call a C function named notifyAll
From notifyAll call a C function named update which will call its equivalent in Java (see code below)
void UpdateListenerWrapper::update(Update& u) {
// Retrieve the current JNIEnv* with the cached JVM
int status;
JNIEnv* env;
bool isAttached = false;
status = gCachedJVM->GetEnv((void **) &env, JNI_VERSION_1_2);
if(status < 0) {
__android_log_print(ANDROID_LOG_ERROR, "UpdateListenerWrapper", "Failed to get JNI environment");
status = gCachedJVM->AttachCurrentThread(&env, NULL);
if(status < 0) {
__android_log_print(ANDROID_LOG_ERROR, "UpdateListenerWrapper", "Failed to attach current thread");
return;
}
isAttached = true;
}
jmethodID update = env->GetMethodID(gClazzUpdateListenerWrapper, "update", "(J)V"); // J stands for Java long type
// Call Java method update from jUpdateListener object
env->CallVoidMethod(jUpdateListener, update, (jlong)(intptr_t)&u); // Pointer as agument, we'll build the Update object in Java
if (isAttached) {
gCachedJVM->DetachCurrentThread();
}
}
I think the problem is at this line gCachedJVM->GetEnv((void **) &env, JNI_VERSION_1_2); and maybe GetEnv return a pointer for the UI thread. Could that be the problem ? How can I fix this ?
The app crash is unrelated to the Choreographer complaints. Those are just a warning that indicates the animation is being starved.
You really want to be viewing the logcat output in a mode that shows thread IDs. I recommend adb logcat -v threadtime from the command line. If you put a log message at the start of your server interaction you can easily see if it's running on the UI thread (thread ID and process ID are the same -- not guaranteed by the system, but reliably true in apps).
Never do network or database I/O on the main thread. If it takes too long, the system gets bored and decides that your app is not responding.
Calling into native code through JNI does not switch you to a different thread. There are not C threads and Java threads, just threads, which can call in and out of code written in C and Java.
Re: question updates...
GetEnv always returns a pointer to data for the current thread. Also, CallVoidMethod always happens in the current thread; even if you passed in the wrong JNIEnv it wouldn't "jump" threads.
The GetMethodID call can be expensive in a class with a lot of methods, so you should try to cache that at the same point where gClassUpdateListenerWrapper is set up. Attaching and detaching the thread from the VM can also be expensive and is something best avoided -- and if you're calling here from a Java method, then by definition it's attached already. I would guess that isAttached is never being set.
That doesn't really explain why the Choreographer is starving though. I think you still need to add a log message to C update() and use logcat -v threadtime to get a sense for what is happening on which threads, and use traceview to see where the time is going.
I found the solution to my problem but it's kind of specific to my app. In the update function (Java side), I had a case which had no break and each updates were triggering new network calls (not in the UI thread). Nasty to find but thanks for your time and your answers, you helped me to solve this :)
With reference to the following code.
for (Future<Long> future : list) {
try {
sum += future.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
Now when i call future.get will this be blocking call? So if i am executing this on the Main Thread of and android application will this cause an ANR exception ? I notice the Interrupted exception is also thrown, so does this mean their is a sleep called on the thread in the get function ?
Yes, documentation of Future.get() says:
Waits if necessary for the computation to complete, and then retrieves its result.
so, it will block until results of computation are available, or the computation was interrupted (cancelled or resulting in exception).
It may cause ANR if your computations take long time to finish.
Again, from documentation of Future.get():
#throws InterruptedException if the current thread was interrupted while waiting
Now, since you call Future.get() from main thread, I suspect that it is the Android system which interrupts your main thread in an attempt to make it responsive again. But it may also be caused by another thread of your application - it's hard to tell, since you haven't specified what your application does, what threads does it create, when, do you use ExecutorService (and if so, which implementation), and so on.
No, FutureTask.get() (which I believe is the implementation of Future you're using) does not call Thread.sleep(). Instead, putting the thread in waiting mode is done via thread parking which causes it to not be scheduled for execution until a signal is given. This may cause in ANR error if done in the main thread. For details of parking mechanism consider reading documentation and this question
You can simply check if future "is done" by calling future.isDone(). Code example:
String result = "";
if (myFuture.isDone()) result = (String) myFuture.get();
You will probably want to check it in an endless loop.
Beware of deadlock with future.get(). If both the MainThread, that call future.get(), and the WorkerThread is synchronized (on the same object) then you get a deadlock.
I have a client software (on Android) that listens to incoming messages. The messages are received in a while loop that waits for messages to come. When a message is found, it updates the GUI. [Since in Android, GUI can not be updated directly ] A thread is called to do this. My problem is, if there are many messages, results in many threads! And it creates a clumsy situation. My abstract code is,
My_Client()
{
send_text_function() // My question is not about it
in_a_thread_Call_receive_from_others_function() [see 1]
}
receiving_funtion() // [this function is mentioned above as (see 1), called in a thread]
{
while( waiting for new message)
{
>>A new message found >> create a thread to update the GUI. // << Here is my question. see 2
//android.os.Handler.thread type thread!
}
}
label 2: Now this thread is created each time there is a message. How can I just create one thread and keep using it again and again? Any idea?
Create a new Thread.
In the run() method of the Thread create a new Handler.
When you want to do something on the target thread, use the Handler's post() method.
You can create a Handler on the Main thread to post-back operations that update the GUI.
Also consider using AsyncTask<>.