01:11:31 | * | q66 quit (Quit: Leaving) |
01:24:10 | * | BitPuffin quit (Read error: Connection reset by peer) |
02:05:47 | * | Associat0r quit (Read error: Connection reset by peer) |
02:06:57 | * | Associat0r joined #nimrod |
02:06:57 | * | Associat0r quit (Changing host) |
02:06:57 | * | Associat0r joined #nimrod |
05:06:06 | * | OrionPK quit (Read error: Connection reset by peer) |
05:16:04 | * | xilo quit (Ping timeout: 264 seconds) |
06:53:04 | zahary | hi dom96, sorry for not being around yesterday |
06:55:01 | zahary | can you summarise what kind of problems you are having with the async design? |
09:39:30 | * | BitPuffin joined #nimrod |
09:48:33 | * | alexandrus joined #nimrod |
09:50:06 | * | q66 joined #nimrod |
09:58:20 | * | alexandrus quit () |
10:19:16 | dom96 | hey zahary, you still around? |
10:29:56 | zahary | yep |
10:32:27 | dom96 | ok, well the problem is storing the return value in a Promise object |
10:33:02 | dom96 | I can't use a generic because I need to store a list of these promises |
10:33:47 | dom96 | I can use a PObject but then I can't store the original type as a separate field so I have to hack around to get it to work |
10:34:40 | * | troydm quit (Ping timeout: 264 seconds) |
10:38:33 | zahary | you need to do what people usually call type erasure in C++. you have a common promise base type that a "virtual" function handling the completion event implemented in the PRomise[T] instances |
10:38:33 | zahary | http://thbecker.net/free_software_utilities/type_erasure_for_cpp_iterators/start_page.html |
10:38:57 | zahary | if you send me some work in progress gist, I |
10:39:16 | zahary | .. I'll probably be able to help you get started |
10:39:39 | zahary | * with a virtual function * |
10:40:23 | dom96 | https://gist.github.com/dom96/65cecdb76deb08a455c9 |
10:40:35 | dom96 | That's my PPromise and my Dispatcher object |
10:40:52 | dom96 | the 'requests' field in the second object is only revelant |
10:40:55 | dom96 | *relevant |
10:41:04 | dom96 | and yes I should rename it to 'promises' |
10:42:21 | dom96 | The way this works is that I generate a P<procNameHere>RetObject type definition |
10:42:43 | dom96 | So when doing 'await sendAsync(sock, "blah")' |
10:43:10 | dom96 | It becomes PsendAsyncRetObject(promise.value).returnVal |
10:44:09 | dom96 | of course when you have a Promise object defined earlier there is no way to know the name of the proc |
10:45:45 | zahary | the dispatcher here represents the event loop? |
10:45:50 | dom96 | yes |
10:46:03 | zahary | and what is pdelegate is? |
10:46:25 | dom96 | that doesn't matter |
10:46:40 | dom96 | That's how the old async is implemented |
10:48:49 | BitPuffin | dom96: how's async going? |
10:49:19 | dom96 | ok-ish. Having some problems with return values though. |
10:51:04 | BitPuffin | what kind of problems? |
10:51:17 | dom96 | read what I just wrote :P |
10:52:58 | zahary | ok, the first step would be to write some regular procs based on the async sockets api that return promises. shall we use my "download" as an example? |
10:53:16 | dom96 | I already have |
10:53:38 | dom96 | I already changed the macro to transform it properly. |
10:53:50 | zahary | is it online too? |
10:53:55 | dom96 | no |
10:57:33 | BitPuffin | dom96: you mean above? |
10:57:38 | dom96 | yes |
10:59:07 | zahary | can you upload the download proc example? your TPromise definition suspiciously lacks notification mechanisms for when it's resolved and rejected and I'd like to see how the code works |
11:00:11 | dom96 | well I haven't gotten as far as a download proc |
11:01:11 | zahary | you probably have something like async connect, async read, etc? any of them would do |
11:02:33 | dom96 | https://gist.github.com/dom96/0c73a80b0dba2453956a |
11:02:46 | dom96 | That's accept |
11:02:52 | dom96 | after macro expansion and before |
11:14:29 | zahary | https://gist.github.com/dom96/0c73a80b0dba2453956a |
11:15:04 | zahary | I left you some comments. my example is not particularly good, because accept is not one-off operation |
11:15:59 | zahary | there are two general approaches to async network APIs - the most widely used one is when each operation has it's own completion callback |
11:16:29 | zahary | socket.async_read(number_of_bytes, completion_handler_proc) |
11:16:46 | dom96 | but then that's just a callback API? |
11:17:38 | dom96 | Why are iterators a wrong idea? |
11:17:50 | zahary | this is how boost.asio (C++), node.js (libuv), etc are written. this is very easily married to promises, because the callback just resolves the promise |
11:18:18 | dom96 | You yield a promise and the dispatcher resurrects your iterator once that promise has been completed |
11:18:53 | zahary | the other kind of APIs (like python's async socket and nimrod's) will resolve the promise in similar way, but the ownership of the handleXX fields in the socket object is a bit more messy |
11:20:05 | zahary | yes, the benefits of the promises come with the iterator style procs - but these procs need a basic API to work with written in the classic style - that's what I meant |
11:20:51 | dom96 | well I don't get how this solves my problem |
11:21:19 | zahary | well, what is the next problem? |
11:21:48 | dom96 | that's really the only problem currently |
11:23:49 | zahary | so what is it? how to advance the iterator? |
11:24:16 | dom96 | Didn't I just describe the problem? |
11:24:21 | dom96 | the return values |
11:24:27 | * | BitPuffin quit (Ping timeout: 260 seconds) |
11:25:05 | zahary | notice how in my example, I'm supplying the return value when I resolve the promise |
11:25:49 | zahary | since the promise is strongly typed, the return value can be stored as a field or just immediately dispatched to any handlers subscribed to the promise |
11:26:36 | zahary | also, notice how callers of asyncAccept are working with TPromise[Connection], so the simple await templete will read the proper TConnection value |
11:28:03 | dom96 | well you still need iterators don't you? |
11:28:52 | zahary | as I said, iterators is what the user of library write most of the time (that is .async. procs) |
11:29:06 | * | EXetoC joined #nimrod |
11:29:14 | zahary | for example in their code there will be |
11:29:15 | zahary | var connection = await acceptAsync(socket) |
11:29:21 | dom96 | yes, and won't we arrive at exactly the same problem? |
11:29:47 | dom96 | the iterators will yield a promise right? |
11:29:57 | zahary | yes, base promise type |
11:30:10 | dom96 | base promise type? |
11:30:34 | zahary | you need to do what people usually call type erasure in C++. you have a common promise base type that a "virtual" function handling the completion event implemented in the PRomise[T] instances |
11:30:34 | zahary | http://thbecker.net/free_software_utilities/type_erasure_for_cpp_iterators/start_page.html |
11:31:18 | dom96 | yes, I have no idea what that means or how to do that in Nimrod |
11:36:21 | zahary | https://gist.github.com/dom96/0c73a80b0dba2453956a |
11:47:26 | zahary | did the code compile in your head? |
11:48:21 | dom96 | no, I don't really get it |
11:48:43 | zahary | any part in particular? |
11:49:18 | dom96 | Any reason why we can't go with my solution? |
11:49:36 | dom96 | is it impossible to fix the 'return value problem' with the way I implemented this? |
11:51:24 | zahary | well, what is your solution? the way I see it, the missing part of you current approach is the step where you resolve the promises (resolving means that the async operation completes) |
11:53:38 | dom96 | in my iterator, when I yield the 'readPromise' I am asking the dispatcher to bring back execution into the iterator when the socket becomes readable. |
11:54:00 | dom96 | So when line 16 begins execution, `socket` is readable. |
11:54:52 | zahary | aha, this is encoded in the reqKind field |
11:55:01 | dom96 | yes |
11:55:17 | dom96 | There are two possible 'requests', either a read or a write. |
11:58:14 | zahary | well, the promises are really a task agnostic mechanism. they are not just for socket operations and the user can compose them or create his set of "async tasks" |
11:58:49 | zahary | so it's not a good idea to tie them to the sockets module and encode the type of the operation as a closed enum |
11:59:27 | dom96 | hrm, yes. |
12:01:00 | zahary | which parts of my example code seem complicated btw? maybe I can explain them some more |
12:01:23 | dom96 | I think I understand it a bit better now. Hrm. |
12:02:37 | dom96 | still not 100% sure how the event loop will work with the iterators. |
12:02:44 | dom96 | What will the iterators do exactly? |
12:02:51 | dom96 | yield a PromiseBase? |
12:04:03 | zahary | yes |
12:04:42 | zahary | when you call an async proc for the first time in non-await context - it starts the iterator with stepIterator() |
12:05:26 | dom96 | but how will that work? |
12:05:39 | dom96 | say I have: var a = accept(sock) |
12:05:48 | dom96 | will the macro transform it somehow? |
12:06:27 | zahary | what is accept here? async proc? |
12:06:39 | dom96 | yes |
12:06:44 | zahary | then a is a promise |
12:07:04 | zahary | the code returns immediately and execution continues |
12:07:55 | dom96 | what will 'accept' do then? |
12:08:16 | dom96 | where will the iterator be stored? |
12:08:29 | dom96 | (the state of the iterator) |
12:08:40 | zahary | you can scratch my previous line about calling asyncProc for the first time |
12:09:06 | zahary | the iterator is actually advanced in dispatcher.run() |
12:09:35 | dom96 | how will the dispatcher know about the iterator? |
12:11:09 | zahary | the stepIterator function actually represents the yield statement in the iterator |
12:12:39 | * | dom96 is really confused |
12:12:57 | zahary | so the dispatcher only knows about sockets (and other events implemented in system libraries such as libuv); the socket resolves the promise; the onComplete handler of the promise advances the iterator |
12:14:15 | dom96 | well I know you gave me an example of acceptAsync |
12:14:32 | dom96 | but I don't get it |
12:14:45 | dom96 | well first of all, why are you calling .listen? |
12:14:53 | zahary | I updates my example to call the former stepIterator proc "wrapYield" |
12:14:53 | zahary | https://gist.github.com/dom96/0c73a80b0dba2453956a |
12:15:43 | dom96 | where is the iterator stored then? |
12:15:47 | zahary | yes, my example for accept is a bit lame; it would be much easier to understand with some other operation like asyncRead |
12:16:06 | dom96 | show me asyncread then |
12:16:17 | zahary | I request asyncRead; the async socket fire some callback when the operation is complete - this callback resolves the promise |
12:17:48 | dom96 | Ok I understand that. |
12:18:00 | zahary | the iterator is created at the entry of the .async. proc |
12:18:03 | dom96 | So say I have an async proc of my own which wants to read from a socket |
12:18:29 | dom96 | I write: var data = readAsync(sock) |
12:18:56 | dom96 | well, I suppose 'dataPromise' is a more appropriate name for that var |
12:18:57 | dom96 | but w/e |
12:18:59 | zahary | stored as a local variable and referenced from the onComplete callback in wrapYield |
12:19:11 | zahary | thus, it also ends up in a closure |
12:19:19 | dom96 | hrm |
12:20:04 | dom96 | not sure I get that |
12:20:12 | dom96 | lets just go with my example, k? |
12:20:41 | dom96 | proc myRead(sock: PAsyncSocket) {.async.} = |
12:20:48 | * | BitPuffin joined #nimrod |
12:20:50 | dom96 | var dataPromise = readAsync(sock) |
12:21:14 | dom96 | let data = await dataPromise |
12:21:30 | dom96 | How does that look after macro expansion? |
12:36:22 | zahary | hmm, it's a bit more complicated indeed |
12:36:23 | zahary | https://gist.github.com/dom96/0c73a80b0dba2453956a |
12:36:48 | zahary | you also need a special promise for the whole iterator |
12:41:45 | * | BitPuffin quit (Read error: Operation timed out) |
12:43:06 | dom96 | you're calling onComplete on an iter? |
12:43:49 | zahary | well, it should be an object wrapping the iterator and the promise we created |
12:43:57 | zahary | … at the start of the async proc |
12:44:25 | zahary | is it possible to instantiate an iterator without starting it now? |
12:44:54 | dom96 | you need to keep the state of the iterator and the arg you pass to it somewhere |
12:45:02 | dom96 | the arg must be the same on each call I think |
12:45:25 | dom96 | well I dunno |
12:45:28 | dom96 | This is really confusing |
12:45:51 | dom96 | and i've rewritten it once already |
12:50:29 | zahary | alright, I was able to simplify it significantly |
12:50:59 | zahary | the iterator should get the .async. result promise and returns in the iterator should resolve that promise |
12:51:07 | zahary | https://gist.github.com/dom96/0c73a80b0dba2453956a |
12:53:46 | dom96 | wait why is onCompleted a seq? |
12:55:15 | zahary | it should be a signal (aka event) |
12:55:27 | zahary | to allow for multiple subscribers |
12:56:54 | zahary | this is quite nice feature for adding additional cross cutting logic to the async operations: for example, every async network operation, should change the mouse cursor to hourglass, etc |
12:59:10 | zahary | http://msdn.microsoft.com/en-us/library/aa645739(v=vs.71).aspx |
12:59:10 | zahary | http://en.wikipedia.org/wiki/Signals_and_slots |
13:05:29 | dom96 | argh |
13:05:59 | dom96 | i have to leave for a while. |
13:06:22 | dom96 | but yeah, i'm still not entirely sure how this is meant to all come together. |
13:06:27 | dom96 | Perhaps you should just implement it zahary |
13:06:38 | zahary | you can start without signals; just make onComplete a regular proc pointer for a single subscriber |
13:07:18 | zahary | but otherwise, go ahead and read my latest example code- it's getting quite simple and I think the code is complete now |
13:07:39 | dom96 | right. bbl |
13:45:22 | dom96 | back |
14:28:08 | * | xilo joined #nimrod |
14:44:45 | * | BitPuffin joined #nimrod |
14:48:53 | * | OrionPK joined #nimrod |
15:06:42 | * | Mat2 joined #nimrod |
15:06:44 | Mat2 | hello |
15:10:07 | OrionPK | yo |
15:10:18 | Mat2 | ho OnionPK |
15:13:20 | dom96 | hello |
15:13:33 | Mat2 | hi dom96 |
15:13:42 | dom96 | hi Mat2 |
15:19:22 | OrionPK | funny |
15:19:50 | OrionPK | you call me Onion, even though it's Orion right now ;P |
15:20:19 | Mat2 | *g*, sorry - typo |
15:20:48 | OrionPK | lol, no dont worry about it, people call me onion all the time in another community |
15:21:04 | OrionPK | thats why i think its funny, onion is basically my nickname |
16:02:33 | BitPuffin | can nimrod write any function call of two parameters inline? |
16:02:52 | BitPuffin | like a `toThePowerOf` b |
16:03:06 | BitPuffin | that's just haskell style |
16:03:16 | BitPuffin | I was just wondering if nimrod has anything equivalent |
16:05:00 | dom96 | I think someone asked this before. |
16:05:05 | dom96 | in fact was it not you? :P |
16:38:19 | Araq | BitPuffin: no, use a.toThePowerOf(b) instead |
16:38:25 | Araq | or a real operator |
16:38:31 | BitPuffin | dom96: perhaps :P |
16:38:45 | BitPuffin | Araq: that's what I'm currently doing, real operator? |
16:39:13 | Araq | a ^ b |
16:39:22 | BitPuffin | oh |
16:39:28 | BitPuffin | I was thinking real, the type |
16:39:29 | BitPuffin | lol |
16:39:50 | EXetoC | type class? :> |
16:53:16 | * | BitPuffin quit (Ping timeout: 264 seconds) |
17:06:52 | * | shevy joined #nimrod |
17:07:36 | dom96 | hey shevy |
17:07:44 | shevy | heya |
17:07:54 | Mat2 | hi shevy |
17:07:57 | dom96 | where have ya been |
17:08:42 | shevy | hmm, struggled with computer related problems for a while, also had no electricity in my flat for like 10 days and so on and so forth |
17:08:58 | shevy | the only proud thing I did was that I finally managed to switch from ruby 1.8.x to ruby 1.9.x :P |
17:09:38 | shevy | I am on gtk3 now too though |
17:10:09 | Mat2 | what are your experiences with GTK3 ? |
17:10:46 | shevy | I am not sure yet, I am just slowly getting into things with it again with ruby-gtk ... but it looks nicer than gtk2 |
17:13:09 | shevy | has aptana gotten better? |
17:13:11 | * | OrionPKM joined #nimrod |
17:13:15 | dom96 | gtk3 apps still look shit on my desktop. |
17:14:44 | Mat2 | I'm curious because some open-source projects which used GTK2 before (beside Gnome of course) seem switching to Qt |
17:16:08 | shevy | yeah |
17:16:23 | shevy | the gtk guys need to work harder |
17:17:50 | Mat2 | I think there need some seperation from the Gnome project - then more developers will probably interested in development |
17:18:22 | shevy | does not qt require one to have a project in C++? |
17:18:42 | Mat2 | yes |
17:49:48 | * | OrionPKM quit (Ping timeout: 276 seconds) |
17:51:40 | * | OrionPKM joined #nimrod |
18:04:22 | EXetoC | dom96: with the default theme I assume |
18:05:17 | dom96 | Adwaita-X-dark |
18:07:59 | EXetoC | does it look different elsewhere? |
18:09:18 | EXetoC | or is it ugly because of gtk3 in general? |
18:12:12 | * | OrionPKM quit (Remote host closed the connection) |
18:12:51 | dom96 | maybe the theme just doesn't support it |
18:13:28 | dom96 | what is the name of the default theme? |
18:14:29 | EXetoC | I don't know |
18:15:25 | EXetoC | wanna try some game today? |
18:16:01 | EXetoC | btw, do you know what kind of game you want to make? |
18:16:23 | dom96 | I'm working on a Nimrod benchmark currently so maybe a bit later. |
18:17:37 | dom96 | did I say I want to make a game? |
18:19:23 | EXetoC | you were thinking about it at least |
18:19:43 | dom96 | well I wanted to try creating a minecraft clone to learn some stuff about opengl |
18:20:58 | EXetoC | ok |
18:21:10 | dom96 | why do you ask? |
18:22:25 | EXetoC | just out of curiosity |
18:39:25 | * | jbe_ joined #nimrod |
18:39:51 | jbe_ | hello everyone |
18:40:02 | dom96 | hi jbe_ |
18:40:10 | Mat2 | hi jbe |
18:40:56 | jbe_ | i just noticed the generics sample code from the manual won't compile.. is it a bug? |
18:43:23 | * | Associat0r quit (Quit: Associat0r) |
18:44:33 | dom96 | hrm, perhaps. |
18:44:34 | Araq | jbe_: which example? |
18:44:46 | jbe_ | lets see.. |
18:44:52 | dom96 | The binary tree one? |
18:45:06 | jbe_ | yep! |
18:45:23 | dom96 | Looks like generics in iterators are broken. |
18:45:37 | Araq | # inorder traversal of a binary tree |
18:45:39 | Araq | # recursive iterators are not yet implemented, so this does not work in |
18:45:40 | Araq | # the current compiler! |
18:45:43 | Araq | says the code |
18:45:53 | dom96 | hah |
18:45:57 | jbe_ | ah whoops sorry |
18:45:59 | * | dom96 didn't even read the comments |
18:46:30 | dom96 | Might be a good idea to add a "Note" underneath that example. |
18:46:35 | Araq | well |
18:46:46 | Araq | we should implement an 'inorder' that does work |
18:47:01 | Araq | as iterators won't be getting recursion any time soon |
18:47:07 | Mat2 | hi Araq, what's the state of your VM by the way ? |
18:47:31 | Araq | Mat2: it runs some quite complex code |
18:48:08 | Araq | I'm now integrating it so that the it can replace the old VM |
18:51:16 | Mat2 | well, I will take a look after integrating mine in retro (curious about some benchmark results of both) |
18:52:22 | Araq | well I haven't even started on .interpreterLoop and the 'c.code' expression needs to be hoisted out of the loop |
18:53:09 | Araq | also my design is quite constrained by the AST operations that need to be supported efficiently |
18:53:28 | Araq | (it is after all used for macro evaluation in the first place) |
18:56:26 | Mat2 | ok, that's then the first example for misusing Nimrod vm-engines for testing :D |
18:57:04 | Mat2 | ^purposes |
18:57:51 | * | BitPuffin joined #nimrod |
19:09:58 | * | BitPuffin quit (Read error: Connection reset by peer) |
20:46:40 | Araq | jbe_: are you the guy who ported quite some benchmarks to nimrod? |
20:57:29 | dom96 | that's jmb, could still be the same person though heh |
20:59:05 | Araq | oh ... lol |
20:59:34 | Araq | well the names are similar :P |
21:02:04 | jbe_ | Araq & dom96: nope |
21:02:38 | jbe_ | and jdp is here too. confusing.. |
21:02:52 | dom96 | hah, true. |
21:02:57 | * | dom96 didn't even notice |
21:24:59 | * | Associat0r joined #nimrod |
21:24:59 | * | Associat0r quit (Changing host) |
21:25:00 | * | Associat0r joined #nimrod |
21:59:47 | * | BitPuffin joined #nimrod |
22:00:45 | * | jbe_ quit (Quit: Leaving) |
22:01:25 | Mat2 | ciao |
22:01:34 | * | Mat2 quit (Quit: Verlassend) |
22:04:40 | * | BitPuffin quit (Ping timeout: 264 seconds) |
22:08:23 | * | Associ8or joined #nimrod |
22:08:23 | * | Associ8or quit (Changing host) |
22:08:24 | * | Associ8or joined #nimrod |
22:10:14 | * | Associat0r quit (Ping timeout: 240 seconds) |
22:29:15 | * | Associ8or quit (Quit: Associ8or) |
22:30:29 | * | Associat0r joined #nimrod |
22:30:29 | * | Associat0r quit (Changing host) |
22:30:29 | * | Associat0r joined #nimrod |
22:30:38 | * | Associat0r quit (Client Quit) |
22:40:51 | * | Trix[a]r_za is now known as Trixar_za |
22:41:23 | * | Associat0r joined #nimrod |
22:41:23 | * | Associat0r quit (Changing host) |
22:41:23 | * | Associat0r joined #nimrod |
23:03:28 | * | EXetoC quit (Ping timeout: 264 seconds) |