Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses

Re^3: Socket client thread design problem

by BrowserUk (Pope)
on Mar 22, 2014 at 20:12 UTC ( #1079406=note: print w/replies, xml ) Need Help??

in reply to Re^2: Socket client thread design problem
in thread Socket client thread design problem

I downloaded the C zip you linked only to find it only contains the same trivial, single-threaded examples you already posted (amongst lots of other unrelated examples). But no C code that uses 3 threads and shared sockets and queues and stuff to implement something you claim to be trying to emulate in Perl.

Nothing for me to use as a basis for producing a threaded Perl code to meet the sketchy and confused specs you outline in words.

So, then I start to think about the examples you have posted, and it is my conclusion that you are trying to use threads to mix together two different APIs either of which can serve the purpose on its own.

  • Either: your server queries the current value from the device on demand -- ie. when a client connects -- synchronously reads the response and returns it to the connecting client.

    No need for a callback here. Each client gets the latest value on demand.

  • Or: your server registers a callback that, once per second or whatever frequency you choose, gets called back (if the temp changes), and updates a (global) cache variable with the latest temperature value.

    And whenever your clients connect, you simply return the current value of that cache variable.

    No threads -- unless you choose to use threads for your client connects -- no need or use for queues.

    Simplicity personified.

So, unless you can provide a reason for your 3 threads + queues design -- and the C code that implements it -- I can see no reason at all to try and create something that matches your earlier descriptions. Especially from scratch and without reference.

With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
  • Comment on Re^3: Socket client thread design problem

Replies are listed 'Best First'.
Re^4: Socket client thread design problem
by photron (Novice) on Mar 24, 2014 at 15:09 UTC

    Regarding the C zip: the relevant files for my example here are: bindings/ip_connection.(c|h) and bindings/bricklet_temperature.(c|h). ip_connection.(c|h) implements all the thread and socket logic. bricklet_temperature.(c|h) does the packing and unpacking of TCP/IP packages to function call arguments and return values. The C code forms a binding for a TCP/IP protocol here. The examples I provided are using this binding. All the threading and socket handling is done inside the binding C code.

    Sorry, you're right my description of the spec is long and probably hard to follow. Let me try to summarize the critical points:

    • First of all there are only two parties involved here: the user program is the client asking for the temperature (using the binding), the hardware is the server providing the information. There is no other server-like thing in between them that could cache stuff as you describe it.
    • The C binding provides functions to talk to the hardware using TCP/IP. The C binding takes care of packing function call parameters and send them to the hardware and unpacking received data from the hardware to function call return values. There are other hardware modules beside the temperature sensor. For example, there is a relay module. It has a set_state function. The C binding takes care of creating the correct TCP/IP packet to set the state of the relay and sends it. all the user hast to do is calling the set_state function.

      You're right: if all I wanted to do was setting a relay state or getting the temperature then this could all be done synchronous. The get_temperature function would just create and send request and then directly receive incoming data from the socket to get the response and return it to the user.

      Okay, until here everything is fine, I just need a socket, that's it, no threads, no queues, no problems.

    • But there is also a button module. A program that wants to react on a button press could just call the is_pressed function over and over again to do that. Or it can tell the button module to send a message each time the button state changes. This is a callback, a spontaneous response send by the hardware without a corresponding request from the user program. There is no point in caching this information, as suggested.

    And that'a what you called "mixing together two different APIs". There is the getter/setter style stuff and the callback stuff. One could argue that all information that callbacks can provide can also be polled for by getter calls. That's basically correct from a general point of view. But from a hardware point of view polling wastes a lot of bandwidth especially for events that done occur that often such as the press of a button. Also the hardware might not be directly connected to TCP/IP, there might be low bandwidth connections such as USB and RS485 in between. From an API and protocol point of view the actual electrical connection is not visible to the user program. There is also the problem that most communication links are designed for high throughput, but this protocol requires low latency due to the request/response nature. So callback are useful and have advantages compared to polling.

    The callbacks is what makes the implementation of the protocol difficult here, but the hardware and the TCP/IP protocol is there and fixed, the task is to implement a Perl module that provides these features to the user.

    To receive callbacks there has to be someone receiving incoming data from the socket all the time. This cannot be done within the simple model of only receiving data from the socket if a response for a getter call is expected. The C code does this by using a receive thread (thread 1: ip_connection.c:1284 ipcon_receive_loop) that constantly receives incoming data. Then the callbacks have to be delivered to the user code. This is done by the callback thread (thread 2: ip_connection.c:1141 ipcon_callback_loop). As explained in the earlier post, this cannot be done from the receive thread if the user should be able to call getters from the callback functions. The last thread (thread 3) is the main-thread of the program or any other user-created thread that calls getter/setter function of the bindings. As getter/setter calls directly write their request to the socket. Communication between all this threads is done by queues.

    Instead of using threads for callback handling the binding code could include a blocking handle_callbacks function that does the work of the receive and callback threads. Then the user has to call it in order to use callbacks. This is how this is realized in PHP, that lacked thread support at the time the PHP binding was implemented. But I'd like to have the Perl binding work as all the other bindings, and keep PHP as an exception.

    This got quite long again. It seems that I fail at stating my problems in a short fashion :-)

      If the hardware is capable fo supporting multiple concurrent connections; then I would suggest using two different connections.

      One in a separate, library created thread for the blocking read to receive the hardware-initiated timed and/or event-driven packets.

      And the other for client-code initiated, synchronous query/reply transactions.

      If the hardware is unable to support two concurrent connections; then I would go for a separate thread with a non-blocking socket and running a typical select with timeout server that checks a queue for pending queries each time the recv timeout expires.

      With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      "Science is about questioning the status quo. Questioning authority".
      In the absence of evidence, opinion is indistinguishable from prejudice.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://1079406]
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others exploiting the Monastery: (6)
As of 2017-12-18 08:22 GMT
Find Nodes?
    Voting Booth?
    What programming language do you hate the most?

    Results (473 votes). Check out past polls.