* "C - like: THIS" pointer to a task type inside a task function @ 2012-01-23 19:32 Ada BRL 2012-01-23 19:59 ` Dmitry A. Kazakov ` (3 more replies) 0 siblings, 4 replies; 19+ messages in thread From: Ada BRL @ 2012-01-23 19:32 UTC (permalink / raw) Dear all, I'm experiencing an issue about local and not local pointers... I've N clients and one server that communicate each other. The N clients retrieve data dynamically, send it to the server throgh enrty call (obviously the server can accept just one call per time) and wait for the reply from the server (through accept statement). For this reason the server needs to know on which client call the entry: one time could be the 3th, another the 1st and so on... This is my - deeply simplified - framework: package P1 is task type T1 is entry Retrieve_Data(Data : String); end T1; task type T2 is entry Retrieve_Data(Data : String); end T2; task type T3 is entry Retrieve_Data(Data : String); end T3; end P1; package body P1 is task body T1 is Data : String; begin while True loop -- retrieve somehow data T4.Send_Data(Data); accept Retrieve_Data(Data); end loop; end T1; task body T2 is Data : String; begin while True loop -- retrieve somehow data T4.Send_Data(Data); accept Retrieve_Data(Data); end loop; end T2; task body T3 is Data : String; begin while True loop -- retrieve somehow data T4.Send_Data(Data); accept Retrieve_Data(Data); end loop; end T3; end P1; -- other file package P2 is task type T4 is entry Send_Data(Data : String; Ti : task_pointer_type); end T4; end P2; package body P2 is task body T4 is Data : String; begin while True loop accept Send_Data(Data, Ti) do -- ===> Problem here! How can I retrieve Ti object. I think I need a "this" pointer inside the task body. Ti has to notify T4 who's the sender of data. -- do some stuff end Send_Data; Ti.Retrieve_Data(Data); -- ===> Problem here! How can I retrieve Ti object end loop; end T4; end P2; I thought to create a task interface (because abstract types for tasks are illegal) in order to use a dynamic dispatching inside Send_Data, in the example identified by the "i" index of Task. --- other file package P_Interface type Tsk is task interface; type Tsk_ptr is access all Tsk'Class; end P_Interface; I've tried in so many ways (inserting local types into the tasks, outiside, into the interface, using explicit casting and so on) to get the things working but without any good outcomes... I even had some problems of circular dependency but eventually I've solved them with "limited with" directive. No problems (for this moment =) ) for the T4 reference. May you help me, please =)? I think this is a quite common problem and so I'm optimistic to receive some useful replies! Thank you very much! ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: "C - like: THIS" pointer to a task type inside a task function 2012-01-23 19:32 "C - like: THIS" pointer to a task type inside a task function Ada BRL @ 2012-01-23 19:59 ` Dmitry A. Kazakov 2012-01-23 22:17 ` tmoran ` (2 more replies) 2012-01-23 20:20 ` Jeffrey Carter ` (2 subsequent siblings) 3 siblings, 3 replies; 19+ messages in thread From: Dmitry A. Kazakov @ 2012-01-23 19:59 UTC (permalink / raw) On Mon, 23 Jan 2012 11:32:39 -0800 (PST), Ada BRL wrote: > I've N clients and one server that communicate each other. > The N clients retrieve data dynamically, send it to the server throgh > enrty call (obviously the server can accept just one call per time) > and wait for the reply from the server (through accept statement). A server cannot wait for itself either "through accept statement" or any other way. T4.Send_Data (Data); accept Retrieve_Data (Data); is a patented way to run into a deadlock. > For this reason the server needs to know on which client call the > entry: That does not follow. Why do the server need to know the caller? > package P1 is > > task type T1 is > entry Retrieve_Data(Data : String); entry Exchange_Data (Data : in out String); An entry can have in, out, in-out parameters like a subprogram call. You can pass parameters in and get the results out, just in one call. > I think this is a quite common problem and so I'm optimistic to > receive some useful replies! It is considered bad design when two components know each other. Usually the software is designed in a way that component relationships are asymmetric, e.g. the callee knows nothing about the caller. Component knows nothing about the container, etc. The advantage of this approach is its robustness. You can have as many callers you need without changing the callee. Imagine, that sine from the math library would have to be modified each time somebody writes a program calling it. For concurrency symmetric relationships impose an additional risk of deadlocking. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: "C - like: THIS" pointer to a task type inside a task function 2012-01-23 19:59 ` Dmitry A. Kazakov @ 2012-01-23 22:17 ` tmoran 2012-01-24 8:47 ` Dmitry A. Kazakov 2012-01-24 17:12 ` Ada BRL 2012-01-24 17:27 ` Ada BRL 2 siblings, 1 reply; 19+ messages in thread From: tmoran @ 2012-01-23 22:17 UTC (permalink / raw) > An entry can have in, out, in-out parameters like a subprogram call. You > can pass parameters in and get the results out, just in one call. If the client task, after giving work to the server, needs to do things other than wait for a result, then adding an "out" parameter won't work. > It is considered bad design when two components know each other. Usually > the software is designed in a way that component relationships are > asymmetric, e.g. the callee knows nothing about the caller. Component knows > nothing about the container, etc. The advantage of this approach is its > robustness. You can have as many callers you need without changing the > callee. True, but if the server really does need to call the client, it will need to know the "name" of the client. You can do this with Ada.Task_Identification: with Ada.Task_Identification; procedure Testti is task type Clients is entry Get_Result(Result : in Character); end Clients; task Server is entry Get_Work(Work : in Character); end Server; task body Clients is Generated_Result: Character; begin for Jobs in 1 .. 5 loop -- we do want eventual termination of this demo! -- generate some work todo, then Server.Get_Work(Work => 'w'); -- do other stuff, then ask for the results select accept Get_Result(Result : in Character) do Generated_Result := Result; end Get_Result; -- use Generated_Result or terminate; -- Server is dead! Don't just hang around. Die. end select; end loop; end Clients; Client_List: array (1 .. 10) of Clients; task body Server is use type Ada.Task_Identification.Task_Id; Todo : Character; Result : Character; Source : Ada.Task_Identification.Task_Id; begin loop select accept Get_Work(Work : in Character) do Todo := Work; Source := Get_Work'Caller; end Get_Work; or terminate; end select; -- handle Todo, generating Result, then pass it back to Source client. for I in Client_List'range loop if Client_List(I)'Identity = Source then Client_List(I).Get_Result(Result); exit; end if; -- if a task other than one in Client_List gave us work, toss it. end loop; end loop; end Server; begin null; -- Client_List and Server tasks are working away... end Testti; ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: "C - like: THIS" pointer to a task type inside a task function 2012-01-23 22:17 ` tmoran @ 2012-01-24 8:47 ` Dmitry A. Kazakov 0 siblings, 0 replies; 19+ messages in thread From: Dmitry A. Kazakov @ 2012-01-24 8:47 UTC (permalink / raw) On Mon, 23 Jan 2012 22:17:00 +0000 (UTC), tmoran@acm.org wrote: >> An entry can have in, out, in-out parameters like a subprogram call. You >> can pass parameters in and get the results out, just in one call. > > If the client task, after giving work to the server, needs to do things > other than wait for a result, then adding an "out" parameter won't work. Yes, but that would not be a N-to-1 service then. The case you are describing is rather N-to-M, when a task may queue several requests to 1..M servers and later wait for completion of these requests as needed. The solution of this problem is not in identifying the caller and then engaging a rendezvous back to it, but rather the classical one: the request is a proper ADT. The client task queues the requests which contain the parameters and/or results. When the task needs the results it waits for the request to complete. protected type Item_Of_Work is [ procedure Set_Parameters (...); ] function Get_Result return ...; entry Wait_For_Completion; [ procedure/entry Cancel; -- Don't want this anymore ] end Item_Of_Work; task type Server is entry Queue (Request : in out Item_Of_Work); end Server; ... Server_1.Queue (This); Server_2.Queue (That); ... This.Wait_For_Completion; -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: "C - like: THIS" pointer to a task type inside a task function 2012-01-23 19:59 ` Dmitry A. Kazakov 2012-01-23 22:17 ` tmoran @ 2012-01-24 17:12 ` Ada BRL 2012-01-24 18:43 ` Dmitry A. Kazakov 2012-01-24 17:27 ` Ada BRL 2 siblings, 1 reply; 19+ messages in thread From: Ada BRL @ 2012-01-24 17:12 UTC (permalink / raw) On 23 Gen, 19:59, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de> wrote: > On Mon, 23 Jan 2012 11:32:39 -0800 (PST), Ada BRL wrote: > > I've N clients and one server that communicate each other. > > The N clients retrieve data dynamically, send it to the server throgh > > enrty call (obviously the server can accept just one call per time) > > and wait for the reply from the server (through accept statement). > > A server cannot wait for itself either "through accept statement" or any > other way. > > T4.Send_Data (Data); > accept Retrieve_Data (Data); > > is a patented way to run into a deadlock. > yes...you are right ... sorry ... =( BUT I MADE A MISTAKE!!! There are two tasks for every communication channel: - one performing input, so retrieving data from the net and sending it to the server (call it T1_IN, T2_IN, ...) - one performing output, so retrieving data from the server and sending it on the net (call it T1_OUT, T2_OUT, ...) > > For this reason the server needs to know on which client call the > > entry: > > That does not follow. Why do the server need to know the caller? The server has to call the right "output" according to the matching "input": received data from T2_IN, server has to send data to T2_OUT and not T1 or T3... > > > package P1 is > > > task type T1 is > > entry Retrieve_Data(Data : String); > > entry Exchange_Data (Data : in out String); > > An entry can have in, out, in-out parameters like a subprogram call. You > can pass parameters in and get the results out, just in one call. > For the reasons above I cannot use in out. > > I think this is a quite common problem and so I'm optimistic to > > receive some useful replies! > > It is considered bad design when two components know each other. Usually > the software is designed in a way that component relationships are > asymmetric, e.g. the callee knows nothing about the caller. Component knows > nothing about the container, etc. The advantage of this approach is its > robustness. You can have as many callers you need without changing the > callee. Imagine, that sine from the math library would have to be modified > each time somebody writes a program calling it. For concurrency symmetric > relationships impose an additional risk of deadlocking. Thank you very much. > > -- > Regards, > Dmitry A. Kazakovhttp://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: "C - like: THIS" pointer to a task type inside a task function 2012-01-24 17:12 ` Ada BRL @ 2012-01-24 18:43 ` Dmitry A. Kazakov 2012-01-25 12:43 ` Ada BRL 0 siblings, 1 reply; 19+ messages in thread From: Dmitry A. Kazakov @ 2012-01-24 18:43 UTC (permalink / raw) On Tue, 24 Jan 2012 09:12:03 -0800 (PST), Ada BRL wrote: > On 23 Gen, 19:59, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de> > wrote: >> On Mon, 23 Jan 2012 11:32:39 -0800 (PST), Ada BRL wrote: >>> I've N clients and one server that communicate each other. >>> The N clients retrieve data dynamically, send it to the server throgh >>> enrty call (obviously the server can accept just one call per time) >>> and wait for the reply from the server (through accept statement). >> >> A server cannot wait for itself either "through accept statement" or any >> other way. >> >> � �T4.Send_Data (Data); >> � �accept Retrieve_Data (Data); >> >> is a patented way to run into a deadlock. >> > yes...you are right ... sorry ... =( BUT I MADE A MISTAKE!!! > > There are two tasks for every communication channel: > - one performing input, so retrieving data from the net and sending it > to the server (call it T1_IN, T2_IN, ...) > - one performing output, so retrieving data from the server and > sending it on the net (call it T1_OUT, T2_OUT, ...) OK. When you are working with sockets you normally do not need a dedicated output task. The network stack is already buffered and most likely asynchronous to the sender once you have initiated send. Thus you could consider sending data straight out of the server. Note also that unless you have a relatively small number of sockets to handle (a dozen or so), a task per socket doing blocking read would not scale. Tasks are used to read sockets simply because it is easier to program this way. If you have 2-3 sockets, why bother with asynchronous socket I/O? But you won't likely get a better performance in terms of data throughout and latencies with separate reader/writer tasks. Having one server engaging rendezvous with writers that would make this design even less reasonable. That is because you have the jobs *serialized* in the server. Writers will be either idle most of the time waiting for the server or else block server, which would want to make a rendezvous with a *concrete* writer each time. You would gain nothing from parallelism here, because serialization of processing is enforced by server, it only appears parallel. Unless there is some considerable post-processing in the writers, it would rather eat performance on meaningless task switching. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: "C - like: THIS" pointer to a task type inside a task function 2012-01-24 18:43 ` Dmitry A. Kazakov @ 2012-01-25 12:43 ` Ada BRL 2012-01-25 13:48 ` Dmitry A. Kazakov 0 siblings, 1 reply; 19+ messages in thread From: Ada BRL @ 2012-01-25 12:43 UTC (permalink / raw) On 24 Gen, 18:43, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de> wrote: > On Tue, 24 Jan 2012 09:12:03 -0800 (PST), Ada BRL wrote: > > On 23 Gen, 19:59, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de> > > wrote: > >> On Mon, 23 Jan 2012 11:32:39 -0800 (PST), Ada BRL wrote: > >>> I've N clients and one server that communicate each other. > >>> The N clients retrieve data dynamically, send it to the server throgh > >>> enrty call (obviously the server can accept just one call per time) > >>> and wait for the reply from the server (through accept statement). > > >> A server cannot wait for itself either "through accept statement" or any > >> other way. > > >> T4.Send_Data (Data); > >> accept Retrieve_Data (Data); > > >> is a patented way to run into a deadlock. > > > yes...you are right ... sorry ... =( BUT I MADE A MISTAKE!!! > > > There are two tasks for every communication channel: > > - one performing input, so retrieving data from the net and sending it > > to the server (call it T1_IN, T2_IN, ...) > > - one performing output, so retrieving data from the server and > > sending it on the net (call it T1_OUT, T2_OUT, ...) > > OK. When you are working with sockets you normally do not need a dedicated > output task. The network stack is already buffered and most likely > asynchronous to the sender once you have initiated send. Thus you could > consider sending data straight out of the server. So, please tell me if I'm right, the server has to implement inside itself the N output socket connections and I just need to have N tasks implementing a socket connection each useful just for reading data from the net and forwarding it to the server? Note also that unless you > have a relatively small number of sockets to handle (a dozen or so), a task > per socket doing blocking read would not scale. Are you referring to the tasks reading from the net? Tasks are used to read > sockets simply because it is easier to program this way. If you have 2-3 > sockets, why bother with asynchronous socket I/O? So I don't have to use tasks neither for reading? Sorry but I haven't got the concept... But you won't likely get > a better performance in terms of data throughout and latencies with > separate reader/writer tasks. Having one server engaging rendezvous with > writers that would make this design even less reasonable. That is because > you have the jobs *serialized* in the server. Writers will be either idle > most of the time waiting for the server or else block server, which would > want to make a rendezvous with a *concrete* writer each time. You would > gain nothing from parallelism here, because serialization of processing is > enforced by server, it only appears parallel. Unless there is some > considerable post-processing in the writers, it would rather eat > performance on meaningless task switching. The writers just receive data from the server and send it over the net... now I recognize it's not a well designed software... :-(... Just to see if I have understood everything: - NO "writers tasks", - N "readers tasks": every task has just one connection (socket) to the peer from which receives data, - Server is connected (by sockets) to N clients to which sends data after elaboration, - Server has one entry like: entry Receive_Data(Id_Reader_task : in Integer; Data : in String), and inside its infinite loop accept this entry, - the generic "reader task" i calls the entry of the server like: Server.Receive_Data(i, data); Thank you very much! You have "opened my eyes"! > > -- > Regards, > Dmitry A. Kazakovhttp://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: "C - like: THIS" pointer to a task type inside a task function 2012-01-25 12:43 ` Ada BRL @ 2012-01-25 13:48 ` Dmitry A. Kazakov 2012-01-25 15:05 ` Ada BRL 2012-01-26 4:17 ` Randy Brukardt 0 siblings, 2 replies; 19+ messages in thread From: Dmitry A. Kazakov @ 2012-01-25 13:48 UTC (permalink / raw) On Wed, 25 Jan 2012 04:43:57 -0800 (PST), Ada BRL wrote: > On 24 Gen, 18:43, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de> > wrote: >> On Tue, 24 Jan 2012 09:12:03 -0800 (PST), Ada BRL wrote: >>> On 23 Gen, 19:59, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de> >>> wrote: >>>> On Mon, 23 Jan 2012 11:32:39 -0800 (PST), Ada BRL wrote: >>>>> I've N clients and one server that communicate each other. >>>>> The N clients retrieve data dynamically, send it to the server throgh >>>>> enrty call (obviously the server can accept just one call per time) >>>>> and wait for the reply from the server (through accept statement). >> >>>> A server cannot wait for itself either "through accept statement" or any >>>> other way. >> >>>> � �T4.Send_Data (Data); >>>> � �accept Retrieve_Data (Data); >> >>>> is a patented way to run into a deadlock. >> >>> yes...you are right ... sorry ... =( BUT I MADE A MISTAKE!!! >> >>> There are two tasks for every communication channel: >>> - one performing input, so retrieving data from the net and sending it >>> to the server (call it T1_IN, T2_IN, ...) >>> - one performing output, so retrieving data from the server and >>> sending it on the net (call it T1_OUT, T2_OUT, ...) >> >> OK. When you are working with sockets you normally do not need a dedicated >> output task. The network stack is already buffered and most likely >> asynchronous to the sender once you have initiated send. Thus you could >> consider sending data straight out of the server. > > So, please tell me if I'm right, the server has to implement inside > itself the N output socket connections and I just need to have N tasks > implementing a socket connection each useful just for reading data > from the net and forwarding it to the server? Useful basically for being blocked when there is no data to read from the socket (actually no data in the network buffer). >> Note also that unless you >> have a relatively small number of sockets to handle (a dozen or so), a task >> per socket doing blocking read would not scale. > > Are you referring to the tasks reading from the net? Yes. There is a limit on the number of threads a process is allowed to have. It is not very big, 200 or so under Windows. If you needed to deal with 1000 connections, it would not help to be able to have 2000 threads, because switching them will consume too much resources. >> Tasks are used to read >> sockets simply because it is easier to program this way. If you have 2-3 >> sockets, why bother with asynchronous socket I/O? > > So I don't have to use tasks neither for reading? Sorry but I haven't > got the concept... One task may service several sockets simultaneously. Normally the OS handles sockets asynchronously to the task reading or writing it, anyway. So it brings nothing to have more than just one task (I don't consider multiple network ports here). The task gets notified when the state of a socket changes. It looks into that socket, takes, for example, the data already read to this time, processes them and go back to sleep. For more information see, for example: http://msdn.microsoft.com/en-us/library/windows/desktop/ms740141%28v=vs.85%29.aspx > Just to see if I have understood everything: > > - NO "writers tasks", > - N "readers tasks": every task has just one connection (socket) to > the peer from which receives data, > - Server is connected (by sockets) to N clients to which sends data > after elaboration, > - Server has one entry like: entry Receive_Data(Id_Reader_task : in > Integer; Data : in String), and inside its infinite loop accept this > entry, > - the generic "reader task" i calls the entry of the server like: > Server.Receive_Data(i, data); You could consider protected objects, as others already suggested. The reader might simply queue the packet read and continue, rather than waiting for a rendezvous with it. Usually, there are higher level protocol superimposed on the socket stream. It is a good idea to handle that in the reader and queue "digested" requests of higher level semantics to the server. Note one important advantage of having a queue of requests rather than communicating directly to the server. The queue decouples the readers from the server. So you could have two or three servers processing the requests from the queue. On a multi-core architecture that could give you better throughout. The number of servers can be adjusted later, you need not to decide it upfront as you would with direct rendezvous. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: "C - like: THIS" pointer to a task type inside a task function 2012-01-25 13:48 ` Dmitry A. Kazakov @ 2012-01-25 15:05 ` Ada BRL 2012-01-25 18:10 ` Dmitry A. Kazakov 2012-01-26 4:17 ` Randy Brukardt 1 sibling, 1 reply; 19+ messages in thread From: Ada BRL @ 2012-01-25 15:05 UTC (permalink / raw) On 25 Gen, 13:48, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de> wrote: > On Wed, 25 Jan 2012 04:43:57 -0800 (PST), Ada BRL wrote: > > On 24 Gen, 18:43, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de> > > wrote: > >> On Tue, 24 Jan 2012 09:12:03 -0800 (PST), Ada BRL wrote: > >>> On 23 Gen, 19:59, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de> > >>> wrote: > >>>> On Mon, 23 Jan 2012 11:32:39 -0800 (PST), Ada BRL wrote: > >>>>> I've N clients and one server that communicate each other. > >>>>> The N clients retrieve data dynamically, send it to the server throgh > >>>>> enrty call (obviously the server can accept just one call per time) > >>>>> and wait for the reply from the server (through accept statement). > > >>>> A server cannot wait for itself either "through accept statement" or any > >>>> other way. > > >>>> T4.Send_Data (Data); > >>>> accept Retrieve_Data (Data); > > >>>> is a patented way to run into a deadlock. > > >>> yes...you are right ... sorry ... =( BUT I MADE A MISTAKE!!! > > >>> There are two tasks for every communication channel: > >>> - one performing input, so retrieving data from the net and sending it > >>> to the server (call it T1_IN, T2_IN, ...) > >>> - one performing output, so retrieving data from the server and > >>> sending it on the net (call it T1_OUT, T2_OUT, ...) > > >> OK. When you are working with sockets you normally do not need a dedicated > >> output task. The network stack is already buffered and most likely > >> asynchronous to the sender once you have initiated send. Thus you could > >> consider sending data straight out of the server. > > > So, please tell me if I'm right, the server has to implement inside > > itself the N output socket connections and I just need to have N tasks > > implementing a socket connection each useful just for reading data > > from the net and forwarding it to the server? > > Useful basically for being blocked when there is no data to read from the > socket (actually no data in the network buffer). > > >> Note also that unless you > >> have a relatively small number of sockets to handle (a dozen or so), a task > >> per socket doing blocking read would not scale. > > > Are you referring to the tasks reading from the net? > > Yes. There is a limit on the number of threads a process is allowed to > have. It is not very big, 200 or so under Windows. If you needed to deal > with 1000 connections, it would not help to be able to have 2000 threads, > because switching them will consume too much resources. > Luckily I don't have thousands of tasks, I can have at about 8 - 10 "readers" from net. > >> Tasks are used to read > >> sockets simply because it is easier to program this way. If you have 2-3 > >> sockets, why bother with asynchronous socket I/O? > > > So I don't have to use tasks neither for reading? Sorry but I haven't > > got the concept... > > One task may service several sockets simultaneously. Normally the OS > handles sockets asynchronously to the task reading or writing it, anyway. > So it brings nothing to have more than just one task (I don't consider > multiple network ports here). The task gets notified when the state of a > socket changes. It looks into that socket, takes, for example, the data > already read to this time, processes them and go back to sleep. For more > information see, for example: > > http://msdn.microsoft.com/en-us/library/windows/desktop/ms740141%28v=... Just a question: If I have understood well, I may have just one thread connected with N clients through N sockets, using the SAME PORT. How may I know if one client (say number 5) is connected or not? I need an array of connections and so on... In the case of N readers I can know it, because there's a mapping one- to-one. In the case unique reader with N sockets, the OS (in my case MS Windows 7 Pro) handles the concurrent requests of sending data to the reader queueing them and delivering each request per time to the (unique) reader. For this reason I must trust the fairness / reliability of the OS. I MUST BE SURE that the data is delivered to the server...what do you suggest me to do? Multiple readers or only one? > > > Just to see if I have understood everything: > > > - NO "writers tasks", > > - N "readers tasks": every task has just one connection (socket) to > > the peer from which receives data, > > - Server is connected (by sockets) to N clients to which sends data > > after elaboration, > > - Server has one entry like: entry Receive_Data(Id_Reader_task : in > > Integer; Data : in String), and inside its infinite loop accept this > > entry, > > - the generic "reader task" i calls the entry of the server like: > > Server.Receive_Data(i, data); > > You could consider protected objects, as others already suggested. The > reader might simply queue the packet read and continue, rather than waiting > for a rendezvous with it. Regardless to the unique reader / N readers, I have to use a protected object that incapsulates a buffer (implemented by an array of strings type); the reader(s) write into this protected buffer and the server reads from it. Am I right? Protected objects implements mutual exclusion by construction. > > Usually, there are higher level protocol superimposed on the socket stream. > It is a good idea to handle that in the reader and queue "digested" > requests of higher level semantics to the server. Yes, this is my case since I have to make some elaboration of incoming data, and I prefer to forward to the server "digested" data rather than raw one. > > Note one important advantage of having a queue of requests rather than > communicating directly to the server. The queue decouples the readers from > the server. So you could have two or three servers processing the requests > from the queue. On a multi-core architecture that could give you better > throughout. The number of servers can be adjusted later, you need not to > decide it upfront as you would with direct rendezvous. Yes, it's clear :-). > > -- > Regards, > Dmitry A. Kazakovhttp://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: "C - like: THIS" pointer to a task type inside a task function 2012-01-25 15:05 ` Ada BRL @ 2012-01-25 18:10 ` Dmitry A. Kazakov 2012-01-26 15:19 ` Ada BRL 0 siblings, 1 reply; 19+ messages in thread From: Dmitry A. Kazakov @ 2012-01-25 18:10 UTC (permalink / raw) On Wed, 25 Jan 2012 07:05:57 -0800 (PST), Ada BRL wrote: > Just a question: > If I have understood well, I may have just one thread connected with N > clients through N sockets, using the SAME PORT. As well as from different Ethernet ports. Reading from one port using multiple tasks is unlikely to give any performance advantage. But if you have, for example a 4-port Ethernet controller, you might wish to assign a separate task for each port. > How may I know if one client (say number 5) is connected or not? I > need an array of connections and so on... Each connection has a socket. Connected/not is a state of a TCP/IP socket. > In the case of N readers I can know it, because there's a mapping one- > to-one. > > In the case unique reader with N sockets, the OS (in my case MS > Windows 7 Pro) handles the concurrent requests of sending data to the > reader queueing them and delivering each request per time to the > (unique) reader. Select() returns list of sockets available to read without blocking. You go through the list reading the data and pushing them further. Typically, you have a state machine associated with each input socket. The machine is fed by the input: often, just one octet, because you don't want to get blocked due to a protocol error. The state machine swallows the octet and depending on its internal state and the octet performs a transition accumulating data as necessary. At some point it queues a request to the server. > I MUST BE SURE that the data is delivered to the server...what do you > suggest me to do? Multiple readers or only one? Delivery is guaranteed (for TCP) and not guaranteed (UDP) independently on the way of reading. Multiple readers is simpler to implement, so you should try this first if the number of sockets is bearable. >> You could consider protected objects, as others already suggested. The >> reader might simply queue the packet read and continue, rather than waiting >> for a rendezvous with it. > > Regardless to the unique reader / N readers, I have to use a protected > object that incapsulates a buffer (implemented by an array of strings type); When readers perform some preprocessing, then elements of the buffer (queue) should likely be something more advanced than mere strings. > the reader(s) write into this protected buffer and the server reads from it. > Am I right? Protected objects implements mutual exclusion by > construction. Yes, it is called "protected action." Waitable operations are entries, like in the case of tasks. Instant operations are procedures. Functions access the object in a way that guaranties coherence. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: "C - like: THIS" pointer to a task type inside a task function 2012-01-25 18:10 ` Dmitry A. Kazakov @ 2012-01-26 15:19 ` Ada BRL 0 siblings, 0 replies; 19+ messages in thread From: Ada BRL @ 2012-01-26 15:19 UTC (permalink / raw) On 25 Gen, 18:10, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de> wrote: > On Wed, 25 Jan 2012 07:05:57 -0800 (PST), Ada BRL wrote: > > Just a question: > > If I have understood well, I may have just one thread connected with N > > clients through N sockets, using the SAME PORT. > > As well as from different Ethernet ports. Reading from one port using > multiple tasks is unlikely to give any performance advantage. But if you > have, for example a 4-port Ethernet controller, you might wish to assign a > separate task for each port. > > > How may I know if one client (say number 5) is connected or not? I > > need an array of connections and so on... > > Each connection has a socket. Connected/not is a state of a TCP/IP socket. > > > In the case of N readers I can know it, because there's a mapping one- > > to-one. > > > In the case unique reader with N sockets, the OS (in my case MS > > Windows 7 Pro) handles the concurrent requests of sending data to the > > reader queueing them and delivering each request per time to the > > (unique) reader. > > Select() returns list of sockets available to read without blocking. You go > through the list reading the data and pushing them further. Typically, you > have a state machine associated with each input socket. The machine is fed > by the input: often, just one octet, because you don't want to get blocked > due to a protocol error. The state machine swallows the octet and depending > on its internal state and the octet performs a transition accumulating data > as necessary. At some point it queues a request to the server. > > > I MUST BE SURE that the data is delivered to the server...what do you > > suggest me to do? Multiple readers or only one? > > Delivery is guaranteed (for TCP) and not guaranteed (UDP) independently on > the way of reading. Multiple readers is simpler to implement, so you should > try this first if the number of sockets is bearable. > > >> You could consider protected objects, as others already suggested. The > >> reader might simply queue the packet read and continue, rather than waiting > >> for a rendezvous with it. > > > Regardless to the unique reader / N readers, I have to use a protected > > object that incapsulates a buffer (implemented by an array of strings type); > > When readers perform some preprocessing, then elements of the buffer > (queue) should likely be something more advanced than mere strings. > > > the reader(s) write into this protected buffer and the server reads from it. > > Am I right? Protected objects implements mutual exclusion by > > construction. > > Yes, it is called "protected action." Waitable operations are entries, like > in the case of tasks. Instant operations are procedures. Functions access > the object in a way that guaranties coherence. > > -- > Regards, > Dmitry A. Kazakovhttp://www.dmitry-kazakov.de Thank you. Just to sum it up: The best soultion is to have: - one reader task connected by sockets on N different ports to N clients, - one protected object "buffer" that receives data from the reader and is read by the server, - one server task that processes data read from the buffer and sends data back directly to the client. The second best solution is to have N reader tasks, each with just one connection to a client (the number of clients is fixed) on a different port. I know that using just one port may result in a bottleneck. Please tell me if I am right, thanks a lot! ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: "C - like: THIS" pointer to a task type inside a task function 2012-01-25 13:48 ` Dmitry A. Kazakov 2012-01-25 15:05 ` Ada BRL @ 2012-01-26 4:17 ` Randy Brukardt 1 sibling, 0 replies; 19+ messages in thread From: Randy Brukardt @ 2012-01-26 4:17 UTC (permalink / raw) "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message news:1rp216zwnjx3j$.rjwu8m3hxgp1.dlg@40tude.net... ... > Note one important advantage of having a queue of requests rather than > communicating directly to the server. The queue decouples the readers from > the server. So you could have two or three servers processing the requests > from the queue. On a multi-core architecture that could give you better > throughout. The number of servers can be adjusted later, you need not to > decide it upfront as you would with direct rendezvous. Right. My spam filter is structured this way. There is a pool of tasks for processing connections, and a manager task that initially receives connections and assigns them to tasks. If there aren't any tasks available, the filter is getting overloaded and the extra connections are just dropped (SMTP will retry them in a while if real, and if junk, who cares?). The connections are processed, and presuming that the connection is not blocked, the incoming mail message is read, a token created for it, and that is queued on the filter queue. There is then a pool of filter tasks, which grab message tokens from the queue, filter the message, and determine what to do with it - delete, quarantine, or deliver. Delete is obvious, quarantine just involves moving the message files to a special place, and in the deliver case the token is put on a delivery queue. And delivery works the same way: there is a pool of delivery tasks, which take messages off the delivery queue whose delivery time is current, and tries to deliver them. If successful, the message is deleted from the server; otherwise it is put back on the delivery queue with a time in the future (in order to support retries). There are a lot more details (like returning non-delivery messages if a message has been retried too long), but that it is general outline -- and it works great. (All of the mail going to the Ada-Comment mailing list, along with many others, goes thru our spam filter - a 100% Ada program.) Randy. ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: "C - like: THIS" pointer to a task type inside a task function 2012-01-23 19:59 ` Dmitry A. Kazakov 2012-01-23 22:17 ` tmoran 2012-01-24 17:12 ` Ada BRL @ 2012-01-24 17:27 ` Ada BRL 2 siblings, 0 replies; 19+ messages in thread From: Ada BRL @ 2012-01-24 17:27 UTC (permalink / raw) I have already inserted a post but it isn't visualized yet... On 23 Gen, 19:59, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de> wrote: > On Mon, 23 Jan 2012 11:32:39 -0800 (PST), Ada BRL wrote: > > I've N clients and one server that communicate each other. > > The N clients retrieve data dynamically, send it to the server throgh > > enrty call (obviously the server can accept just one call per time) > > and wait for the reply from the server (through accept statement). > > A server cannot wait for itself either "through accept statement" or any > other way. > > T4.Send_Data (Data); > accept Retrieve_Data (Data); > I made a mistake, sorry ... :-( I have two tasks for every channel of communication: - input task: retrieves data from the net and send it to the server (call it Ti_IN), - output task: receives data from the server and send it on the net (call it Ti_OUT). For this reason I need: 1) to know who's sending data to the server --> I've already implemented it with "in" parameter, 2) have a reference to the output threads, in order to call every time the entry of the correct thread. For example: T2_IN calls Server.Send_Data(Data, 2); Inside the server I have to call T2_OUT.Retrieve_Data(Data); and NOT the entry on T1_OUT or T3_OUT. So the entry Retrieve_Data is implemented only by the _OUT tasks. > is a patented way to run into a deadlock. I recognize you are definitely true :-)! > > > For this reason the server needs to know on which client call the > > entry: > > That does not follow. Why do the server need to know the caller? > > > package P1 is > > > task type T1 is > > entry Retrieve_Data(Data : String); > > entry Exchange_Data (Data : in out String); > > An entry can have in, out, in-out parameters like a subprogram call. You > can pass parameters in and get the results out, just in one call. > > > I think this is a quite common problem and so I'm optimistic to > > receive some useful replies! > > It is considered bad design when two components know each other. Usually > the software is designed in a way that component relationships are > asymmetric, e.g. the callee knows nothing about the caller. Component knows > nothing about the container, etc. The advantage of this approach is its > robustness. You can have as many callers you need without changing the > callee. Imagine, that sine from the math library would have to be modified > each time somebody writes a program calling it. For concurrency symmetric > relationships impose an additional risk of deadlocking. > > -- > Regards, > Dmitry A. Kazakovhttp://www.dmitry-kazakov.de Thank you very much and sorry for the mistake....but yesterday I have been programming for lots of hours without any rest... ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: "C - like: THIS" pointer to a task type inside a task function 2012-01-23 19:32 "C - like: THIS" pointer to a task type inside a task function Ada BRL 2012-01-23 19:59 ` Dmitry A. Kazakov @ 2012-01-23 20:20 ` Jeffrey Carter 2012-01-24 17:13 ` Ada BRL 2012-01-24 6:39 ` J-P. Rosen 2012-01-25 0:42 ` Adam Beneschan 3 siblings, 1 reply; 19+ messages in thread From: Jeffrey Carter @ 2012-01-23 20:20 UTC (permalink / raw) On 01/23/2012 12:32 PM, Ada BRL wrote: I think perhaps you should become more familiar with basic Ada before attempting something like this. In addition to the use of "in out" parameters already suggested, creating multiple objects of a task type is better than having multiple singleton tasks. > Data : String; This is illegal. > while True loop "loop" all by itself has the same effect, and is clearer. -- Jeff Carter "I was hobbling along, minding my own business, all of a sudden, up he comes, cures me! One minute I'm a leper with a trade, next minute my livelihood's gone! Not so much as a 'by your leave!' You're cured, mate. Bloody do-gooder!" Monty Python's Life of Brian 76 --- Posted via news://freenews.netfront.net/ - Complaints to news@netfront.net --- ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: "C - like: THIS" pointer to a task type inside a task function 2012-01-23 20:20 ` Jeffrey Carter @ 2012-01-24 17:13 ` Ada BRL 0 siblings, 0 replies; 19+ messages in thread From: Ada BRL @ 2012-01-24 17:13 UTC (permalink / raw) On 23 Gen, 20:20, Jeffrey Carter <spam.jrcarter....@spam.not.acm.org> wrote: > On 01/23/2012 12:32 PM, Ada BRL wrote: > > I think perhaps you should become more familiar with basic Ada before attempting > something like this. In addition to the use of "in out" parameters already > suggested, creating multiple objects of a task type is better than having > multiple singleton tasks. > > > Data : String; > > This is illegal. I know, was just an example, not a copy paste of my code :-). > > > while True loop > > "loop" all by itself has the same effect, and is clearer. See above. > > -- > Jeff Carter > "I was hobbling along, minding my own business, all of a > sudden, up he comes, cures me! One minute I'm a leper with > a trade, next minute my livelihood's gone! Not so much as a > 'by your leave!' You're cured, mate. Bloody do-gooder!" > Monty Python's Life of Brian > 76 > > --- Posted via news://freenews.netfront.net/ - Complaints to n...@netfront.net --- ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: "C - like: THIS" pointer to a task type inside a task function 2012-01-23 19:32 "C - like: THIS" pointer to a task type inside a task function Ada BRL 2012-01-23 19:59 ` Dmitry A. Kazakov 2012-01-23 20:20 ` Jeffrey Carter @ 2012-01-24 6:39 ` J-P. Rosen 2012-01-25 0:42 ` Adam Beneschan 3 siblings, 0 replies; 19+ messages in thread From: J-P. Rosen @ 2012-01-24 6:39 UTC (permalink / raw) Le 23/01/2012 20:32, Ada BRL a �crit : I too have concerns about your design, but to answer your specific question: > accept Send_Data(Data, Ti) do -- ===> Problem here! How can I > retrieve Ti object. I think I need a "this" pointer inside the task > body. Ti has to notify T4 who's the sender of data. > Inside the body of T1 (or any task type), the name T1 acts as a "this", i.e. it is not interpreted as a task type, but as a name that designate the current task. If all your clients are of the same type, use an access to this task type and T1'access can be used as a pointer to the current task. If you need several task types, use a pointer to an interface that all task types implement. But there can be many other solutions, assuming you really need two-stage communication. F.E., if know you have a limited number of clients, Retrieve_Data could be turned into an entry family, and Send_Data would provide a token (index into the entry family) where the client would retrieve its own data. This way, it's always the client who calls the server. -- J-P. Rosen Adalog 2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX Tel: +33 1 45 29 21 52, Fax: +33 1 45 29 25 00 http://www.adalog.fr ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: "C - like: THIS" pointer to a task type inside a task function 2012-01-23 19:32 "C - like: THIS" pointer to a task type inside a task function Ada BRL ` (2 preceding siblings ...) 2012-01-24 6:39 ` J-P. Rosen @ 2012-01-25 0:42 ` Adam Beneschan 2012-01-25 0:46 ` Adam Beneschan 2012-01-25 7:38 ` J-P. Rosen 3 siblings, 2 replies; 19+ messages in thread From: Adam Beneschan @ 2012-01-25 0:42 UTC (permalink / raw) On Jan 23, 11:32 am, Ada BRL <ada.brl.2...@gmail.com> wrote: > Dear all, > > I'm experiencing an issue about local and not local pointers... > > I've N clients and one server that communicate each other. > The N clients retrieve data dynamically, send it to the server throgh > enrty call (obviously the server can accept just one call per time) > and wait for the reply from the server (through accept statement). > For this reason the server needs to know on which client call the > entry: > one time could be the 3th, another the 1st and so on... I think you should look into protected types, which may be the best way to solve your problem (or at least some other problems that may be like yours). I'm not sure what exactly you're trying to do, but it sounds something like this: You have a server and a number of clients. Each client may, at some point, initiate a certain kind of request to the server. The client may want to do other things (OK, that might be Tom's idea and not yours) and then, when it's done, wait for the request to be completed and retrieve the result data from the server. I think the problem is that using "accept" to wait for the server to complete the request doesn't work very well, especially when your clients are of several different task types. There's no way in Ada to get the server to call a Receive entry without knowing the type of the task declaring the entry; even if the entries of different task types all have the same name Receive and the same parameter profile, it just won't work. J-P mentioned using interfaces but I think this could get messy. A better idea (in my opinion) is to set things up so that the client will *call* an entry, rather than accept an entry, when it's ready to wait for the request to be completed. It can't be an entry in the server, though, since there's no construct in Ada to "accept" an entry just from one specific task. In Ada 83, I would have had the server create a new, small "helper" task for this purpose; the server would create a new task when the request is initiated, and later it would tell that task when the request can be completed, and the client would wait on that task. Now, protected types can be used for a similar purpose. Something like: protected type Request_Control is entry Retrieve_Data (Data : String); -- other entries that the server would use end Request_Control; type Request_Control_Acc is access all Request_Control; Then, the client would do something like: Req : Request_Control_Acc; loop Server.Send_Data (Data, Req); -- where Req is an OUT parameter -- to the entry -- do some other stuff -- then when you're ready to retrieve the result: Req.Retrieve_Data (Data); -- etc. end loop; The server, when it gets Send_Data, would allocate a new Request_Control and give the access back to the client. The server would also save this access in its own tables so that it can communicate with it when it's ready to signal that the request is complete. Later, the server would call some other operation of Request_Control when the request is complete, and this would open up the Retrieve_Data entry so that the client can now unblock (if it is waiting on Retrieve_Entry) and retrieve the data. This would also work if your client has two tasks and you want one task to initiate the request and the other to retrieve the data (I'm not sure if this is what you meant in one of your later posts). The first task would just have to get the Req value to the second task somehow. I'll let you read about protected types and figure out how you'd set them up to make everything work. Again, I don't know if this is exactly the kind of problem you're trying to solve, but something like this would help with a lot of problems in the same class, so hopefully it will be of some use. -- Adam ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: "C - like: THIS" pointer to a task type inside a task function 2012-01-25 0:42 ` Adam Beneschan @ 2012-01-25 0:46 ` Adam Beneschan 2012-01-25 7:38 ` J-P. Rosen 1 sibling, 0 replies; 19+ messages in thread From: Adam Beneschan @ 2012-01-25 0:46 UTC (permalink / raw) On Jan 24, 4:42 pm, Adam Beneschan <a...@irvine.com> wrote: > A better idea (in my opinion) is to set things up so that the client > will *call* an entry, rather than accept an entry, when it's ready to > wait for the request to be completed. It can't be an entry in the > server, though, since there's no construct in Ada to "accept" an entry > just from one specific task. In Ada 83, I would have had the server > create a new, small "helper" task for this purpose; the server would > create a new task when the request is initiated, and later it would > tell that task when the request can be completed, and the client would > wait on that task. Now, protected types can be used for a similar > purpose.... OK, I didn't realize it at the time, but this is pretty much the same thing Dmitry suggested. Just to give credit where it's due... -- Adam ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: "C - like: THIS" pointer to a task type inside a task function 2012-01-25 0:42 ` Adam Beneschan 2012-01-25 0:46 ` Adam Beneschan @ 2012-01-25 7:38 ` J-P. Rosen 1 sibling, 0 replies; 19+ messages in thread From: J-P. Rosen @ 2012-01-25 7:38 UTC (permalink / raw) Le 25/01/2012 01:42, Adam Beneschan a �crit : > A better idea (in my opinion) is to set things up so that the client > will *call* an entry, rather than accept an entry, when it's ready to > wait for the request to be completed. It can't be an entry in the > server, though, since there's no construct in Ada to "accept" an entry > just from one specific task. In a sense, you can. In the first rendezvous, provide to the client an index into an entry family used to retrieve the data. Excerpt from the client side: Server.Send_Data (Data, Inx); -- do something Server.Retrieve_Data(Inx)(Data); -- J-P. Rosen Adalog 2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX Tel: +33 1 45 29 21 52, Fax: +33 1 45 29 25 00 http://www.adalog.fr ^ permalink raw reply [flat|nested] 19+ messages in thread
end of thread, other threads:[~2012-01-26 15:19 UTC | newest] Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2012-01-23 19:32 "C - like: THIS" pointer to a task type inside a task function Ada BRL 2012-01-23 19:59 ` Dmitry A. Kazakov 2012-01-23 22:17 ` tmoran 2012-01-24 8:47 ` Dmitry A. Kazakov 2012-01-24 17:12 ` Ada BRL 2012-01-24 18:43 ` Dmitry A. Kazakov 2012-01-25 12:43 ` Ada BRL 2012-01-25 13:48 ` Dmitry A. Kazakov 2012-01-25 15:05 ` Ada BRL 2012-01-25 18:10 ` Dmitry A. Kazakov 2012-01-26 15:19 ` Ada BRL 2012-01-26 4:17 ` Randy Brukardt 2012-01-24 17:27 ` Ada BRL 2012-01-23 20:20 ` Jeffrey Carter 2012-01-24 17:13 ` Ada BRL 2012-01-24 6:39 ` J-P. Rosen 2012-01-25 0:42 ` Adam Beneschan 2012-01-25 0:46 ` Adam Beneschan 2012-01-25 7:38 ` J-P. Rosen
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox