<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Ryan's Tech Blog &#187; fun</title>
	<atom:link href="http://ryepup.unwashedmeme.com/blog/category/fun/feed/" rel="self" type="application/rss+xml" />
	<link>http://ryepup.unwashedmeme.com/blog</link>
	<description>mostly tech, mostly rants</description>
	<lastBuildDate>Wed, 04 Jan 2012 03:42:20 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>coroutines in common lisp with bordeaux-threads</title>
		<link>http://ryepup.unwashedmeme.com/blog/2010/11/21/coroutines-in-common-lisp-with-bordeaux-threads/</link>
		<comments>http://ryepup.unwashedmeme.com/blog/2010/11/21/coroutines-in-common-lisp-with-bordeaux-threads/#comments</comments>
		<pubDate>Sun, 21 Nov 2010 20:12:10 +0000</pubDate>
		<dc:creator>ryan</dc:creator>
				<category><![CDATA[fun]]></category>
		<category><![CDATA[lisp]]></category>

		<guid isPermaLink="false">http://ryepup.unwashedmeme.com/blog/?p=217</guid>
		<description><![CDATA[Turns out threads are a lot easier without beer and after a good nights sleep.  Following up on last night&#8217;s defeat (see coroutines in common lisp), I re-read the documentation this morning and got my locks sorted out. I now use one lock and two condition variables (CV).  From the bordeaux-threads API docs: A condition [...]]]></description>
			<content:encoded><![CDATA[<p>Turns out threads are a lot easier without beer and after a good nights sleep.  Following up on last night&#8217;s defeat (see <a href="http://ryepup.unwashedmeme.com/blog/2010/11/21/coroutines-in-common-lisp/">coroutines in common lisp</a>), I re-read the documentation this morning and got my locks sorted out.</p>
<p>I now use one lock and two condition variables (CV).  From the <a href="http://trac.common-lisp.net/bordeaux-threads/wiki/ApiDocumentation">bordeaux-threads API docs</a>:</p>
<blockquote><p>A condition variable provides a mechanism for threads to put themselves  to sleep while waiting for the state of something to change, then to be  subsequently woken by another thread which has changed the state.</p></blockquote>
<p>I thought of these CVs like events in Java/C#/Javascript.  Telling one thread to <code>CONDITION-WAIT</code> on a CV is kinda like telling it to listen to that event, and have another thread <code>CONDITION-NOTIFY</code> on a CV is kinda like firing the event.  It took me a long time to understand the importance of <code>CONDITION-WAIT</code> atomically releasing a lock, and reacquiring it before continuing execution in that thread.  That mechanism let me coordinate some sequential execution between the threads, eliminating the race conditions that beat me last night.</p>
<p>I also added the ability to send a value into the coroutine by setting the return value of <code>yield</code>.</p>
<p>I used one CV to tell the coroutine it should run to the next <code>yield</code>, and another CV for the coroutine to tell the caller that a value was ready for it.  I had a few let bindings for my shared memory, closing variables into both the coroutine and caller functions.  The coroutine doesn&#8217;t spawn a new thread until the first time it&#8217;s <code>funcall</code>ed.  I have a somewhat poor mechanism for determining if the coroutine is done; you specify a sigil value and the coroutine <code>yield</code>s that as the final value (kind of like <code>eof-value</code> in stream reading functions).  I tried to use <code>thread-alive-p</code>, but ran into race conditions.  I have a few ideas for how to improve that.</p>
<p>Here&#8217;s the latest make-coroutine macro and test function:</p>
<pre>
(defmacro make-coroutine ((&#038;key (coroutine-done-value :done))
			  &#038;body body)
  (alexandria:with-gensyms ((yield-cv "there a value ready for pickup")
			    (run-cv "coroutine should run")
			    (lock "lock")
			    (val "shared memory")
			    (yield-result "return value of yield in the corouting")
			    (thrfn "thread function body"))
    `(let* ((,yield-cv (bordeaux-threads:make-condition-variable
			 :name "yield"))
	    (,run-cv (bordeaux-threads:make-condition-variable
			 :name "run"))
	    (,lock (bordeaux-threads:make-lock "coroutine lock"))
	    ,val ,yield-result
	    (,thrfn (lambda ()
		      (flet ((yield (&#038;optional n)
			       (setf ,val n)
			       ;;signal that a value is ready for pickup
			       (bordeaux-threads:condition-notify ,yield-cv)
			       ;;wait for a chance to run
			       (bordeaux-threads:condition-wait ,run-cv ,lock)
			       ,yield-result))
			(bordeaux-threads:acquire-lock ,lock)
			,@body
			(yield ,coroutine-done-value)
			(bordeaux-threads:release-lock ,lock)))))

       ;;function to pull values from the coroutine
       (let ((alive-p T) thr)
	 (lambda (&#038;key (send nil send-suppliedp))
	   (when alive-p
	     (bordeaux-threads:with-lock-held (,lock)
	       (if thr
		   (bordeaux-threads:condition-notify ,run-cv)
		   (setf thr (bordeaux-threads:make-thread
			      ,thrfn :name "coroutine")))

	       (bordeaux-threads:condition-wait ,yield-cv ,lock)

	       (setf ,yield-result
		     (if send-suppliedp send ,val))

	       (when (eql ,coroutine-done-value ,val)
		 (setf alive-p nil)
		 (bordeaux-threads:condition-notify ,run-cv))
	       ))
	   ,val)))))

(defun coroutine-test ()
  (let ((cor (make-coroutine (:coroutine-done-value :done)
	       (yield 1)
	       (yield)
	       (yield 4)))
	(cor2 (make-coroutine ()
		(yield (yield (yield 4)))
		)))

    (assert (eql 1 (funcall cor)) )
    (assert (null (funcall cor)))
    (assert (eql 4 (funcall cor)))
    (assert (eql :done (funcall cor)))
    (assert (eql :done (funcall cor)))

    (assert (eql 4 (funcall cor2)))
    (assert (eql 4 (funcall cor2 :send 6)))
    (assert (eql 6 (funcall cor2)))
    (assert (eql :done (funcall cor2)))))
</pre>
<p>I&#8217;ll probably play with it more tonight, maybe put together a stand-alone repo / library.</p>
]]></content:encoded>
			<wfw:commentRss>http://ryepup.unwashedmeme.com/blog/2010/11/21/coroutines-in-common-lisp-with-bordeaux-threads/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>talking usb-serial to my arduino from lisp (sbcl) on linux</title>
		<link>http://ryepup.unwashedmeme.com/blog/2009/09/28/talking-usb-serial-to-my-arduino-from-lisp-sbcl-on-linux/</link>
		<comments>http://ryepup.unwashedmeme.com/blog/2009/09/28/talking-usb-serial-to-my-arduino-from-lisp-sbcl-on-linux/#comments</comments>
		<pubDate>Tue, 29 Sep 2009 01:07:09 +0000</pubDate>
		<dc:creator>ryan</dc:creator>
				<category><![CDATA[arduino]]></category>
		<category><![CDATA[fun]]></category>
		<category><![CDATA[lisp]]></category>

		<guid isPermaLink="false">http://ryepup.unwashedmeme.com/blog/?p=131</guid>
		<description><![CDATA[I got an arduino microcontroller a little while ago, and have played with it a little but found it&#8217;s C/C++ development environment annoying.  I wanted to control it from lisp, and that meant serial IO.  Many other languages have special serial libraries you can use, where you instatiate a Serial object with configuration like baud, [...]]]></description>
			<content:encoded><![CDATA[<p>I got an <a href="http://www.arduino.cc/">arduino</a> microcontroller a little while ago, and have played with it a little but found it&#8217;s C/C++ development environment annoying.  I wanted to control it from lisp, and that meant serial IO.  Many other languages have special serial libraries you can use, where you instatiate a Serial object with configuration like baud, parity, etc.  John Wiseman wrote<a href="http://lemonodor.com/archives/2008/02/arduino_serial.html"> arduino_serial.py</a> that shows this pattern.</p>
<p>I searched around for lisp options, and came up with a few options:</p>
<ol>
<li>open /dev/ttyUSB0 directly (from <a href="http://groups.google.com/group/comp.lang.lisp/browse_thread/thread/14d33b36279fe104/b7d0caa5540b0281?#b7d0caa5540b0281">a comp.lang.lisp thread</a>)</li>
<li>use a FFI wrapper around libusb (from a <a href="http://groups.google.co.uk/group/comp.lang.lisp/browse_thread/thread/dab1cfa3c3a69768">comp.lang.lisp thread</a>)</li>
<li>use <a href="http://www.sbcl.org/manual/Running-external-programs.html">sb-ext:run-program</a> to call out to python/C/whatever to deal with the serial port (we do something similar at work to render trac wiki markup to HTML in lisp)</li>
<li>write a small C program and FFI to that (was tempting for the experience)</li>
</ol>
<p>After much trial and error and some advice from the helpful folks on #lisp, I got method #1 working tonight.  I was able to read from arduino pretty easily, but I needed to issue this magic <a href="http://unixhelp.ed.ac.uk/CGI/man-cgi?stty">stty</a> command before I could write:</p>
<pre>stty -F /dev/ttyUSB0 9600 raw -parenb -parodd cs8 -hupcl -cstopb clocal</pre>
<p>I had been curious how lisp (or my underlying linux) would know what baud, parity, etc to use, and it makes perfect sense that I need to set these first.  After that, the lisp side ends up pretty simple.  It took a little tweaking to find the right <code>:direction</code>, <code>:if-exists</code>, and <code>:external-format</code> arguments.</p>
<pre>(with-open-file (stream "/dev/ttyUSB0"
			:direction :io
			:if-exists :overwrite
			:external-format :ascii)
  (format stream "hello")
  (read-line stream))</pre>
<p>Disorganized source is available at <a href="http://github.com/ryepup/arduino-experiments">http://github.com/ryepup/arduino-experiments</a>.  I have a few servos laying around, maybe this weekend I&#8217;ll have time to get lisp moving around the real world.</p>
<p>My dream goal is to have lisp controlling motors that are spinning mirrors to reflect a laser in very particular patterns.  I&#8217;d use this on halloween decorations for starters, combining with fog machine/dry ice to create nifty patterns and make people wonder how the hell I did it.  Maybe, if I have the willpower to see that through, then I&#8217;ll also hook up a USB camera (using <a href="http://www.cliki.net/CL-V4L2">cl-v4l2</a>) and get lisp to track and hightlight objects, augmented-reality style.  That&#8217;d be great for table-top games, being able to overlay terrain or effects on a grid mat.</p>
]]></content:encoded>
			<wfw:commentRss>http://ryepup.unwashedmeme.com/blog/2009/09/28/talking-usb-serial-to-my-arduino-from-lisp-sbcl-on-linux/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
	</channel>
</rss>

<!-- Dynamic Page Served (once) in 0.483 seconds -->

