Multiple adapters vs. multiple threads

24 views
Skip to first unread message

atoji

unread,
Jul 29, 2008, 2:01:18 PM7/29/08
to bluecove-users
Hello,

I'm trying the new API to use Multiple Adapters and Bluetooth Stacks
in parallel in the same JVM.
I've downloaded the last snapshot of BlueCove and BlueCove-GPL,
compiling the GPL to work on Linux/BlueZ.

When not using the Multiple Adapters API, I'm able to have multiple
threads accessing the bluetooth stack, transparently, sending data to
two or more devices and doing device discovery at the same time, for
example.

But when using Multiple Adapters API, I'm not able to have multiple
threads accessing the same device at the same time. I'm getting
BluetoothStateException: device X already in use.

The exception is thrown in situations like this:

final Object adapterID = BlueCoveImpl.getThreadBluetoothStackID();

// Thread 1
Thread t1 = new Thread() {
public void run() {
BlueCoveImpl.setThreadBluetoothStackID(adapterID);
}}

// Thread 2
Thread t2 = new Thread() {
public void run() {
BlueCoveImpl.setThreadBluetoothStackID(adapterID);
}}

Exception is thrown when running the second thread.

I would like to know if this is the expected behavior.
When using a single bluetooth adapter, it's possible to communicate
with up to 7 devices. But when using multiple adapters the
communication is limited to 1 device per adapter?

Thanks in advance,

Rodolpho

Vlad Skarzhevskyy

unread,
Jul 29, 2008, 2:08:44 PM7/29/08
to bluecov...@googlegroups.com
Hi Rodolpho
All should work fine. But you should not be able to run two discovery
processes in parallel accessing the same stack.

In my tests I used to create service in one thread and client
connecting to the service in another stack and thread

Anyway more detailed example and exception traces with full thread
dump if possible should help to identify the problem if any..

Regards,
Vlad

atoji

unread,
Jul 29, 2008, 5:05:38 PM7/29/08
to bluecove-users
Hi Vlad,

Thanks for your quick reply!

I've tried again the example above, and it worked, it was a mistake
of mine.

Now I'm trying to do device discover on one adapter and OBEX push
on other. But I'm unable to initialize the stacks, I get
IllegalArgumentException:
BlueCove stack already initialized.

In fact I'm a bit confused on where to call static methods to
BlueCoveImpl.
I've trying to code something like the API example.

The test I'm trying follows below.
RootThread2 should do the device discovery task, and RootThread3
should
push a text file to an arbitrary device.

The problem arises when BlueCoveImpl.getThreadBluetoothStackID() is
called.
RootThread2 calls this method first on the constructor. When called on
RootThread3's constructor, the IllegalStateException is thrown.

----------- 8< ------------- Java code
--------------------------------------

package mypack;

import java.io.IOException;
import java.io.OutputStream;

import javax.bluetooth.BluetoothStateException;
import javax.bluetooth.DeviceClass;
import javax.bluetooth.DiscoveryAgent;
import javax.bluetooth.DiscoveryListener;
import javax.bluetooth.LocalDevice;
import javax.bluetooth.RemoteDevice;
import javax.bluetooth.ServiceRecord;
import javax.microedition.io.Connector;
import javax.obex.ClientSession;
import javax.obex.HeaderSet;
import javax.obex.Operation;
import javax.obex.ResponseCodes;

import com.intel.bluetooth.BlueCoveImpl;

public class MultipleAdaptersTest2 {

public static void main(String[] args) throws BluetoothStateException
{
RootThread2 rootThread = new RootThread2();
Thread r = new Thread(rootThread);

RootThread3 rootThread3 = new RootThread3();
Thread r3 = new Thread(rootThread3);

r.run();
r3.run();
}

}

final class RootThread3 implements Runnable {

private final Object id;

public RootThread3() throws BluetoothStateException {
BlueCoveImpl.useThreadLocalBluetoothStack();
BlueCoveImpl.setConfigProperty("bluecove.deviceID", "1");
this.id = BlueCoveImpl.getThreadBluetoothStackID();
}

public void run() {
Thread t2 = new Thread(new Runnable() {
public void run() {
BlueCoveImpl.useThreadLocalBluetoothStack();
System.out.println("T2: " + id);
BlueCoveImpl.setThreadBluetoothStackID(id);

try {
new ObexPutClient().run();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});

t2.run();
}

private class ObexPutClient {

public void run() throws IOException, InterruptedException {
BlueCoveImpl.useThreadLocalBluetoothStack();

BlueCoveImpl.setThreadBluetoothStackID(BlueCoveImpl.getCurrentThreadBluetoothStackID());

String serverURL = "btgoep://111111111111:6";
System.out.println("Connecting to " + serverURL);
ClientSession clientSession = (ClientSession)
Connector.open(serverURL);
HeaderSet hsConnectReply = clientSession.connect(null);
if (hsConnectReply.getResponseCode() !=
ResponseCodes.OBEX_HTTP_OK) {
System.out.println("Failed to connect");
return;
}

HeaderSet hsOperation = clientSession.createHeaderSet();
hsOperation.setHeader(HeaderSet.NAME, "Hello.txt");
hsOperation.setHeader(HeaderSet.TYPE, "text");

//Create PUT Operation
Operation putOperation = clientSession.put(hsOperation);

// Send some text to server
byte data[] = "Hello world!".getBytes("iso-8859-1");
OutputStream os = putOperation.openOutputStream();
os.write(data);
os.close();

putOperation.close();

clientSession.disconnect(null);

clientSession.close();
}
}

}

final class RootThread2 implements Runnable {

private final Object id;

public RootThread2() throws BluetoothStateException {
BlueCoveImpl.useThreadLocalBluetoothStack();
BlueCoveImpl.setConfigProperty("bluecove.deviceID", "0");
this.id = BlueCoveImpl.getThreadBluetoothStackID();
}

public void run() {
Thread t1 = new Thread(new Runnable() {
public void run() {
BlueCoveImpl.useThreadLocalBluetoothStack();
System.out.println("T1: " + id);
BlueCoveImpl.setThreadBluetoothStackID(id);
try {
DiscoveryAgent agent =
LocalDevice.getLocalDevice().getDiscoveryAgent();
agent.startInquiry(DiscoveryAgent.GIAC, new Listener());
} catch (BluetoothStateException e) {
e.printStackTrace();
}
}
});

t1.run();
}

private final class Listener implements DiscoveryListener {
public void deviceDiscovered(RemoteDevice arg0, DeviceClass arg1) {
System.out.println("Discovered: " + arg0.getBluetoothAddress());
}

public void inquiryCompleted(int arg0) {
System.out.println("Completed");
}

public void serviceSearchCompleted(int arg0, int arg1) {
System.out.println("Service search completed");
}

public void servicesDiscovered(int arg0, ServiceRecord[] arg1) {
System.out.println("Services discovered");
}
}

}

----------- 8< ------------- Java code
--------------------------------------

This is the stack trace I get when running this program:

BlueCove version 2.0.3-SNAPSHOT on bluez
Exception in thread "main" java.lang.IllegalArgumentException:
BlueCove Stack already initialized
at
com.intel.bluetooth.BlueCoveImpl.setConfigProperty(BlueCoveImpl.java:
777)
at
net.infomobile.bluecast.server.RootThread3.<init>(MultipleAdaptersTest2.java:
42)
at
net.infomobile.bluecast.server.MultipleAdaptersTest2.main(MultipleAdaptersTest2.java:
27)
BlueCove stack shutdown completed

Line 42 is: BlueCoveImpl.setConfigProperty("bluecove.deviceID", "1");


Sorry for the big post...!
Maybe you could provide me another example, and I'll try to find
where is the error on my code.

Thanks again,

Rodolpho

Vlad Skarzhevskyy

unread,
Jul 29, 2008, 5:33:45 PM7/29/08
to bluecov...@googlegroups.com
The constructors new RootThread2(); and new RootThread3(); are called
in the same thread! So they try to bind to the same stack! And
reinitialize it.

Call releaseThreadBluetoothStack() before making call to another your
constructor!
E.g. once you initialized stack and got a reference to it; release it
and start another initialization.

I know I made it to hard to use. But if you have better idea for API
I'm listening.


--
Vlad

atoji

unread,
Jul 29, 2008, 5:45:08 PM7/29/08
to bluecove-users
Hi Vlad,

Adding a call to releaseThreadBluetoothStack() has solved the
problem!
Now device discover and OBEX works in parallel.

I think API is OK, maybe I should read more about thread locals in
Java. :)

Thank you very much and best regards,

Rodolpho

On 29 jul, 18:33, "Vlad Skarzhevskyy" <skarzhevs...@gmail.com> wrote:
> The constructors new RootThread2(); and new RootThread3(); are called
> in the same thread!  So they try to bind to the same stack!  And
> reinitialize it.
>
> Call releaseThreadBluetoothStack()  before making call to another your
> constructor!
> E.g. once you initialized stack and got a reference to it; release it
> and start another initialization.
>
> I know I made it to hard to use. But if you have better idea for API
> I'm listening.
>

Raspete

unread,
Jul 31, 2008, 7:43:22 AM7/31/08
to bluecove-users
Hi atoji

Where do you write the calls to releaseThreadBluetoothStack()?
I'm trying to run your example on windows, but I cannot make it work.

Thanks.
> ...
>
> leer más »

atoji

unread,
Aug 4, 2008, 2:14:43 PM8/4/08
to bluecove-users
Hello,

In the example, add it to the first line of RootThread3 constructor.

Regards,

Rodolpho
> ...
>
> mais »

Raspete

unread,
Aug 6, 2008, 4:23:53 AM8/6/08
to bluecove-users
Ok thanks.

My problem was that I work on windows and there don't works.
Thanks anyways.
> ...
>
> leer más »
Reply all
Reply to author
Forward
0 new messages