My Problem: I've got 802.15.4 Wireless network connected to a serial port (using a wrapper). I can send packages into the network and listen for incoming packages. As you can imagine this is highly asynchronous.
Here comes the task: I want to send commands to the network and wait for the response in one function call. For Example: I want to get the temperature from the Node with the network ID 1338.
double getTemperature(int id) throws Exception { .... }
Is there a better way of waiting for a response message other than doing all this "synchonized(object) wait(..) notify(..)" stuff?
Best regards, bigbohne
Maybe to add some spice:
This should all end in a webinterface where user can request these commands (either through ajax or directly). I've also thought of caching responce values in a database. But for some commands you MUSS have a direct answer of success/failure
You can do this with a BlockingQueue so you will not have to manually manage any of the synchronization. The request can send the message, then call take() on a BlockingQueue which will wait for an element to be present. The element is the reply which is inserted into the queue by whatever listener you have on the port when the reply is returned.
You just have to coordinate so that the listener and requester share the same queue. You only need a queue of size one for each request to support this scenario.
// Send method
BlockingQueue<Reply> q = new ArrayBlockingQueue<Reply>(1);
serialCom.registerQueue(myRequest.getId());
serialCom.sendRequest(myRequest);
return q.take();
//Listener
BlockingQueue<Reply> q = queueMap.get(incomingMessage.getId());
q.add(incomingMessage.getReply());
I'm not sure I understand the question correcly, but I usually use a Future<T>
for these sorts of tasks.
Internally the Future<T>
implementation uses wait and notify and all of that, but the interface itself becomes rather clean.
Future<Double> getTemperature(int id);
In your communication code you then can map incoming messages towards unfulfilled futures. If ordering is guaranteed you could do something like
class Something {
Map<Integer, Queue<Object>> requests;
synchronized Future<?> request(int id, Object data) {
MyFutureImpl future = new MyFuture();
requests.get(id).add(future);
serializeAndSend(id, data);
return future;
}
void serializeAndSend(id, data) {...}
synchronized void response(int id, Object data) {
MyFutureImpl future = requests.get(id).remove();
future.setValue(data); // This would fulfill the future, and any
// threads waiting in a get() will get the
// value and continue.
}
}
Where MyFutureImpl is a very basic future-implementation. I'm assuming there's a communications thread that calls response()
when a packet is received. I'm also assuming that the serializeAndSend()
-function handles the writing to the client or blocks until the write operation can be made or handed off to a communication thread.
The use of concurrency-capable map and queue structures could make some synchronization
s unnecessary. If there's only ever one outstanding call per id, the Queue becomes unnecessary of course.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With