chrishowie.com

Covariant IEnumerables, pre-.NET-4.0

by on Nov.05, 2009, under C#, Computer

One of the nice things that .NET 3.5 gives us is LINQ, which gives new life to the often-neglected IEnumerable generic interface. Sequence processing is now a first-class citizen in the C# world, and this is a good thing. However, it can be very tricky to design a usable API around enumerables. Today I present my solution to an annoying (but not showstopping) hurdle.

Consider the case where you have several types implementing an interface. In my case, these types all have a common ancestor, but this is beside the point. We’ll call the interface IFoo, and the classes implementing this interface ThingOne, ThingTwo, and ThingThree.

If I have a method that acts on a series of IFoo objects, it is tempting to accept IEnumerable<IFoo> as an argument. It makes sense, right? Well, sort of. Your users will not like this, because IEnumerable<ThingOne>, IEnumerable<ThingTwo>, and IEnumerable<ThingThree> are not convertible to IEnumerable<IFoo>. While it’s not too annoying, your users will have to cope by invoking Cast<IFoo>() on their enumerables for them to work with your API. This not only adds code overhead (read: more code to maintain) but a minor amount of CPU and memory overhead to create an object that is going to cast objects to an interface that they explicitly implement.

The solution is rather simple, but not very obvious at first glance. Instead of using the signature void OperateOnFoos(IEnumerable<IFoo> foos), use this instead: void OperateOnFoos<T>(IEnumerable<T> foos) where T : IFoo. It is a simple change, and the method will work exactly the same as before, except your users will no longer be required to cast their enumerables to IFoo.

This technique applies just as well to situations where you take an enumerable to a class that is designed to be subclassed.

Now depending on how generics are implemented in your runtime of choice, you’re still probably going to see a small memory hit for each different T you use when calling this method. But it’s not likely to be anywhere near the cost of creating a bunch of cast-enumerables that you really could do without. And that aside, the convenience of not having to Cast<IFoo>() enumerables is totally worth changing one line of code.

.NET 4.0 will likely render this mechanism obsolete with the introduction of covariant interfaces, but in the meantime let’s all do something nice for our users!

1 Comment more...

Cdh.SimpleRpc

by on Oct.15, 2009, under C#

I’ve got this idea to code some game servers for a series of cooperative games my brother and I used to play as kids. I get similar ideas all the time… how about a game server for this card game or that board game? The problem I run into is pretty much always exactly the same: what communication protocol do I use?

I decided on a list of criteria that this protocol, whatever it is, must meet:

  1. It must be portable across programming languages and runtimes. If somebody else wants to write a better client using a different environment, that should be straightforward — perhaps not necessarily easy, but at least straightforward.
  2. It must be relatively efficient on the wire. Protocol chatter should be minimal in comparison to the data being exchanged.
  3. The object library should be simple and elegant to code against. When writing my game, the last thing I want to worry about is silly protocol details. Just get my message to the other computer please.

And here are the existing protocols I considered:

  • .NET remoting. Since I code most in C# these days, it seemed like a logical choice. But it very blatantly breaks criterion 1 when using the binary formatter, and breaks both 1 and 2 when using the SOAP formatter.
  • SOAP web service. Criterion 3 is satisfied, until you get to session persistence details. Criterion 1 is satisfied, and criterion 2… not so much.
  • XML-RPC. Criterion 1 is met, and 2 is somewhat met. But criterion 3 is not — XML-RPC does not define any mechanism for dealing with persistent sessions. I would have to spend time writing a session manager with expiration and whatnot. No thanks.

And I’m sure I looked at others. The point is, for something as simple as message-passing between a game client and server, there doesn’t appear to be much out there that satisfies my requirements. And this is something I’ve come back to frequently.

Well, after several years of mulling the problem over in my subconscious, I knuckled down and coded. I have a usable library after two days of development. (And we’re talking maybe a few hours per day.) Written in C#, it allows any CIL-based language to write simple message-based client/server programs in very small amounts of code. For a quick example, let’s create a server that will convert strings to uppercase, with tracing back to the client.

First, we need to create an interface library so that the client and server know what each other’s methods are:

using System;
using Cdh.SimpleRpc;

namespace ServiceTest.Interfaces {
    public interface IServer {
        [RpcMethod] string ToUppercase(string str);
    }

    public interface IClient {
        [RpcMethod] void Trace(string message);
    }
}

Now, here is the client:

using System;
using System.IO;
using Cdh.SimpleRpc;
using ServiceTest.Interfaces;

namespace ServiceTest.Client {
    public class MainClass {
        public static void Main() {
            Stream serverStream = ConnectToServer();

            var service = new RpcService<IClient, IServer>(new Client(), serverStream);

            new Thread(delegate { while(service.Read()); }).Start();

            IServer server = service.RemoteServerProxy;
            Console.WriteLine("ToUppercase result: " + server.ToUppercase("this is a test"));

            serverStream.Close();
        }

        private Stream ConnectToServer() {
            // Here is your code to connect to the server endpoint.
        }
    }

    internal class Client : IClient {
        public void Trace(string message) {
            Console.WriteLine("Server trace: " + message);
        }
    }
}

Note that the RpcService object generates a typed object that will transparently proxy calls to the remote service. The server program is almost as simple:

using System;
using System.IO;
using Cdh.SimpleRpc;
using ServiceTest.Interfaces;

namespace ServiceTest.Server {
    public class MainClass {
        public static void Main() {
            Stream clientStream = AcceptConnection();

            Server server = new Server();
            var service = new RpcService<IServer, IClient>(server, clientStream);
            server.client = service.RemoteServerProxy;

            while(service.Read());

            clientStream.Close();
        }

        private Stream AcceptConnection() {
            // Here is your code to accept a client connection.
        }
    }

    internal class Server : IServer {
        public IClient client;

        public string ToUppercase(string str) {
            client.Trace("Entering ToUppercase");
            str = str.ToUpper();
            client.Trace("Leaving ToUppercase");

            return str;
        }
    }
}

Ta-da. Some closing notes about this library:

  • It should be completely thread-safe, and will allow you to place calls using the proxy objects from multiple threads. The calls will block until a response is returned from the remote service.
  • Yes, you can throw exceptions in a service method, and yes, it will cause an exception to be thrown remotely from the proxy object.
  • In the future it may be possible to flag service methods that return void as “no response” calls, which will cause the proxy call to return immediately. Of course, you will not be notified if an exception is thrown remotely.
  • This API doesn’t do any complex serialization, and will only operate on the primitive types, excluding IntPtr. It will probably allow transmission of arrays at some point, and perhaps allow custom objects too.

Looking back on the list of criteria, this library, even in the early stages of development, easily meets all three. I’ll be hacking on it some more I’m sure, and may even publish the Git repository somewhere, when I’m confident that the code doesn’t totally suck.

10 Comments more...

Chris Matthews vs. Kirk Watson (Re: Obama)

by on Sep.25, 2009, under Politics

Come to think of it, I can’t name any either…

2 Comments more...

Yet another monolithic update

by on Sep.02, 2009, under Computer, Games, OpenVP, Personal

I need to get into the habit of blogging more often. I haven’t even been twittering much lately…

You’ve probably noticed the visual update to my blog by now. I got tired of the default WordPress theme. I had to tweak this one a bit to get it to behave the way I want, but overall it’s pretty nice. A few weeks ago I added the live chat widget as well, which so far has attracted comments from exactly two people. Come on, I know there’s more of you out there!

My new job is going well. The current project I’m working on is a migration script to fix some datetimes that may have been incorrectly converted to GMT. If you’ve done any programming around timezone conversions, you’ll know it’s a blast! … Ok, it’s not that bad. It’s actually kind of fun, in a weird way.

On the “my projects” front, I’ve converted the OpenVP Subversion repository to two separate Git repositories, and created a third for the metadata pipeline project. Check them out on Gitorious.

I’ve started playing Black & White on my lunch break. The voice acting is a little iffy, but the gameplay is good after you figure out what you’re doing. (Which, ironically, doesn’t happen until you leave the tutorial island.) Oh, and I got the Metroid Prime Trilogy for Wii. I’ve only played the first on GameCube, but absolutely loved it. Can’t wait to tackle the two sequels.

That’s all for now.

5 Comments more...

New horizons

by on Jul.17, 2009, under Personal

There have been many good changes in my life recently. It’s been almost three months since I graduated college, and nearly two since I got married. Well, now I have another for the list.

For two years I’ve been working at Ontario Systems as an intern. The first year and a half were a lot of fun. I was coding PHP and Flex/ActionScript on a team of two other developers (one also my manager). However, I’ve been unable to secure a full-time job offer since graduating and have been continuing work as an intern, which pays enough to cover the bills, but not much more. Additionally, the company’s partnership with Microsoft means that pretty much all of the Linux servers are in the cross-hairs, so to speak. This is not necessarily a bad thing, but it does mean that my current role of PHP developer and interim Linux sysadmin is not exactly going to be permanent.

Last week I had the privilege of accepting a full-time job offer from Aprimo and will be starting work with them on July 27th. They are also a Microsoft shop, but I will be working on the development team and coding C#, which I’ve been hacking with for some years now. The company looks to be doing well, and the people I’ve met so far have been very friendly and welcoming. The developers I’ve talked to all seem very knowledgeable, and I’m looking forward to working with them.

I’m not sure which I’m excited about more: getting to work at Aprimo, or finally ending my job hunt. Both are pretty cool. I will miss my friends at Ontario Systems (we’ve had some pretty good times) but I am definitely looking forward to the future.

2 Comments more...

Splitting a Git repository

by on Jul.09, 2009, under Computer, Programming

First some backstory…

I had a public and a private Subversion repository on my web server, and when I started a new project I’d import it into one of them. This is nice because I get versioning and history, plus I get implicit synchronization between my various development boxen.

It’s not unusual to have one monolithic Subversion repository for many different projects, mainly because setting up a Subversion repository can take a small bit of work, especially if you are serving it from HTTP. However, Git makes it so easy to create new repositories that there is no excuse not to create per-project repositories, not to mention that you should anyway since Git doesn’t support checking out a subdirectory of a repository. You simply can’t use a monolithic Git repository because you have to clone the whole big tree, even if you only plan on working on one subdirectory.

Since Git is so much more awesome, I plan on converting my Subversion repositories over. But what do I do with the multi-project ones? There’s no built-in mechanism for pulling out just one directory, with history, into a new repository. So I wrote one.

The usage is git-pluck src-repo dest-repo path/to/directory. The script copies the repository at src-repo to a new directory, dest-repo, and then does its magic. It rewrites all of the commits so that all of the files in path/to/directory are moved into the root of the repository, and everything else is deleted. Commits that do not introduce changes to that directory are removed from the history, potentially including the first commit to the repository. Finally, the reflogs and backups are removed and the repository is compacted, leaving you with a small, single-project repository.

This script was written and tested using Git 1.5.6.5. Feedback is welcome!

3 Comments more...

Office fail

by on Jun.29, 2009, under Computer

One of the better fails I’ve seen from MS Office:

9 Comments more...

The road ahead

by on Jun.06, 2009, under Personal

When this is posted, my wedding ceremony will be underway. It’s been a long wait but it was so worth it.

Today I am marrying Deanne, the love of my life. We started dating about two and a half years ago. I can’t say it’s always been an easy road, but it’s been a good one and I wouldn’t trade her, nor my experiences, for anything.

I love you, De! I look forward to spending the rest of my life with you.

Expect radio silence until the 16th. (This, unfortunately, includes comment moderation. I will check comments first thing when I get back. Promise!)

6 Comments more...

Book meme at 5:39AM

by on May.19, 2009, under Personal

  • Grab the nearest book.
  • Open it to page 56.
  • Find the fifth sentence.
  • Post the text of the sentence in your journal along with these instructions.
  • Don’t dig for your favorite book, the cool book, or the intellectual one: pick the CLOSEST.

“It is still in dispute whether wars between neighbors occur mainly because they fight over territory, because they generate disagreements in their day-to-day interaction, or because they are more easily available for fights—but Vasquez (1995) presents a strong case for the territorial explanation.”

I’m selling textbooks online, you see…

3 Comments more...

Comcast modem fun

by on May.15, 2009, under Computer, Linux

Well, the Comcast guy showed up today and dropped off the modem self-installation kit. About two or three hours later and it still wasn’t working quite right.

Here is my setup. The modem is plugged into eth0 on a Linux box, and eth1 runs to a switch. Traffic routed out eth0 is masqueraded (also known as NATed). If the modem and Linux box are turned on then everything works fine. But if I bring eth0 down and back up, then some odd behavior begins. All traffic that originates on the Linux box behaves normally — I can use elinks to browse the web and irssi to chat on IRC without any problems. But any traffic that is masqueraded, meaning that it comes from another computer on my network, does not behave normally. The connection establishes and works for a split second and then is silent.

I’d suspect a routing problem on the Linux box, but tcpdump there confirms everything is working as it should. However, ifconfig reports RX errors on eth0. This makes no sense — traffic originating from the LAN side of the router box triggers receive errors on eth0. Unless I reboot the router and the modem. I have not observed this behavior with any other ISP or uplink switch.

Anyone have any theories?

6 Comments more...

Looking for something?

Use the form below to search the site:

Still not finding what you're looking for? Drop a comment on a post or contact me so I can take care of it!

Links

Links to friends' blogs, and a few other sites of mine.