Any suggestion for a robust C coroutine library which can be used with LuaJIT ?

classic Classic list List threaded Threaded
19 messages Options
Reply | Threaded
Open this post in threaded view
|

Any suggestion for a robust C coroutine library which can be used with LuaJIT ?

Johnson Lin
Hi all,

Recently I stumbled upon this post on lua-l again:
http://permalink.gmane.org/gmane.comp.lang.lua.general/75139

And all of a sudden (maybe I played SpaceChem too much recently) I
found out that how I might be able to apply this to our C++ codebase.
Of course the LuaJIT FFI callbacks worked, but I just want to try if I
can implement what Mike suggested there back then.

However, the biggest problem I bumped into right now is there seems to
have no robust C coroutine implementation. I need asymmetric coroutine
support and value passing (just like the Lua one), and can be compiled
across 3 major platforms (windows, osx and linux).

Boost.Coroutine: http://www.crystalclearsoftware.com/soc/coroutine/index.html
supports asymmetric coroutine and value passing, but it's unfinished
and dunno if it works on OSX, and heavily dependent on boost.

libconcurrency: http://code.google.com/p/libconcurrency/
seemed like have asymmetric support. value passing is ok; However
there's unresolved issue about compiling on OSX.

I hope this is not too off-topic on the list. Can someone help me out
a little bit?
Thanks in advance.

Sincerely,
Johnson Lin

Reply | Threaded
Open this post in threaded view
|

Re: Any suggestion for a robust C coroutine library which can be used with LuaJIT ?

Petite Abeille

On Jan 5, 2012, at 11:30 AM, Johnson Lin wrote:

>  I need asymmetric coroutine
> support and value passing (just like the Lua one), and can be compiled
> across 3 major platforms (windows, osx and linux).

Not sure how it fits your requirements, but have you looked at Steve Dekorte's libcoroutine?

http://www.dekorte.com/projects/opensource/libCoroutine/
https://github.com/stevedekorte/coroutine


Reply | Threaded
Open this post in threaded view
|

Re: Any suggestion for a robust C coroutine library which can be used with LuaJIT ?

Johnson Lin
On Thu, Jan 5, 2012 at 6:41 PM, Petite Abeille <[hidden email]> wrote:

>
> On Jan 5, 2012, at 11:30 AM, Johnson Lin wrote:
>
>>  I need asymmetric coroutine
>> support and value passing (just like the Lua one), and can be compiled
>> across 3 major platforms (windows, osx and linux).
>
> Not sure how it fits your requirements, but have you looked at Steve Dekorte's libcoroutine?
>
> http://www.dekorte.com/projects/opensource/libCoroutine/
> https://github.com/stevedekorte/coroutine
>
>

Hello, thanks for the fast reply. And yes I've seen this one, however
it can only provide a context (which acts as value passing) when a new
coroutine starts. I may be ignorant here, but I don't see how to pass
a value when switching (yielding/resuming).

Reply | Threaded
Open this post in threaded view
|

Re: Any suggestion for a robust C coroutine library which can be used with LuaJIT ?

David Given
In reply to this post by Johnson Lin
Johnson Lin wrote:
[...]
> However, the biggest problem I bumped into right now is there seems to
> have no robust C coroutine implementation. I need asymmetric coroutine
> support and value passing (just like the Lua one), and can be compiled
> across 3 major platforms (windows, osx and linux).

A while back I wrote a coroutine library using
setcontext()/getcontext(), for a project I was doing in C++ (which, it
turns out, would have been much easier in Lua, but that's beside the point).

The lesson I learned from this is: don't use setcontext()/getcontext().
Some Linux libc versions do not allow you to use pthreads functions from
stacks that were not allocated through pthreads. (Because they use magic
numbers at the top of the stack to identify which thread is running.)
This means that if you call a function in any library which has been
compiled with pthreads support, like malloc(), really bad things happen.

I eventually ended up rewriting everything to use multiple pthreads and
a big global lock to force one thread to run at a time. As what I was
using the coroutines for was to implement cooperatively scheduled
threads, this was no big problem, but this technique probably isn't
suitable for other projects.

--
┌─── dg@cowlark.com ───── http://www.cowlark.com ─────
│ "I have always wished for my computer to be as easy to use as my
│ telephone; my wish has come true because I can no longer figure out
│ how to use my telephone." --- Bjarne Stroustrup


signature.asc (270 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Any suggestion for a robust C coroutine library which can be used with LuaJIT ?

Szymon Gatner
In reply to this post by Johnson Lin
2012/1/5 Johnson Lin <[hidden email]>:

>
> Boost.Coroutine: http://www.crystalclearsoftware.com/soc/coroutine/index.html
> supports asymmetric coroutine and value passing, but it's unfinished
> and dunno if it works on OSX, and heavily dependent on boost.
>

I was looking for good coroutine library for C++ myself after learning about
them with Lua. Boost.Coroutine status is unclear to me but its author
seems to be now involved in provisionally accepted Boost.Context:

http://ok73.ok.funpic.de/boost/libs/context/doc/html/

It looks really good and it is now under additional minireview meaning
all issues from original review have been addressed.

Hope this helps.



--
Szymon Gatner
The Lordz Games Studio
www.thelordzgamesstudio.com

Reply | Threaded
Open this post in threaded view
|

Re: Any suggestion for a robust C coroutine library which can be used with LuaJIT ?

Alex Bradbury
In reply to this post by David Given
On 5 January 2012 11:39, David Given <[hidden email]> wrote:
> The lesson I learned from this is: don't use setcontext()/getcontext().

Another reason is they're not currently implemented in ARM glibc
(though a first attempt at patches to implement them is available here
https://bugs.launchpad.net/qemu-linaro/+bug/883136).

Alex

Reply | Threaded
Open this post in threaded view
|

Re: Any suggestion for a robust C coroutine library which can be used with LuaJIT ?

Johnson Lin
In reply to this post by Szymon Gatner
On Thu, Jan 5, 2012 at 7:41 PM, Szymon Gatner <[hidden email]> wrote:

> I was looking for good coroutine library for C++ myself after learning about
> them with Lua. Boost.Coroutine status is unclear to me but its author
> seems to be now involved in provisionally accepted Boost.Context:
>
> http://ok73.ok.funpic.de/boost/libs/context/doc/html/
>
> It looks really good and it is now under additional minireview meaning
> all issues from original review have been addressed.
>
> Hope this helps.
>

Thank you all! I did not know about Boost.Context. Apart from being
still dependent on Boost, this one looks promising, and it already
provides some examples that work almost just like Lua's powerful
coroutine. It's own fcontext seemed to be a lot faster than ucontext
as well....

On a second glimpse at libCoroutine, I think adding a wrapper around
the simple C API and encapsulate some kind of buffer for value passing
when switching might be doable.

Any other suggestions? :)

Sincerely,
Johnson Lin

Reply | Threaded
Open this post in threaded view
|

Re: Any suggestion for a robust C coroutine library which can be used with LuaJIT ?

Javier Guerra Giraldez
On Thu, Jan 5, 2012 at 8:31 AM, Johnson Lin <[hidden email]> wrote:
> On a second glimpse at libCoroutine, I think adding a wrapper around
> the simple C API and encapsulate some kind of buffer for value passing
> when switching might be doable.

i haven't seen libCoroutine; but since coroutines are all about
nonconcurrency, it sounds reasonably easy to just use a static pointer
or struct to hold any parameters.  no need to allocate buffers, since
there won't be more than a single yield()/resume() happening at a
time.

--
Javier

Reply | Threaded
Open this post in threaded view
|

Re: Any suggestion for a robust C coroutine library which can be used with LuaJIT ?

Johnson Lin
On Thu, Jan 5, 2012 at 10:09 PM, Javier Guerra Giraldez
<[hidden email]> wrote:

> On Thu, Jan 5, 2012 at 8:31 AM, Johnson Lin <[hidden email]> wrote:
>> On a second glimpse at libCoroutine, I think adding a wrapper around
>> the simple C API and encapsulate some kind of buffer for value passing
>> when switching might be doable.
>
> i haven't seen libCoroutine; but since coroutines are all about
> nonconcurrency, it sounds reasonably easy to just use a static pointer
> or struct to hold any parameters.  no need to allocate buffers, since
> there won't be more than a single yield()/resume() happening at a
> time.
>
> --
> Javier
>

Haven't finished my crude benchmark yet, but it seemed that
Boost.Context currently don't work with mingw-gcc. There must be come
work around but the codebase is really too complex... I can hardly
read inside boost headers. Maybe something about bjam as well.

However, one thing is quite definitive. Boost.Context's static-release
build is about 500KB on my machine, while libcoroutine is less than
10KB (If I didn't get anything wrong...), libcoroutine depends on a
basekit from the same author, but it turns out that only 3 files from
that library are needed. So I just simply copied them into
libcoroutine.

I've tried this one as well:
http://www.akira.ruc.dk/~keld/research/COROUTINE/

but after fixing some code in it to work with gcc 4.5, I still can't
quite get the idea of its API. Maybe libcoroutine is my best bet for
now.

best regards,
Johnson Lin

Reply | Threaded
Open this post in threaded view
|

Re: Any suggestion for a robust C coroutine library which can be used with LuaJIT ?

steve donovan
On Fri, Jan 6, 2012 at 12:56 PM, Johnson Lin <[hidden email]> wrote:
> However, one thing is quite definitive. Boost.Context's static-release
> build is about 500KB on my machine, while libcoroutine is less than
> 10KB (If I didn't get anything wrong...),

Wow, another example of 'things which are larger than Lua', to
continue a recently popular meme.

(Another good example of that would be PCRE)

Better to stick to C here, since you have to be close to the machine
here anyway!

steve d.  (who still has a sore head from trying to write a C++
interpreter that could process the STL)

Reply | Threaded
Open this post in threaded view
|

Re: Any suggestion for a robust C coroutine library which can be used with LuaJIT ?

Johnson Lin
On Fri, Jan 6, 2012 at 7:01 PM, steve donovan <[hidden email]> wrote:

> Wow, another example of 'things which are larger than Lua', to
> continue a recently popular meme.
>
> (Another good example of that would be PCRE)
>
> Better to stick to C here, since you have to be close to the machine
> here anyway!
>
> steve d.  (who still has a sore head from trying to write a C++
> interpreter that could process the STL)
>

You must forgive me for not quite following that meme.. :p

About close to the machine, it turns out that it's not very
distinctive between Boost.Context and libcoroutine... Currently
Boost.Context is all running on its fcontext implementation, the fiber
implementation on windows isn't even included for now, and
libcoroutine is running fiber on windows.

My crude benchmark is just like this: https://gist.github.com/1571187
I made the codes based on different C/C++ coroutine library do
something like lua code in that gist do. Boost bloats binary, but
speed-wise they are pretty much on par with one another. BTW, although
LuaJIT's coroutine.yield and resume are still NYI FastFunc, I get
about the same performance when the above lua code is run by LuaJIT.
Which means both C coroutine libraries must be really slow?

I'll try to benchmark these 2 scenario next:
1. A tight loop in C keeps calling back to Lua through LuaJIT FFI callback.
2. LuaJIT FFI calls to C in a tight loop, and yield there (C
coroutine), and the main coroutine (in C) will keep resuming to that
yield point.

Johnson

Reply | Threaded
Open this post in threaded view
|

Re: Any suggestion for a robust C coroutine library which can be used with LuaJIT ?

Douglas Creager-2
In reply to this post by Johnson Lin
> but after fixing some code in it to work with gcc 4.5, I still can't
> quite get the idea of its API. Maybe libcoroutine is my best bet for
> now.

We're using PCL [1] in a current project, and it's worked great on both
Linux and OS X.  Haven't tested on Windows, but their website claims
that it works there, too.  PCL also doesn't support passing values
directly in its yield function (co_call), but like others have
mentioned, we just throw the value into a struct that both coroutines
have access to.

[1] http://www.xmailserver.org/libpcl.html

–doug


Reply | Threaded
Open this post in threaded view
|

Re: Any suggestion for a robust C coroutine library which can be used with LuaJIT ?

Johnson Lin
On Sat, Jan 7, 2012 at 1:10 AM, Douglas Creager <[hidden email]> wrote:

>
> We're using PCL [1] in a current project, and it's worked great on both
> Linux and OS X.  Haven't tested on Windows, but their website claims that it
> works there, too.  PCL also doesn't support passing values directly in its
> yield function (co_call), but like others have mentioned, we just throw the
> value into a struct that both coroutines have access to.
>
> [1] http://www.xmailserver.org/libpcl.html
>
> –doug
>
>

Hi all, again!

Thank you douglas for the PCL link. I think it's pretty much the same
implmentation as libcoroutine, but seemed to be harder to build on
windows. :P I can be wrong since I didn't put much effort into making
PCL work on windows after a few compile-error.

Anyway, here's the crude benchmark I made:

https://github.com/arch-jslin/mysandbox/tree/master/cpp/fficb_vs_coro

the main.cpp consists of 4 similar kinds of callbacks and their
benchmarking loop. I simply dumped libcoroutine's source into this
repository (with modification: taskimpl.h doesn't work on windows so I
added preprocesser directives to those; and changed some file from *.c
to *.cpp.)

The benchmark may be inaccurate since these 4 methods aren't doing
exactly the same thing, they do achieve more or less the same
functionality however:

1. call a C++ callback (as a base case, since I wanted to move these
callbacks to lua)
2. register a lua callback to C through LuaJIT FFI.
3. call a C++ callback which contain a call to a lua function.
4. notify lua by switching C coroutine.

The 4th method should be the case which Mike Pall mentioned before he
implemented LuaJIT FFI callback.

And the results:

No doubt 1st method is faster than all 3 other methods by an order of
magitude. LuaJIT FFI callback is the slowest one in this test, but 3rd
method is no better, as they are about the same (difference less than
10%). Pretty much as expected so far.

Lastly, the 4th method is faster than 2nd and 3rd ones, but not THAT
fast (about 40% faster). I've checked with code used by "luajit -jv"
that tight loop in lua is compiled, so the threshold still lies in the
context switching mechanism implemented by libcoroutine, which on
windows uses Fibers.

When using the 4th method you have to be careful that the yielding
call in Lua (which would be triggered by Coro_startCoro_ call in my
code) can't block too long, or LuaJIT will no doubtly blacklist that
loop, and that is an order of magitude slower.

These code should be easily compiled, provided you have a C++ compiler
which can handle tr1 functions and LuaJIT installed.

best regards,
Johnson Lin

Reply | Threaded
Open this post in threaded view
|

Re: Any suggestion for a robust C coroutine library which can be used with LuaJIT ?

Tony Finch
In reply to this post by David Given
David Given <[hidden email]> wrote:

>
> A while back I wrote a coroutine library using
> setcontext()/getcontext(), for a project I was doing in C++ (which, it
> turns out, would have been much easier in Lua, but that's beside the point).
>
> The lesson I learned from this is: don't use setcontext()/getcontext().
> Some Linux libc versions do not allow you to use pthreads functions from
> stacks that were not allocated through pthreads. (Because they use magic
> numbers at the top of the stack to identify which thread is running.)
> This means that if you call a function in any library which has been
> compiled with pthreads support, like malloc(), really bad things happen.

That's pretty sad.

GNU Pth is a co-operative threading library designed to look a bit like
POSIX threads. I don't know what primitives it uses.
http://www.gnu.org/software/pth/

If you know which direction your stack grows in, you can implement
coroutines with setjmp+longjmp (to switch contexts) and either alloca() or
C99 dynamic arrays (to perform arithmetic on the stack pointer when
creating a new context). This is a fun low-level hack rather than
something you should use in real life...

http://fanf.livejournal.com/105413.html
http://fanf.livejournal.com/105655.html

Tony.
--
f.anthony.n.finch  <[hidden email]>  http://dotat.at/
Sole: Variable 3 or 4, becoming southeasterly 4 or 5 later in west. Moderate.
Showers. Moderate or good.

Reply | Threaded
Open this post in threaded view
|

Re: Any suggestion for a robust C coroutine library which can be used with LuaJIT ?

Peter Kuemmel
In reply to this post by Johnson Lin
If linking against Qt isn't a show stopper:

    https://qt.gitorious.org/qt-labs/coroutine

I assume it compiles at least under common desktop operating systems.

But there was a problem when used in combination with WebKit:

    https://bugreports.qt.nokia.com/browse/QTSIM-22

--
Peter
--
Empfehlen Sie GMX DSL Ihren Freunden und Bekannten und wir
belohnen Sie mit bis zu 50,- Euro! https://freundschaftswerbung.gmx.de

Reply | Threaded
Open this post in threaded view
|

Re: Any suggestion for a robust C coroutine library which can be used with LuaJIT ?

Joseph Stewart
Maybe this is too much but I've enjoyed messing with "libtask":


I've used this in conjunction with lua for some non-serious tinkering. You'd get channels and some networking code with this too. I believe Zed Shaw uses pieces of libtask (not my code) in his Mongrel2 server.

-joe

On Thu, Jan 12, 2012 at 1:37 PM, Peter Kuemmel <[hidden email]> wrote:
If linking against Qt isn't a show stopper:

   https://qt.gitorious.org/qt-labs/coroutine

I assume it compiles at least under common desktop operating systems.

But there was a problem when used in combination with WebKit:

   https://bugreports.qt.nokia.com/browse/QTSIM-22

--
Peter
--
Empfehlen Sie GMX DSL Ihren Freunden und Bekannten und wir
belohnen Sie mit bis zu 50,- Euro! https://freundschaftswerbung.gmx.de


Reply | Threaded
Open this post in threaded view
|

Re: Any suggestion for a robust C coroutine library which can be used with LuaJIT ?

William Ahern
On Thu, Jan 12, 2012 at 04:52:20PM -0800, Joseph Stewart wrote:
> Maybe this is too much but I've enjoyed messing with "libtask":
>
> http://swtch.com/libtask/
>
> I've used this in conjunction with lua for some non-serious tinkering.
> You'd get channels and some networking code with this too. I believe Zed
> Shaw uses pieces of libtask (not my code) in his Mongrel2 server.
>

It, too, uses makecontext(3), swapcontext(3), et al. In fact, all of the
alternatives given on the list do, AFAICT, because it's the obvious and
correct way to do it. However, notwithstanding the prevalence of the
interfaces (*BSD, Linux, and OS X all have them) they've been removed from
POSIX because all the vendors have abandoned them. The vendors haven't put
any effort into making them play well with POSIX threads; in particular,
apparently, thread local storage.

As long as you're not linking with pthreads, all of the alternatives will be
equally "robust", lightweight, or what have you. The only differences are
the appeal of their APIs.


Reply | Threaded
Open this post in threaded view
|

Re: Any suggestion for a robust C coroutine library which can be used with LuaJIT ?

Joseph Stewart
Yeah, you're right... I forgot I had to muck with stuff to get this to compile for ARM.

On Thu, Jan 12, 2012 at 6:32 PM, William Ahern <[hidden email]> wrote:
On Thu, Jan 12, 2012 at 04:52:20PM -0800, Joseph Stewart wrote:
> Maybe this is too much but I've enjoyed messing with "libtask":
>
> http://swtch.com/libtask/
>
> I've used this in conjunction with lua for some non-serious tinkering.
> You'd get channels and some networking code with this too. I believe Zed
> Shaw uses pieces of libtask (not my code) in his Mongrel2 server.
>

It, too, uses makecontext(3), swapcontext(3), et al. In fact, all of the
alternatives given on the list do, AFAICT, because it's the obvious and
correct way to do it. However, notwithstanding the prevalence of the
interfaces (*BSD, Linux, and OS X all have them) they've been removed from
POSIX because all the vendors have abandoned them. The vendors haven't put
any effort into making them play well with POSIX threads; in particular,
apparently, thread local storage.

As long as you're not linking with pthreads, all of the alternatives will be
equally "robust", lightweight, or what have you. The only differences are
the appeal of their APIs.



Reply | Threaded
Open this post in threaded view
|

Re: Any suggestion for a robust C coroutine library which can be used with LuaJIT ?

Graham Wakefield-2
In reply to this post by William Ahern
I read that makecontext/setcontext etc. are deprecated (e.g. on OSX)

http://tch854135.tch.quora.com/Why-is-ucontext-h-setcontext-getcontext-etc-deprecated-on-Mac-OS-X-Is-there-an-equivalent-coroutine-esque-library-or-is-it-all-just-threads-now

On Jan 12, 2012, at 6:32 PM, William Ahern wrote:

> On Thu, Jan 12, 2012 at 04:52:20PM -0800, Joseph Stewart wrote:
>> Maybe this is too much but I've enjoyed messing with "libtask":
>>
>> http://swtch.com/libtask/
>>
>> I've used this in conjunction with lua for some non-serious tinkering.
>> You'd get channels and some networking code with this too. I believe Zed
>> Shaw uses pieces of libtask (not my code) in his Mongrel2 server.
>>
>
> It, too, uses makecontext(3), swapcontext(3), et al. In fact, all of the
> alternatives given on the list do, AFAICT, because it's the obvious and
> correct way to do it. However, notwithstanding the prevalence of the
> interfaces (*BSD, Linux, and OS X all have them) they've been removed from
> POSIX because all the vendors have abandoned them. The vendors haven't put
> any effort into making them play well with POSIX threads; in particular,
> apparently, thread local storage.
>
> As long as you're not linking with pthreads, all of the alternatives will be
> equally "robust", lightweight, or what have you. The only differences are
> the appeal of their APIs.
>
>