Categories
Other Programming

Playing with Go: Channels and Go-Routines

Edit:  I’m implementing a new version of this that isn’t limited by overflow.  I’m doing this by adding the numbers on a per digit basis, carefully managing the overflow, and storing the numbers as strings.  Theoretically, we should be able to calculate LARGE Fibonacci numbers like this.

When I heard about Google’s new programming language Go last week, I immediately jumped on it.  I had used Limbo before for a distributed programming course, so I thought that I might write some code to help other people get their feet wet.

My example is a simple Fibonacci number calculator.  It works by creating a new Go-routine every time it needs to calculate the next number.  There are a couple different approaches to doing this:  Create the entire pipeline first (faster calculation, slower set up), Create the pipeline as we go (not a bad way to go, smaller overhead), or create a ring and have the calculation take place within the ring.  Communication between the Go-routines and the main thread are handled via channels.

I heavily documented the code so that beginners might be able to make sense of what’s going on.  If you have any questions, please leave a comment!

Download the code here.

/*
* Name:   fibonacci.go
* Date:   November 16, 2009
* Author: Jack Slingerland (jack.slingerland@gmail.com)
*
* Description:  This program is a Fibonacci number calculator.
*   It may be invoked as follows:  “./8.out [goal]”, where [goal]
*   is the Fibonacci number that you want to computer.  Currently
*   the program is limited to the 46th Fibonacci number due to
*   overflow, however a new implementation is in the works that
*   won’t have that limitation.  The real purpose of this program
*   is to show how Go-routines work, and how communication and
*   sychronization between them is handled using channels.
*/

package main

import (
“os”;
“fmt”;
“strconv”;
)

/*
*  This ADT holds all the information needed to calculate the next
*  Fibonacci number in the sequence.  Current is the current index
*  in the series (ex, 5 = We’re on the 5th number in the sequence).
*  Goal is of course, the number in the sequence that we’d like to
*  achieve.
*/
type fibonacci struct {
a int;
b int;
current int;
goal int;
}

func main() {
//Check the command line arguments for sanity.
goal, err := checkArgs();
if(err != “”) {
fmt.Fprintf(os.Stdout, “Error: %s”, err);
os.Exit(1);
}

//Special case:  If the goal is 2 or less, the Fibonacci number is always
//1.  This isn’t really worth creating channels + go routines for.
if(goal <= 2) {
fmt.Fprintf(os.Stdout, “Fibnonacci Value %d is: %d\n”, goal, 1);
} else {
//Construct two channels, the input channel acts as our communication
//between the Go routines.  As you can see, it can be typed as an
//ADT(struct), which makes passing data REALLY easy between go routines.
//The final channel is for passing back the goal Fibonacci number to
//the main thread.
input := make(chan fibonacci);
final := make(chan int);

//Create a new fibonacci object and set it’s values.
var x fibonacci;
x.a = 1;
x.b = 1;
x.current = 2;
x.goal = goal;

//Create a new Go routine with the addNumber function.  We pass it the
//two channels that were declared earlier.  This is similiar to “spawn”
//in Limbo.
go addNumber(input, final);

//The first addNumber() Go routine will block until it gets input from
//the input channel.  So, we pass it our fibonacci object.
input <- x;

//Now, we block and wait for the Go routines (addNumber()) to finish up
//and send us back the final value.
number := <- final;

//Print the value out and we’re done!
fmt.Fprintf(os.Stdout, “Fibnonacci Value %d is: %d\n”, x.goal, number);
}
}

/*
* The addNumber() function takes two channels as parameters.  One is a
* channel of fibonacci, which holds information about which number to
* calculate and when to stop, and then a channel of type int, which will
* be used to send the final goal number back to the main thread.
*/
func addNumber(input chan fibonacci, final chan int) () {
//Block here and wait for input from the previous thread
//or the main thread, depending on the situation.
x := <- input;

//Here we check to see if we have met our goal, if we
//have, we return the goal value back to the main thread
//via the final channel.  Otherwise, we calculate the
//next number in the sequence.
if(x.current < x.goal) {
fib := x.a + x.b;

//This is fun because you can assign multiple values at once.
//x.a <- x.b and x.b <- fib.  🙂
x.a, x.b  = x.b, fib;
x.current = x.current + 1;

//Make a new channel of type fibonacci so that we can communicate
//with the new Go routine that we are about to create.
output := make(chan fibonacci);

//Pass the new Go routine the newly created channel, as well as the
//final channel that was passed in from the caller.
go addNumber(output, final);

//Send the fibonacci object out on the channel.
output <- x;
} else {
//Send the goal value out on the channel back to main.
final <- x.b;
}
//Go routine dies now.
}

/*
* The checkArgs() function is a great example of returning multiple
* values.  We return an integer and a string to the caller, so handling
* errors is fairly straight forward.
*/
func checkArgs() (int, string) {
//Fetch the command line arguments.
args := os.Args;

//Check the length of the arugments, return failure if that are too
//long or too short.
if((len(args) < 2) || (len(args) >= 3)) {
return -1, “Invalid number of arguments.\n”;
}

//Convert the goal argument to an integer.
goal, err := strconv.Atoi(args[1]);

//Make sure the conversion went correctly, otherwise return failure.
if(err != nil) {
return -1, “Invalid argument.  Argument must be an integer.\n”;
}

//Since this implementation is limited, make sure the user can’t go
//beyond the program’s limits.
if(goal > 46) {
return -1, “This program only calculates up to the 46th Fibonacci number.\n”;
}

//Check the lower bound as well.
if(goal < 1) {
return -1, “Invalid range.  Number must be >= 1.\n”;
}

//On success, return the goal value and an empty string indicating
//that everything is good.
return goal, “”;
}

Categories
Other

$25 Amazon Gift Certificate

ShoulIGetTheBook.com is giving away a $25 gift certificate just for entering a review on their site.   The odds of winning are good now (only 5 or six people have registered), so i suggest checking it out here.

Categories
Other Other Programming

Geocities : Salvaged

As much as it pains me to look at, I decided to salvage one of the earlier web pages that I ever made.  I have long since forgot earlier web pages, but “The NannyMUD Guide” really stood out to me because it was my first serious effort at web development.

It’s nasty sure (big crappy flash animations, talking to myself, awful menu design, crap color scheme,…), but it was an important to me then.  Click the link below to check it out.

The NannyMUD Guide

Edit:  I’ve been asked for a quest walk-through for NannyMUD.  Click here to download it.

Categories
Other

Circular Queue

If you float around Computer Science / Programming circles enough, it’s likely that you’ve come across the term “circular queue”.  A circular queue is a queue of <something> that is fixed in size, and when the end of the queue has been reached, it circles back to the front and starts pushing items from there.  If the head catches up to the tail, the queue is said to be full.  In C style languages, circular queues can be implemented using pointers fairly easily.  In my case though, I don’t have pointers, so I’m just keeping two variables (head, tail) that tell me where the import parts are.

Some people might wonder “Why on earth are you implementing a queue by hand?”, which is valid question.  The answer is because there is now STL-type library in Limbo, so implementation of a queue falls into my lap.  I suppose this post doesn’t have much of point, except to say “Use the friggin’ library if it’s available.”.  For one, it’s already been done, and two, it’s probably bug free.

Categories
Other

Interesting Assignment

Recently in my graduate level operating systems course, we were assigned to make a networked semaphore manager.  Essentially, client machines can connect to the semaphore manager and ask it to control access to SOMETHING.  In our case, we’re just proving a point, so we’re controlling access standard error.  It’s an interesting problem because coding anything over a network is tough.  Secondly, creating a reliable semaphore manager is tough on it’s own.  To make matters worse, we’re using a hosted environment called Inferno.  Inferno was once created by Bell Labs, but is now distributed by Vitanuova.  For reference:

LimboOh, and it’s due in two days.  Taking a bit of time off was nice, but probably not the wisest decision.

Categories
Other

Weekend

This weekend I’m charged writing a networked semaphore manager.  In other news, I’m hanging out with Kelly all weekend.

Spring Break 2009
Spring Break 2009
Categories
Other

Windows 7: First Impressions

Windows 7 Login

Yesterday I decided to abandon Linux on my laptop.  Why?  I was bored.  I’ve been using Linux (Ubuntu) on my laptop(s) since 2005, so I was in need of something different.  Of course, there are definitely some other reasons why I switched:  stand by actually works, full driver support for my 9600 GT M, full support for finger-print reader, ability to place games.

In addition to the features mentioned above, Windows 7 has some great new additions.  First of all Aero is actually useful now.  The transparency issues of Vista have all be taken care of.  And, it has some sweet new themes too.  Ooh, and gestures too!  You can grab the top of a window, shake it around vigorously, and all the other windows will minimize to the task bar.  Performance-wise, it’s also heads and shoulders about Vista.

I’ve only been using it for a day, and I can’t say enough good things about it.

Categories
Other

Taking Over

Whenever you think that things are getting a little too boring, something will always come up that will make you wish that they were still that way.  Today, has been one of those days.  Recently, one of our senior faculty decided to go AWAL.  BOOM! BAM! Gone.  Just like that, he decided that he didn’t want to do his job anymore and he left the rest of the department to pick up the pieces.

While I’m only a grad assistant, I’m officially part of the department.  I teach 5 labs, hold office hours, yada yada yada.  So guess what that means for me?  I got to pick up one of the labs that this faculty abandoned.  It’s a fairly large lab, with about 30 people in it.  From looking at their faces, they seemed to be relieved that I showed up.  After looking at their grades, I can see why:  I don’t think he actually told them when assignments were due.  In fact, only half of them even turned in their first project (significant portion of their grade).

As big of pain as it is, I’m happy to do it.  I like to be able to contribute and hopefully I can help the department save-face in this whole fiasco.