Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Windows/MSVC support and on-flow ideas #16

Closed
jmckaskill opened this issue May 2, 2015 · 24 comments
Closed

Windows/MSVC support and on-flow ideas #16

jmckaskill opened this issue May 2, 2015 · 24 comments

Comments

@jmckaskill
Copy link

Hi, love the library.
I've been playing around with porting it to windows under msvc.
The go function was fairly straight forward although I had to resort to assembly in the end. MSVC doesn't support VLAs, and things crashed if I tried alloca. I think it tries to write to the intervening memory. It ends up looking something like the following:

if defined _M_IX86

define mill_rax eax

define mill_rsp esp

elif defined _M_X64

define mill_rax rax

define mill_rsp rsp

elif defined _M_ARM

define mill_rax r0

define mill_rsp r15

endif

define go(fn) \

do {\
    void *mill_sp = mill_go_prologue();\
    if(mill_sp) {\
        __asm {mov mill_rax, mill_rsp}\
        __asm {mov mill_rsp, mill_sp}\
        __asm {push mill_rax}\
        fn;\
        __asm {pop mill_rsp}\
        mill_go_epilogue();\
    }\
} while(0)

For the choose statement I've taken a different approach. The choose implementation at the moment uses goto labels which is very specific to GCC. The approach I've been playing with looks like the following:

switch (choose(IN, ch1, IN, ch2, END)) {
case 0:
    printf("coroutine 'a(%d)' has finished first!\n", ch1->value);
    break;
case 1:
    printf("coroutine 'b(%d)' has finished first!\n", ch2->value);
    break;
}

choose is then a var arg function which takes an enum (IN, OUT, END, DEFAULT) channel pairs. The value can be accessed as channel->value, which works because the channels pointers are typed (see next). This approach also seems to drastically simplify the choose logic as it doesn't have to track the labels (e.g. I've removed the clause structure and the channel just tracks the list of continuations).

I've also been playing with having the channels be typed. I've played with this concept before with a containers library. To use a channel you would first have a call to DECL_CHAN(name, type) somewhere in the header. You can then use chan(name) as the channel type. For example:

DECL_CHAN(int, int);

void worker(int count, const char *text, chan(int) ch) {
int i;
for(i = 0; i != count; ++i) {
printf("%s\n", text);
musleep(10000);
}
chs(ch, count);
chclose(ch);
}

int main() {

chan(int) ch1 = chmake(int, 0);
go(worker(4, "a", chdup(ch1)));
chan(int) ch2 = chmake(int, 0);
go(worker(2, "b", chdup(ch2)));

switch (choose(IN, ch1, IN, ch2, END)) {
case 0:
    printf("coroutine 'a(%d)' has finished first!\n", ch1->value);
    break;
case 1:
    printf("coroutine 'b(%d)' has finished first!\n", ch2->value);
    break;
}

chclose(ch2);
chclose(ch1);

return 0;

}

Thoughts?

@sustrik
Copy link
Owner

sustrik commented May 2, 2015

Nice work!

As for the go() part, why not create a pull request? Don't forget to state it's MIT licensed, please, so that I can merge it without licensing issues.

As for choose syntax and typed channels, I've deliberately tried to make the syntax as simple and golang-like as possible. After all, it's a convenience library, so the usability should be goal no.1. Having to specify the type in each command sucks, but it sucks less than having to declare a new type for each kind of channel you want to use.

As for the problem with goto labels, I can re-write the code so that it doesn't use them. It will still need COUNTER gcc-ism but that's supported by MSVC as well.

What do you think?

@jmckaskill
Copy link
Author

Interesting.

I kind of like the typed channels as it gives you a certain amount of type safety. In small examples I get your point that not having to type them is useful, but with anything larger than that things start to become a bit unwieldy making sure that you use the right types on the send and receive side.

Maybe I have a slightly different definition of usability than you. Typically I find magical constructs to be annoying and the closer you can make the API match the natural language the better. Otherwise you miss one bit and you get the craziest compile errors imaginable. My personal take would be to not try and match the go syntax correctly (and lets face it you can't), but rather to use the same concepts but in a more C like manner. That way people are less surprised by magic stuff and their effect on break, continue, compilation errors, etc. In this regard the go command isn't too magical, but the in, out, and end are supremely magical.

I'm curious: how would you remove the goto labels, but keep the current API? The reason I suggested the switch statement is that I couldn't think of a different way of moving between multiple code blocks where the setup and jump to was in the same line.

@sustrik
Copy link
Owner

sustrik commented May 2, 2015

Well, why not use libtask then? It's as C-idiomatic as it can possibly get and functionally it matches mill.

As for the goto labels, the idea is something like this:

int res = -1;
while(1) {
    if (res != -1) {
       goto label1;
   }
   mill_in(...);
   if(0) {
       label1:
       if(res == 1) {
           // code from clause1
          break;
       }
       goto label2;
   }
   mill_out(...);
   if(0) {
      label2:
      if(res == 2) {
          // code from clause2
          break;
      }
   }
   res = mill_wait(...);
}

@sustrik
Copy link
Owner

sustrik commented May 2, 2015

That being said, if you have an idea of how to allow for typed channels without having to invent a new name for each channel type, I'm all for it. Type-safeness <3

@jmckaskill
Copy link
Author

Thanks. I'll give the goto labels a try.
Moving the res = mill_wait up to the top would have the advantage of not needing the end macro.
Just had a look at libtask ... interesting, but the API is fairly clumsy.

@sustrik
Copy link
Owner

sustrik commented May 3, 2015

Ok, the code now doesn't use goto labels. Let me know whether it helped with your MSVC work.

@jmckaskill
Copy link
Author

Thanks I'll have a look at it next weekend. I'm out of office this week.
On May 3, 2015 1:35 PM, "sustrik" notifications@github.com wrote:

Ok, the code now doesn't use goto labels. Let me know whether it helped
with your MSVC work.


Reply to this email directly or view it on GitHub
#16 (comment).

@jaybny
Copy link

jaybny commented May 13, 2015

any chance we can get a CMakeLists.txt for windows like nanomsg? ty :)

https://github.com/nanomsg/nanomsg/blob/master/CMakeLists.txt

@sustrik
Copy link
Owner

sustrik commented May 13, 2015

Sure, why not, but it's only the tests that's built at the moment.

@sustrik
Copy link
Owner

sustrik commented Jul 12, 2015

CMake build is in place now.

@jaybny
Copy link

jaybny commented Jul 13, 2015

oops - i thought this was nanomsg.. my bad. ignore comments below. will test mill.. think it can replace some of my nanomsg "inproc" stuff, with mill

/*
yes.. ty!!! i've been using it. curious about the Statc vs Share lib, and the NN_EXPORTS and NN_EXPORT .. looks like TTimos branch has different strategy for this.

also btw: sometimes "tcp_shutdown" and "timeo" do fail... not sure exactly, could be only when compiled x86 and Static lib. will put an issue if/when i can recreate
*/

@sustrik
Copy link
Owner

sustrik commented Aug 11, 2015

Inactive for several months. Closing it. Reopen as needed.

@sustrik sustrik closed this as completed Aug 11, 2015
@adamenno
Copy link

Doesn't build on Windows

@sustrik
Copy link
Owner

sustrik commented Apr 25, 2016

Not supposed to.

@mewalig
Copy link

mewalig commented May 22, 2016

Any plans to port this to win? It would be HUGE. We don't dev on Win and don't like it, but all of our customers run it so we have to support it. We would be happy to help in the porting to the extent we have resources to do so. Is there a specific / known list of issues that if solved would enable porting (and more specifically, building with mingw64 tools)

@sustrik
Copy link
Owner

sustrik commented May 22, 2016

You can give it a try. IIRC there's no poll() on Windows. Take poll.inc and rewrite it using select(). Fix other compilation errors. See whether it works.

@mewalig
Copy link

mewalig commented May 22, 2016

will take a look thx. looking at a sigsetjmp port unless you know of one already

@sustrik
Copy link
Owner

sustrik commented May 22, 2016

Use setjmp() instead of sigsetjmp() and longjmp() instead of siglongjmp().

@mewalig
Copy link

mewalig commented May 22, 2016

ok thx. on to resource.h...

@sustrik
Copy link
Owner

sustrik commented May 22, 2016

You won't need it on windows. It's used only in epoll.inc and kqueue.inc and you are going to create your own select.inc anyway.

@mewalig
Copy link

mewalig commented May 23, 2016

moving to getrlimit. also, switching to your libdill, to try and solve what appears to be a smaller universe of problems first before the wider one of libmill. sound about right?

@sustrik
Copy link
Owner

sustrik commented May 23, 2016

getrlimit = resource.h. Same answer as above. As for libdill, as you wish, but notice there's no networking library there.

@Immortalin
Copy link

@mewalig how's progress?

@mewalig
Copy link

mewalig commented Jul 4, 2016

I got through the part that overlaps with libdill-- you can see what I've done in a diff file I attached to a comment to sustrik/libdill#18. have not finished fixing the remaining parts, including incompatibilities in dns/dns.c and other networking-related parts. If anyone would like to pitch in, lmk and I will open a fork or at least send a patch of what I have so far

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants