Welcome!

Welcome to the official BlackBerry Support Community Forums.

This is your resource to discuss support topics with your peers, and learn from each other.

inside custom component

Java Development

Reply
Regular Contributor
Posts: 59
Registered: ‎05-10-2012
My Device: 8800
My Carrier: verizon

threading problem v5 vs v6

Hello all

 

I've got a problem with an app I intend to run on OS v5, 6 & 7.

 

Its a multi threaded app that communicates with the outside world via a socket impl that contains an InputStream and OutputStream. 

 

The InputStream and OutputStream are assoc with 2 different threads that read/write data to/from them..  For the sake of this post I'm going to say ReadThread controls InputStream and the WriteThread controls the OutputStream.

 

On OS v6 everything works ok.  ReadThread & WriteThread read and write in such a fashion so data appears to simultaneously flow in/out of the app.

 

On OS v5, at some point it appears as though WriteThread pre-empts ReadThread and sucks up all the cpu.  Log mssgs show WriteThread constantly checking if there is data to write (although there is none).  I know ReadThread is still operating because after WriteThread is stopped then ReadThread reads in all data sent to it.  

 

Questions:

 

Could this be some kind of buffering?

 

Is threading model between OS v5 & v6 different? 

 

Should the threads be synchronized to ensure so one operates at a time?

I realize these obvious questions, but the only reason I ask is because I see such different behavior between the app running on the different OS's.

 

Also, I'm running this on a Bold and a Curve - is there any significant difference between the CPU's on these devices?

Mark 

Developer
Posts: 19,636
Registered: ‎07-14-2008
My Device: Not Specified

Re: threading problem v5 vs v6

I would say that assuming that the difference is because of the different OS, based on one sample, is possibly jumping to conclusions.  There are other variables involved here that are equally likely to contribute, including, as you point out, the different hardware involved. 

 

This is suspicious:

"Log mssgs show WriteThread constantly checking if there is data to write"

The "checking that there is something to write" would seem likely to be something in your write Thread processing and not related to the OS - so if it is not stalling when it has checked and found nothing, then that would be a problem in your code would it not?  Have you looked at this processing,  I presume your write Thread has some sort of notify/wait mechanism that allows it to 'pause' when there is nothing to do. 

 

And just to say, I have similar socket level networking code, the difference is that I do the read and write on the same Thread (1/2 duplex protocol). 

 

I have noted that there are significant differences in the socket processing between OS 5.0 and OS 6.0, specifically that in OS 5.0, (a) a read would only be completed when the buffer supplied was full and (b) available() could not be relied on.  In OS 6.0 by contrast, available() is actually useful, and when you issue a read, you can get a partial buffer.  But AFAIK, neither of these differences should impact your write Thread. 

Regular Contributor
Posts: 59
Registered: ‎05-10-2012
My Device: 8800
My Carrier: verizon

Re: threading problem v5 vs v6

The WriteThread does the following:

 

1.  check if its buffer has data

2.  if it does, write it

3.  if it does not, sleep for 1 second

 

The message is generated prior to checking if the buffer has data.  I have added messages to display if and only if the sleep is executed and they display as expected.

 

Its not a wait/notify, but I am unsure they are warranted since there's no shared object, unless the socket object counts as being shared - but even then, one thread uses the sockets input stream and a different thread uses its output stream.


I'm intrigued by "a read would only be completed when the buffer supplied was full"  My code uses

int c = java.io.InputStream.read()  


per the docs it returns 1 byte.  Is there an internal buffer somewhere?  Does it have an exposed api by which I can determine how full it is?  What number of bytes constitutes a full buffer?

Developer
Posts: 19,636
Registered: ‎07-14-2008
My Device: Not Specified

Re: threading problem v5 vs v6

I will describe my processing so that you can compare, but the architecture I use is different, being based on packets rather than bytes.

 

A packet is placed in a queue (Vector) by the sending program and a shared Object is notified.

 

The socket Thread waits on this shared Object.  When notified, the processing goes round in a loop sending the requests that are in the queue.  When the queue is empty, it returns to the wait.

 

This processing means that there is no activity when there is nothing to do.  In fact there is a little activity, the wait will wait for a queue entry or a maximum time.  I could use this mechanism to create a heartbeat to keep the socket alive, in fact I don't, the socket is closed when there has been no activity for a period rather than keeping it alive.  This is a battery saving option, but it does mean when the next request comes along, it will be delayed while the connection is re-established. 

 

I am slightly confused by this

"Its not a wait/notify, but I am unsure they are warranted since there's no shared object"

If there was no shared Object, how does your client actually put the data in the appropriate place to send it?

 

With respect to the reads, all the messages that are sent to this client begin with a 4 byte header that includes the length. So the read processing begins with a read for 4 bytes, something like this

lengthActuallyRead = _in.read(buffer, 0, 4);

and then extracts the length from the header and does

lengthActuallyRead = _in.read(buffer, 4, len);

In OS 5.0, this would not complete until 4 or len bytes had actually been received.  In OS 6.0 I have to repeat the read if it did not get all the bytes. 

 

As noted in my previous post, you can do:

_in.available()

to get the bytes that are available without blocking.

 

I can not read a socket connection as you do, because I am not sure how the bytes are going to be treated.  Some are encrypted so I can't convert them to a character.  I prefer to read them into a byte array. 

 

Anyway, with respect to going into a loop, are you saying

"Log mssgs show WriteThread constantly checking if there is data to write (although there is none"

 

Given the logic you are using, this should only happen once a second.  This is unlikely to be hogging all the processing unless the wait was by passed.  When you see the processing, do the messages appear to be1 second apart as you expect, or more frequently?

 

So one possibility is that there is in fact an OS difference here and that in addition to the fixes to the socket processing that I noted, RIM also fixed a problem that stopped multiple Threads sharing a socket

Regular Contributor
Posts: 59
Registered: ‎05-10-2012
My Device: 8800
My Carrier: verizon

Re: threading problem v5 vs v6

[ Edited ]

"If there was no shared Object, how does your client actually put the data in the appropriate place to send it?"

I have created my own Socket object. 
Here's the important part from the Socket obj constructor:

 

conn = (StreamConnection)Connector.open("ssl://"+server+":11111;deviceside=true");
_in = conn.openInputStream();
_out = conn.openOutputStream();

 

_in is sent to ReadThread and _out is sent to WriteThread at Read/WriteThread construction time.  

 

I understand this means 2 different threads are sharing the conn field in the Socket obj.  I didn't think syncronization was necessary because the 2 threads are not modifying conn but using different methods of it to perform different operations.  Does that make any sense?


I'm also a bit confused about deviceside=true.  I've read information saying its only needed for running in the emulator and that its ignored if you are not running in the emulator.  Is that correct?
 

"As noted in my previous post, you can do:

_in.available()

to get the bytes that are available without blocking."

 

I thought your previous post said available() was unreliable in OS v5.  Did I read that incorrectly?

Here's some abbreviated code to describe my processing (I'm hoping by writing this something will strike me and, at this point, extra sets of eyes on this are very welcome)

 

My Socket obj is created.  _in and _out are sent to ReadThread/WriteThread at their construction time.

Here's the important part of ReadThread's  run():
 

while (mInputStream != null) {


  int ch = mInputStream.read();

  if (ch >= 0)
    insert(ch);
  else
  {
     System.out.println("we are done");
     break;
  }

}

}

I have verified that I am blocking on  int ch = mInputStream.read() until data is available.

WriteThread has a buffer that contains the data to write.  There is a method by which the controller can place data into buffer so it will be written.


Here's the important part of WriteThread's run:
 

while (true)
{

   if (buffer != null && buffer.length > 1)
  {

      mOutputStream.write(buffer);
      mOutputStream.flush();
      buffer = null;

  }
  else
  {
    if (allDone){

        return

    }
   else{
        sleep(1000); // 1 second sleep
   }

}

 

I have also verified the WriteThread does pause for 1 sec as expected.

Developer
Posts: 19,636
Registered: ‎07-14-2008
My Device: Not Specified

Re: threading problem v5 vs v6

[ Edited ]

Let me start with the difficult part

 

deviceside=true and the other connection suffixes that you add to determine the actual path of a communication are a source of much confusion and difficulty.  Search the forum, you will find loads of network related Threads.  Anyway, here are two places to start in the understanding of connection Suffixes.

http://supportforums.blackberry.com/t5/Java-Development/Networking-Transports-II/ta-p/446742

http://supportforums.blackberry.com/t5/Java-Development/Different-ways-to-make-an-HTTP-or-socket-con...

 

And since you are looking at OS 5.0 and above only, check out the ConnectionFactory API to help you with this. 

 

Back to this issue.

 

"I didn't think synchronization was necessary because the 2 threads are not modifying conn but using different methods of it to perform different operations. "

Sorry I have no idea about this.  As noted, there were significant changes made in OS 6.0, one of the changes made might have been to fix synchronization issues.  Just guessing, no evidence of this....

 

"I thought your previous post said available() was unreliable in OS v5.  Did I read that incorrectly?
You did, sorry for suggesting that without the caveat that it only worked (in my experience) in OS6. 

 

"There is a method by which the controller can place data into buffer so it will be written."

Ah, so this same method could in fact notify a shared Object - meaning you could do processing in the same way I do it. 

 

If I was reviewing this code, I would look for synchronization/locking in two places:

 

a) between the method in the controller that places data in the buffer and this code:

      mOutputStream.write(buffer);
      mOutputStream.flush();
      buffer = null;

How do you know that your controller is not adding bytes to the buffer at the same time as you are dong the flush()?

 

b) between the insert and the code that processing the input data.  The insert I am talking about is this code:

insert(ch);

 

Anyway, can you reproduce this error at will?  Can you do it on a simulator?

One final thing, I am concerned that you are aware that the in the variable "ch" after this statement:

int ch = mInputStream.read();

you have a byte, not a character. 

Highlighted
Regular Contributor
Posts: 59
Registered: ‎05-10-2012
My Device: 8800
My Carrier: verizon

Re: threading problem v5 vs v6

I've done more digging with this and my findings suggested the problem I posted in:

 

http://supportforums.blackberry.com/t5/Java-Development/InputStream-read-different-behavior-between-...