digitalmars.D - public MessageBox
- Nathan M. Swan (11/11) Mar 20 2012 After playing around with making a library with uses threads, I
- Sean Kelly (8/9) Mar 21 2012 realized it would be nice if there could be multiple inter-thread =
- Nathan M. Swan (28/38) Mar 21 2012 What about this pseudocode?
- Sean Kelly (12/49) Mar 21 2012 it would be nice if there could be multiple inter-thread mailboxes than...
- David Nadlinger (9/13) Mar 22 2012 Nice to hear that I'm not alone with that opinion – I hit the
- Sean Kelly (15/21) Mar 22 2012 wonderful and powerful, and the implementation is great. But the fact =
- Nathan M. Swan (19/31) Mar 21 2012 After thinking about this more, this is my proposal for the API.
- dennis luehring (4/7) Mar 21 2012 how is queued runned - another thread, or can i only communicate to the
- Paulo Pinto (24/34) Mar 22 2012 Making such interface public would even allow to integrate D communicati...
- Sean Kelly (23/48) Mar 22 2012 t would be nice if there could be multiple inter-thread mailboxes than j...
- Nathan M. Swan (11/24) Mar 22 2012 I think they would be passed as parameters to spawn or received
- Sean Kelly (21/32) Mar 22 2012 e (keep in mind that we'll be adding interprocess messaging at some poin...
- Nathan M. Swan (47/86) Mar 22 2012 But what if the client spawns threads?
- Sean Kelly (36/91) Mar 22 2012 message queue (keep in mind that we'll be adding interprocess messaging ...
- Nathan M. Swan (12/23) Mar 22 2012 I see your point. To make this easier, may I suggest:
- David Nadlinger (4/7) Mar 23 2012 Are you trying to build std.concurrency from Git master against
- Nathan M. Swan (3/6) Mar 23 2012 I cloned from git://github.com/D-Programming-Language/phobos.git
- Dmitry Olshansky (4/11) Mar 23 2012 replace the original phobos after rebuilding it?
- Sean Kelly (5/11) Mar 23 2012 058 or something like that?
- deadalnix (2/6) Mar 22 2012 They will, even with different boxes.
- David Nadlinger (2/3) Mar 22 2012 Similarly succinct: How so?
- deadalnix (3/6) Mar 22 2012 They will because of synchronization. This cost will not be transparent....
After playing around with making a library with uses threads, I realized it would be nice if there could be multiple inter-thread mailboxes than just one per thread. That way, client code and third-party library code don't interfere with each other. So this is my proposal: that std.concurrency is modified so that class MessageBox is public and MessageBoxs be passed around through other MessageBoxs, or perhaps another class is devised for this. I'm not sure of the implications of this, though I know I would find it very useful by allowing me to write code without ("import core."~someLowLevelModule)
Mar 20 2012
On Mar 20, 2012, at 8:37 PM, Nathan M. Swan wrote:After playing around with making a library with uses threads, I =realized it would be nice if there could be multiple inter-thread = mailboxes than just one per thread. That way, client code and = third-party library code don't interfere with each other. They shouldn't interfere anyway. The third-party code just has to = devise a message format that client code won't look for. Though if the = client discards messages arbitrarily via receive((Variant v) {}) then = all bets are off.=
Mar 21 2012
On Wednesday, 21 March 2012 at 19:53:55 UTC, Sean Kelly wrote:On Mar 20, 2012, at 8:37 PM, Nathan M. Swan wrote:What about this pseudocode? Thread1: spawn Thread2 library sends LibMsg client sends ClientMsg Thread2: client receives ClientMsg library receives LibMsg The client will receiveOnly!ClientMsg() and get a MessageMismatch. With multiple MessageBoxes: Thread1: clientmail = new MessageBox spawn Thread2(libobj, clientmail) libobj.mb.send(LibMsg) cleintmail.send(ClientMsg) Thread2: clientmail.receive(ClientMsg) libobj.mb.send(LibMsg) If you scroll down to the section commented out as "doesn't work", it would work if my implementation could use MessageBoxes: https://github.com/carlor/dcaflib/blob/master/buggy/asyncobj.d As I posted a while back, the concept of a variant message queue is wonderful and powerful, and the implementation is great. But the fact that you can't declare "auto mq = new MessageQueue()" is a gaping whole in an otherwise A+ API. (A+ as the grade, not the array programming language ;) ) NMSAfter playing around with making a library with uses threads, I realized it would be nice if there could be multiple inter-thread mailboxes than just one per thread. That way, client code and third-party library code don't interfere with each other.They shouldn't interfere anyway. The third-party code just has to devise a message format that client code won't look for. Though if the client discards messages arbitrarily via receive((Variant v) {}) then all bets are off.
Mar 21 2012
On Mar 21, 2012, at 5:30 PM, "Nathan M. Swan" <nathanmswan gmail.com> wrote:=On Wednesday, 21 March 2012 at 19:53:55 UTC, Sean Kelly wrote:it would be nice if there could be multiple inter-thread mailboxes than jus= t one per thread. That way, client code and third-party library code don't i= nterfere with each other.On Mar 20, 2012, at 8:37 PM, Nathan M. Swan wrote: =20After playing around with making a library with uses threads, I realized=a message format that client code won't look for. Though if the client dis= cards messages arbitrarily via receive((Variant v) {}) then all bets are off= .=20 They shouldn't interfere anyway. The third-party code just has to devise==20 What about this pseudocode? =20 Thread1: spawn Thread2 library sends LibMsg client sends ClientMsg =20 Thread2: client receives ClientMsg library receives LibMsg =20 The client will receiveOnly!ClientMsg() and get a MessageMismatch. =20 With multiple MessageBoxes: =20 Thread1: clientmail =3D new MessageBox spawn Thread2(libobj, clientmail) libobj.mb.send(LibMsg) cleintmail.send(ClientMsg) =20 Thread2: clientmail.receive(ClientMsg) libobj.mb.send(LibMsg) =20 If you scroll down to the section commented out as "doesn't work", it woul=d work if my implementation could use MessageBoxes:=20 https://github.com/carlor/dcaflib/blob/master/buggy/asyncobj.d =20 As I posted a while back, the concept of a variant message queue is wonder=ful and powerful, and the implementation is great. But the fact that you can= 't declare "auto mq =3D new MessageQueue()" is a gaping whole in an otherwis= e A+ API. Oops you're right. I tend to forget about receiveOnly.=20=
Mar 21 2012
On Thursday, 22 March 2012 at 00:30:51 UTC, Nathan M. Swan wrote:As I posted a while back, the concept of a variant message queue is wonderful and powerful, and the implementation is great. But the fact that you can't declare "auto mq = new MessageQueue()" is a gaping whole in an otherwise A+ API.Nice to hear that I'm not alone with that opinion – I hit the same problem when implementing a request log file writer for Thrift, which runs in a separate thread and communicates with the main thread via a message queue. It works great and performed even better than a similar C++ version due to lower lock contention, but the user'd better not try to call receiveOnly!() from »his« thread… David
Mar 22 2012
On Mar 22, 2012, at 8:49 AM, David Nadlinger wrote:On Thursday, 22 March 2012 at 00:30:51 UTC, Nathan M. Swan wrote:wonderful and powerful, and the implementation is great. But the fact = that you can't declare "auto mq =3D new MessageQueue()" is a gaping = whole in an otherwise A+ API.As I posted a while back, the concept of a variant message queue is ==20 Nice to hear that I'm not alone with that opinion =96 I hit the same =problem when implementing a request log file writer for Thrift, which = runs in a separate thread and communicates with the main thread via a = message queue.=20 It works great and performed even better than a similar C++ version =due to lower lock contention, but the user'd better not try to call = receiveOnly!() from =BBhis=AB thread=85 And this is why I've never used receiveOnly. A simple way to receive a = specific message type is great, but throwing if there's anything else in = the queue isn't generally what you want, as it assumes complete = knowledge of all messages received by the application. Perhaps what's = needed here is something semantically like receiveOnly that doesn't = throw?=
Mar 22 2012
On Wednesday, 21 March 2012 at 03:37:35 UTC, Nathan M. Swan wrote:After playing around with making a library with uses threads, I realized it would be nice if there could be multiple inter-thread mailboxes than just one per thread. That way, client code and third-party library code don't interfere with each other. So this is my proposal: that std.concurrency is modified so that class MessageBox is public and MessageBoxs be passed around through other MessageBoxs, or perhaps another class is devised for this. I'm not sure of the implications of this, though I know I would find it very useful by allowing me to write code without ("import core."~someLowLevelModule)After thinking about this more, this is my proposal for the API. Backward compatibility is more important here than in other places because it is documented in TDPL. Each Tid contains a default MessageQueue accessible by property messageQueue. The send/receive functions and their variants operate on the tid's default messageQueue. The interface for class MessageQueue: void send(T...)(T vals); void prioritySend(T...)(T vals); void receive(T...)(T ops); receiveOnlyRet!(T) receiveOnly(T...)(T ops); bool receiveTimeout(T...)(Duration duration, T ops); property void maxSize(size_t size); property void onCrowding(OnCrowding oc); property void onCrowding(bool function(MessageQueue) doThis); Hopefully, this won't break any current code, and it will be easy to implement.
Mar 21 2012
Am 22.03.2012 05:12, schrieb Nathan M. Swan:On Wednesday, 21 March 2012 at 03:37:35 UTC, Nathan M. Swan wrote: Each Tid contains a default MessageQueue accessible by property messageQueue.how is queued runned - another thread, or can i only communicate to the tid-thread by using the queue? if its another - don't we just double the amount of used thread - what is not a very good idea
Mar 21 2012
Making such interface public would even allow to integrate D communication mechanisms between processes/machines, similar to what Akka allows. "Nathan M. Swan" wrote in message news:ladihiaieksszjodfbyn forum.dlang.org... On Wednesday, 21 March 2012 at 03:37:35 UTC, Nathan M. Swan wrote:After playing around with making a library with uses threads, I realized it would be nice if there could be multiple inter-thread mailboxes than just one per thread. That way, client code and third-party library code don't interfere with each other. So this is my proposal: that std.concurrency is modified so that class MessageBox is public and MessageBoxs be passed around through other MessageBoxs, or perhaps another class is devised for this. I'm not sure of the implications of this, though I know I would find it very useful by allowing me to write code without ("import core."~someLowLevelModule)After thinking about this more, this is my proposal for the API. Backward compatibility is more important here than in other places because it is documented in TDPL. Each Tid contains a default MessageQueue accessible by property messageQueue. The send/receive functions and their variants operate on the tid's default messageQueue. The interface for class MessageQueue: void send(T...)(T vals); void prioritySend(T...)(T vals); void receive(T...)(T ops); receiveOnlyRet!(T) receiveOnly(T...)(T ops); bool receiveTimeout(T...)(Duration duration, T ops); property void maxSize(size_t size); property void onCrowding(OnCrowding oc); property void onCrowding(bool function(MessageQueue) doThis); Hopefully, this won't break any current code, and it will be easy to implement.
Mar 22 2012
On Mar 21, 2012, at 9:12 PM, "Nathan M. Swan" <nathanmswan gmail.com> wrote:=On Wednesday, 21 March 2012 at 03:37:35 UTC, Nathan M. Swan wrote:t would be nice if there could be multiple inter-thread mailboxes than just o= ne per thread. That way, client code and third-party library code don't inte= rfere with each other.After playing around with making a library with uses threads, I realized i=ssageBox is public and MessageBoxs be passed around through other MessageBox= s, or perhaps another class is devised for this.=20 So this is my proposal: that std.concurrency is modified so that class Me=ery useful by allowing me to write code without ("import core."~someLowLevel= Module)=20 I'm not sure of the implications of this, though I know I would find it v==20 After thinking about this more, this is my proposal for the API. Backward c=ompatibility is more important here than in other places because it is docum= ented in TDPL.=20 Each Tid contains a default MessageQueue accessible by property messageQue=ue.=20 The send/receive functions and their variants operate on the tid's default=messageQueue.=20 The interface for class MessageQueue: =20 void send(T...)(T vals); void prioritySend(T...)(T vals); void receive(T...)(T ops); receiveOnlyRet!(T) receiveOnly(T...)(T ops); bool receiveTimeout(T...)(Duration duration, T ops); property void maxSize(size_t size); property void onCrowding(OnCrowding oc); property void onCrowding(bool function(MessageQueue) doThis); =20 Hopefully, this won't break any current code, and it will be easy to imple=ment. I can see adapting the API so that each thread has a default message queue (= keep in mind that we'll be adding interprocess messaging at some point via t= he same routines). I'm not yet clear how the existence of alternate message q= ueues could be communicated to other portions of the code though. register()= is one way I suppose. Really what's happening here is that Tid is being rep= laced by a queue ID, not extended with a mutable variable.=20 I guess Tid would become an alias for the Qid created when a thread is spawn= ed. What I really don't want though, is for receive() to operate on a messag= e queue created in a different thread. Messaging would become substantially s= lower if receive() had to be synchronized.=20=
Mar 22 2012
On Thursday, 22 March 2012 at 15:53:56 UTC, Sean Kelly wrote:I can see adapting the API so that each thread has a default message queue (keep in mind that we'll be adding interprocess messaging at some point via the same routines). I'm not yet clear how the existence of alternate message queues could be communicated to other portions of the code though. register() is one way I suppose. Really what's happening here is that Tid is being replaced by a queue ID, not extended with a mutable variable.I think they would be passed as parameters to spawn or received from the default message queue.I guess Tid would become an alias for the Qid created when a thread is spawned. What I really don't want though, is for receive() to operate on a message queue created in a different thread. Messaging would become substantially slower if receive() had to be synchronized.That's a drawback I haven't considered. To solve this, it would be made part of the contract that receiving must all be done in one thread. I can't think of a use where receiving in multiple threads would apply, but if it would, a SynchronizedMessageQueue subclass could easily be drawn up that broadens the contract and synchronizes for receive(). BTW, how do you unittest just the std.concurrency module?
Mar 22 2012
On Mar 22, 2012, at 12:06 PM, "Nathan M. Swan" <nathanmswan gmail.com> wrote= :On Thursday, 22 March 2012 at 15:53:56 UTC, Sean Kelly wrote:e (keep in mind that we'll be adding interprocess messaging at some point vi= a the same routines). I'm not yet clear how the existence of alternate messa= ge queues could be communicated to other portions of the code though. regist= er() is one way I suppose. Really what's happening here is that Tid is being= replaced by a queue ID, not extended with a mutable variable.I can see adapting the API so that each thread has a default message queu==20 I think they would be passed as parameters to spawn or received from the d=efault message queue. But will either of those solve the problem you outlined where user code is c= alling receiveOnly and bumping into a message meant for a third-party API? I= f the API is spawning threads they typically won't be running user code, or a= t least would certainly impose restrictions on message queue use by called u= ser code. And in the case of sending the Qid to the default queue, you end u= p with a race condition where user code might call receiveOnly.=20awned. What I really don't want though, is for receive() to operate on a mes= sage queue created in a different thread. Messaging would become substantial= ly slower if receive() had to be synchronized.I guess Tid would become an alias for the Qid created when a thread is sp==20 That's a drawback I haven't considered. To solve this, it would be made pa=rt of the contract that receiving must all be done in one thread.=20 I can't think of a use where receiving in multiple threads would apply, bu=t if it would, a SynchronizedMessageQueue subclass could easily be drawn up t= hat broadens the contract and synchronizes for receive().=20 BTW, how do you unittest just the std.concurrency module?Not easily, since a failure often means that a thread hangs.=20=
Mar 22 2012
On Thursday, 22 March 2012 at 21:27:40 UTC, Sean Kelly wrote:On Mar 22, 2012, at 12:06 PM, "Nathan M. Swan" <nathanmswan gmail.com> wrote:But what if the client spawns threads? An example would be with a desktop GUI. In a background thread meant for a CPU-intensive task, they want to update a progress indicator and send partially-calculated data to a main-thread. void mainThread() { string data; auto mq = new MessageQueue(); spawn(&backgroundThread, mq, pi); pi.onChange = (double val) { if (val == 0.5) { data = me.receiveOnly!string(); } else { data ~= me.receiveOnly!string(); } }; } void backgroundThread(MessageQueue me, ProgressIndicator pi) { // part 1 of calculations... me.send(partiallyCalculatedData); pi.value = 0.5; // implementation: this._queue.send(UpdateValue(value)) // part 2... me.send(theRestOfTheData); pi.value = 1.0; } With one MessageQueue per thread, the mailbox would contain a (string, UpdateValue, string, UpdateValue). The mainThread would expect a (UpdateValue, string, UpdateValue, string). This way, the client code is separated from the library. The default queue is an idea suggested for backward compatibility, and new programmers wouldn't be encouraged to use it.On Thursday, 22 March 2012 at 15:53:56 UTC, Sean Kelly wrote:But will either of those solve the problem you outlined where user code is calling receiveOnly and bumping into a message meant for a third-party API? If the API is spawning threads they typically won't be running user code, or at least would certainly impose restrictions on message queue use by called user code. And in the case of sending the Qid to the default queue, you end up with a race condition where user code might call receiveOnly.I can see adapting the API so that each thread has a default message queue (keep in mind that we'll be adding interprocess messaging at some point via the same routines). I'm not yet clear how the existence of alternate message queues could be communicated to other portions of the code though. register() is one way I suppose. Really what's happening here is that Tid is being replaced by a queue ID, not extended with a mutable variable.I think they would be passed as parameters to spawn or received from the default message queue.Linking fails (I'm on OSX): $ rdmd --main -unittest std/concurrency.d Undefined symbols for architecture x86_64: "_D3std3utf10strideImplFNaNeamZk", referenced from: _D3std3utf15__T6strideTAxaZ6strideFNaNfxAamZk in concurrency.d.o _D3std3utf14__T6strideTAaZ6strideFNaNfxAamZk in concurrency.d.o _D3std3utf15__T6strideTAyaZ6strideFNaNfxAyamZk in concurrency.d.o ld: symbol(s) not found for architecture x86_64 collect2: ld returned 1 exit status --- errorlevel 1 Thanks, NMSNot easily, since a failure often means that a thread hangs.I guess Tid would become an alias for the Qid created when a thread is spawned. What I really don't want though, is for receive() to operate on a message queue created in a different thread. Messaging would become substantially slower if receive() had to be synchronized.That's a drawback I haven't considered. To solve this, it would be made part of the contract that receiving must all be done in one thread. I can't think of a use where receiving in multiple threads would apply, but if it would, a SynchronizedMessageQueue subclass could easily be drawn up that broadens the contract and synchronizes for receive(). BTW, how do you unittest just the std.concurrency module?
Mar 22 2012
On Mar 22, 2012, at 4:01 PM, Nathan M. Swan wrote:On Thursday, 22 March 2012 at 21:27:40 UTC, Sean Kelly wrote:<nathanmswan gmail.com> wrote:On Mar 22, 2012, at 12:06 PM, "Nathan M. Swan" =message queue (keep in mind that we'll be adding interprocess messaging = at some point via the same routines). I'm not yet clear how the = existence of alternate message queues could be communicated to other = portions of the code though. register() is one way I suppose. Really = what's happening here is that Tid is being replaced by a queue ID, not = extended with a mutable variable.=20On Thursday, 22 March 2012 at 15:53:56 UTC, Sean Kelly wrote:I can see adapting the API so that each thread has a default =the default message queue.I think they would be passed as parameters to spawn or received from =code is calling receiveOnly and bumping into a message meant for a = third-party API? If the API is spawning threads they typically won't be = running user code, or at least would certainly impose restrictions on = message queue use by called user code. And in the case of sending the = Qid to the default queue, you end up with a race condition where user = code might call receiveOnly.=20 But will either of those solve the problem you outlined where user =for a CPU-intensive task, they want to update a progress indicator and = send partially-calculated data to a main-thread.=20=20 But what if the client spawns threads? =20 An example would be with a desktop GUI. In a background thread meant ==20 void mainThread() { string data; auto mq =3D new MessageQueue(); spawn(&backgroundThread, mq, pi); pi.onChange =3D (double val) { if (val =3D=3D 0.5) { data =3D me.receiveOnly!string(); } else { data ~=3D me.receiveOnly!string(); } }; } =20 void backgroundThread(MessageQueue me, ProgressIndicator pi) { // part 1 of calculations... me.send(partiallyCalculatedData); pi.value =3D 0.5; // implementation: =this._queue.send(UpdateValue(value))// part 2... me.send(theRestOfTheData); pi.value =3D 1.0; } =20 With one MessageQueue per thread, the mailbox would contain a (string, =UpdateValue, string, UpdateValue). The mainThread would expect a = (UpdateValue, string, UpdateValue, string). While sending messages like a bare string might be good for example = code, any real application is going to use structured messages whose = type is specific to what the message is for, contains fields like sender = Tid, etc. It seems like you're aiming more for CSP where you'd create a = separate communication channel per use. You could even fake it by = wrapping send/receive with your own CSP-like API, though it's quite = likely that a from-scratch CSP style implementation would be faster = because there'd be no need to package messages.is spawned. What I really don't want though, is for receive() to operate = on a message queue created in a different thread. Messaging would become = substantially slower if receive() had to be synchronized.I guess Tid would become an alias for the Qid created when a thread =made part of the contract that receiving must all be done in one thread.That's a drawback I haven't considered. To solve this, it would be =apply, but if it would, a SynchronizedMessageQueue subclass could easily = be drawn up that broadens the contract and synchronizes for receive().I can't think of a use where receiving in multiple threads would =Used to work, and std.concurrency doesn't even use std.utf. Not sure = what's going on there.==20 Linking fails (I'm on OSX): =20 $ rdmd --main -unittest std/concurrency.d Undefined symbols for architecture x86_64: "_D3std3utf10strideImplFNaNeamZk", referenced from: _D3std3utf15__T6strideTAxaZ6strideFNaNfxAamZk in concurrency.d.o _D3std3utf14__T6strideTAaZ6strideFNaNfxAamZk in concurrency.d.o _D3std3utf15__T6strideTAyaZ6strideFNaNfxAyamZk in concurrency.d.o ld: symbol(s) not found for architecture x86_64 collect2: ld returned 1 exit status --- errorlevel 1BTW, how do you unittest just the std.concurrency module?=20 Not easily, since a failure often means that a thread hangs.
Mar 22 2012
On Friday, 23 March 2012 at 00:14:00 UTC, Sean Kelly wrote:While sending messages like a bare string might be good for example code, any real application is going to use structured messages whose type is specific to what the message is for, contains fields like sender Tid, etc. It seems like you're aiming more for CSP where you'd create a separate communication channel per use. You could even fake it by wrapping send/receive with your own CSP-like API, though it's quite likely that a from-scratch CSP style implementation would be faster because there'd be no need to package messages.I see your point. To make this easier, may I suggest: T receiveNext(T)() { T r; receive((T t) {r = t;}); return r; } A big reason for the use of receiveOnly (in my code) is its convenience. receiveNext, and a discouragement of using receiveOnly, would be a simpler solution.Used to work, and std.concurrency doesn't even use std.utf. Not sure what's going on there.Weird :( NMS
Mar 22 2012
On Friday, 23 March 2012 at 01:35:05 UTC, Nathan M. Swan wrote:Are you trying to build std.concurrency from Git master against Phobos 2.058 or something like that? DavidUsed to work, and std.concurrency doesn't even use std.utf. Not sure what's going on there.Weird :(
Mar 23 2012
On Friday, 23 March 2012 at 12:36:42 UTC, David Nadlinger wrote:Are you trying to build std.concurrency from Git master against Phobos 2.058 or something like that? DavidI cloned from git://github.com/D-Programming-Language/phobos.git NMS
Mar 23 2012
On 23.03.2012 22:17, Nathan M. Swan wrote:On Friday, 23 March 2012 at 12:36:42 UTC, David Nadlinger wrote:replace the original phobos after rebuilding it? -- Dmitry OlshanskyAre you trying to build std.concurrency from Git master against Phobos 2.058 or something like that? DavidI cloned from git://github.com/D-Programming-Language/phobos.git NMS
Mar 23 2012
On Mar 23, 2012, at 11:17 AM, "Nathan M. Swan" <nathanmswan gmail.com> wrote= :On Friday, 23 March 2012 at 12:36:42 UTC, David Nadlinger wrote:058 or something like that?Are you trying to build std.concurrency from Git master against Phobos 2.=If you're running Phobos from git and something doesn't work, you likely nee= d to use the latest DMD from git as well.=20==20 David=20 I cloned from git://github.com/D-Programming-Language/phobos.git
Mar 23 2012
Le 21/03/2012 04:37, Nathan M. Swan a écrit :After playing around with making a library with uses threads, I realized it would be nice if there could be multiple inter-thread mailboxes than just one per thread. That way, client code and third-party library code don't interfere with each other.They will, even with different boxes.
Mar 22 2012
On Thursday, 22 March 2012 at 15:14:31 UTC, deadalnix wrote:They will, even with different boxes.Similarly succinct: How so?
Mar 22 2012
Le 22/03/2012 16:50, David Nadlinger a écrit :On Thursday, 22 March 2012 at 15:14:31 UTC, deadalnix wrote:They will because of synchronization. This cost will not be transparent. Not that it is a bad idea, but it depends what it meant by no interference.They will, even with different boxes.Similarly succinct: How so?
Mar 22 2012