Journal for 2007

GHOP Help Needed

The Google Highly Open Participation (GHOP) contest has been running for a couple of weeks now, and the Mono Project has seen a fair bit of action. Sadly we've only had five completed tasks, with a couple more almost done. On a lot of the claimed tasks, many of the students and mentors have been slow to act, busy with real life work. I think that the timescale of the tasks makes things difficult. It's not easy to think up a task that an inexperienced student can complete within five days, especially considering that they often need to get up to speed with the technologies before starting, and need to fit it in around schoolwork. Hopefully now that the Christmas holidays are beginning, students will have a lot more time to spend on the GHOP!

I apologise to any student who's been held up from starting further tasks because of delays in reviewing and closing the tasks. Doing a proper job takes quite a bit of time, and the Mono team has a lot of other important things to do too, like getting the shiny new Mono 1.2.6 and MonoDevelop 1.0 Beta 3 releases ready.

I'd like to put out a general request to everyone and anyone in the Mono community, or working with Mono-based apps, to lend a hand for the GHOP. You can submit proposals for tasks on the Mono GHOP issue tracker, and critique students' work. It doesn't matter if you can't write code — help with docs or icons. Go out and send students our way. This has the potential to be a huge community event. You can find us hanging out on #mono-ghop as well as the usual IRC channels on GIMPNet IRC.

MonoDevelop in the GHOP

So far, all five completed tasks for the Mono GHOP have been MonoDevelop -related. I'm really pleased with the amount of interest we've had so far. I'd like to thank our hard-working students and mentors, and the wonderful people at Google's Open-Source Program Office who put this contest together.

  • Dan Abramov submitted a very cleanly-written addin to integrate the Smokey code analysis tool . I'll be using this to tidy up minor bugs in the MonoDevelop codebase, and hopefully we can ship it in the addin repository after the 1.0 release.
  • This was followed by some fantastic icons from Vinicius Depizzol ("videpizzol"), and these will certainly be in the 1.0 release. They're not yet in SVN due to my pending review of our icon usage and handling in MonoDevelop.
  • The completed Brazilian Portuguese translation by Renato Felipe Atilio ("renatoat") is now our most up-to-date first translation, though due to changes to our translation infrastructure it's not merged into SVN yet.
  • The latest addition to our still-meagre documentation comes from "entereczek", a Tutorial for C/C++ Projects. I've put it on the MonoDevelop wiki.
  • Although not strictly a MonoDevelop contribution, "dwashing" created a MonoDevelop solution for F-Spot that's been committed to SVN.

Please continue to suggest, claim and review tasks. We still have plenty left on the issue tracker over at Google Code.Pop over to #mono-ghop on GIMPNet IRC to discuss things or to hang out with us.

Be careful using anonymous delegates across threads

[UPDATE]: It has been pointed out to me that the premise of this article is wrong. The compiler specifically avoids this problem by hoisting the captured variables into an inner class of which the generated method is also an instance member, and creating a new instance of this class for each call. I'm not sure what bug I ran into that causes the behaviour I denounced, or whether it was simply sloppy handling of reference types on my part -- but I feel particularly stupid having vaguely remembered "inner classes" from reading Raymond Chen's fine explanation of this over a year ago, yet not having checked it before posting this article. Nonetheless, I shall let the article remain as a reminder of the code that this wonderful feature saves you from having to write. Also, the queue/lock-based code may still be useful when one needs data passed to the GTK thread in a guaranteed order.

Anonymous delegates are incredibly useful, especially in that they can "capture" variables from a parent scope. Used within a single thread, they are very easy to understand. However, if you're using them to pass data across threads, you need to understand how the variable capture works.

Consider the following code snippet, in which the "data" variable is captured from the delegate's parent scope.

void ProcessIncomingData (string data)
{
	Gtk.Application.Invoke (delegate (object sender, EventArgs e) {
			textBuffer.AddText (data);
		});
}

What's wrong with this?

Let's expand the anonymous method into something resembling the compiler-generated code.

void ProcessIncomingData (string data)
{
	compilerHoistedVariable = name;
	Gtk.Application.Invoke (new EventHandler (compilerGeneratedMethod));
}
 
string compilerHoistedVariable = null;
 
void compilerGeneratedMethod (object sender, EventArgs e)
{
	textBuffer.AddText (compilerHoistedVariable);
}

Notice that the variable has been "hoisted" into the class scope, so that the generated method used for the anonymous delegate can access it. (The actual compiler-generated code is a bit different, encapsulating the hoisted variables in an inner class, but the principle is the same).

Now consider what happens if ProcessIncomingData gets called by the data-processing thread several times before the GTK+ loop gets run and can handle the invocations. Only the most recent value remains in the compiler-hoisted variable, and the earlier data strings are lost.

This isn't a problem if you're passing transient state, for example the visibility state of a button. But if you're passing data, think carefully about the internal mechanics. You may have to implement locking on the shared data structure.

void ProcessIncomingData (string data)
{
	lock (textBufferQueue) {
		textBufferQueue.Enqueue (data);
		if (!queueHandlerRunning) {
			queueHandlerRunning = true;
			Gtk.Application.Invoke (
				delegate (object sender, EventArgs e) {
					lock (textBufferQueue) {
						while (textBufferQueue.Count > 0) {
							textBuffer.AddText (textBufferQueue.Dequeue ());
						}
						queueHandlerRunning = false;
					}
				});
		}
	}
}
bool queueHandlerRunning = false;
Queue<string> textBufferQueue = new Queue<string> ();

This could hardly be described as "pretty", and the anonymous delegate has grown so big that we may as well move its definition out into a conventional method.

Things are easier if the delegate consumer offers an alternate call allowing you to pass arguments along with the delegate, such as Gtk.Application.Invoke and its Invoke (object sender, System.EventArgs args, System.EventHandler d) overload.

void ProcessIncomingData (string data)
{
	Gtk.Application.Invoke (
		this,
		new dataEventArgs (data),
		delegate (object sender, dataEventArgs e) {
			textBuffer.AddText (dataEventArgs.Data);
		});
}
 
class dataEventArgs : EventArgs
{
	public string Data;
	public dataEventArgs (string data)
	{
		this.Data = data;
	}
}

This is much more verbose than the method with which we started, but at least you won't lose any data and don't have to worry about locking.

Sadly, the anonymous types in C# 3.0 can't be used to simplify this. For a start, they don't allow inheritance. One might think that the "object sender" argument could be abused to pass an anonymous type, however in order to leave the scope of a method, the anonymous type must be cast to "object". The only way to access its properties would be via reflection, which would not only be verbose but would also carry a performance penalty.

How not to break Mono installations

It's a bad idea to mess with the packaged version of Mono on your Linux distro by installing another version of Mono on top of it or into another of your distro's standard prefixes such as /usr/local. Your distro's developers, testers and packagers have tested the packaged version of Mono to make sure that it works with the various applications that depend on it, such as MonoDevelop, Tomboy, F-Spot, Beagle and Banshee. In addition, you're likely to end up with unusual errors due to mismatched bits and pieces interacting in unpredictable ways.

If you need a more recent version in order to test new features and bugfixes, please keep a properly separated parallel Mono environment. By following these instructions you can ensure that you don't affect your stable Mono platform while experimenting with newer versions.

This applies to platform bindings such as GTK#, GtkSourceView# and GNOME# too!

GtkSourceView 2 in MonoDevelop

I recently added support for GtkSourceView 2 to MonoDevelop, and it can be enabled with the "--enable-gtksourceview2" configure switch. Unfortunately the Boo Binding and the Database Addin depend on GtkSourceView# directly, and aren't compatible with the API changes in 2.0. I may get round to fixing them later. However, I've already switched on GtkSourceView2 support in my MonoDevelop build repository. The main reason I did this, of course, was the wonderful dark grey colour scheme "oblivion" :-)

The GtkSourceView2# binding isn't officially released yet, and will probably get absorbed into the Gnome# platform bindings, but right now it seems to work fine.
Packages for openSUSE 10.3 are available from my MonoDevelop build repository.

Notable new features are:

  • Improved syntax highlighting
  • Support for colour schemes

Notable missing/removed features are:

  • Printing
  • Bookmarks (also used for debugger breakpoints, when the debugger worked)

There isn't a UI for changing colour schemes yet, but it can be done manually in the ~/.config/MonoDevelop/MonoDevelopProperties.xml file by setting/adding the property <Property key="GtkSourceViewStyleScheme" value="oblivion" /> within the property <Property key="MonoDevelop.TextEditor.Document.Document.DefaultDocumentAggregatorProperties">.

MonoDevelop trunk builds

Hot on the heels of Lluis's MonoDevelop 1.0 Beta 2 announcement, I'd like to announce the availability of frequent builds of MonoDevelop from SVN trunk, packaged for openSUSE 10.3. If you'd like to get the latest and greatest bug fixes and features but don't want to build MD yourself, head over to my openSUSE Build Service Sandbox. The packages will also come up in the openSUSE search for MonoDevelop packages.

Warning: these packages are not guaranteed to be stable, though I'll try to push only usable revisions. I may also enable and disable features at a whim, e.g. disabling the Boo binding and MonoDevelop.Database addin in order to enable GtkSourceView 2 support.

Update: the sandbox link currently requires that you're logged into the openSUSE Build Service, so here's a direct link to the repository.

Joined Novell, and moving to Boston

I apologise for not having updated my blog more often. Things have been quite hectic recently...

A month ago (as announced by Miguel de Icaza) I joined the fantastic Mono team at Novell, working on the MonoDevelop IDE. Since then I've been busy getting the ASP.NET Project features ready for MonoDevelop 1.0 Beta 1, which we finally released on Monday. It's essentially feature complete for 1.0, except for the "Web Deploy" feature that didn't quite make it into the beta but is currently in SVN trunk.

My "free" time has been taken up with preparing for my upcoming move to Boston, MA, USA this weekend. I'll soon be working with the cool people in the Novell offices in Cambridge! This move is a little daunting, as I've never been outside of Europe before, but I'm really excited about it.

International Talk Like Pirate Day

Fetch me spyglass! I just realised 'tis International Talk Like A Pirate Day and I ha'nae installed th' Drupal Pirate Filter on this incarnation o' me site.

Notes on GUADEC

First of all I'd like so say what a great experience GUADEC was. It was great to talk to cool people, see the amazing software people are writing, and hear talks from inspiring speakers. It really emphasised for me why having such a diverse yet coherent community has made GNOME the awesome ecosystem it is today.

I'm a little disappointed I could only attend the Core days, but I think they were enough for me. I'm currently away and it's not easy to write or post to my journal, but I've patched together some notes on the talks I attended.

Tuesday: Core I

OpenMoko: I can't wait to get one and put Mono on it. There will be loads of incredible applications.

LibGnomeDB: This looks like a good start to do bespoke data apps in C or C++, but it's not even close to the kind of databinding we need in GTK# to compete with SWF.

Ari Jaaksi's Keynote: An interesting perspective on F/OSS from Nokia's viewpoint. It's worth bearing in mind that support and training costs prevent commercial concerns from being as agile as hackers.

Telepathy and Tubes: Great stuff. This should be everywhere. Could F-Spot use it for photo sharing? Could Banshee-NG-DBus use tubes to replace DAAP?

Metadata Overview: Joe explained the current state of metadata on the Desktop and made a good case for aggregating separate metadata stores rather than using Tracker's approach of squeezing everything into a one-size-fits-all solution.

Havoc's and Bryan's Keynote: I fully agree that integration with online services is key to the continued success of GNOME, and could be a good way to expand our user base. But beware of getting people locked into proprietary services.

Wednesday: Core II

Keynote: Disappointed the speaker wasn't there, as I dashed to make it on time. However, Michael Meeks' replacement talk on using a simulated disc to calculate reproducible I/O times was pretty cool.

New Main Menu: Jim gave a nice account of the reasoning behind the cool new Main Menu. I like the way the 'tiles' are being used elsewhere; they should be part of the platform. One thing I'd like to see is a huge main menu instead of the desktop...

Lowfat: MacSlow demonstated his really cool user interface, but I see it as having a limited scope. Why limit ourselves to physical metaphors? My real desktop is often a mess. I would love to abolish the "desktop" metaphor completely. It's a horribly inefficient use of screen real-estate, so I certainly don't think it'll ever filter down to small mobile devices.

Alex Graveley's Keynote: Pyro Desktop is an awesome hack, and I'd love to see web developers welcomed to the desktop. However, I don't think desktop developers should move that far towards web-style inefficiency...

Lightning Talks: In particular I remember the Giver/Tomboy note sharing over Avahi. It's simple, yet I imagine it could be very useful. It would be nice to have this on every electronic device I own. I also saw Banter, which I'd love to be able to try myself (segfaults from unmanaged land have prevented me thus far). The short version of Michael Meeks' talk with Federico was fun.

GTK+ Status: Looks like there are some nice improvements to look forward to, but nothing earth-shattering.

GTK+ 3.0 Discussion: No progress at all. A small group of people argued over what we can't do. What I took away from this was 'there will be no GTK 3.0'. The only way to make it workable in my view is to write a separate canvas-based toolkit library that can be embedded in GTK and vice versa. Eventually some apps will be able to drop the GTK dependency. I suspect that an ABI-stable GTK 2.x will stay around for a very long time.

Thursday: Core III

Robert Love's Keynote: Nice presentation of the wonderful Summer of Code program, though little was news to me. Shame about the fire alarm.

Clutter: Cool. I need to play with the Mono bindings. Wish I had time to write a widget set on top of it, with a widget interface/theme separation. This would be a good start for GTK 3.0. Indeed, why not write a toolkit like Moonlight, in that managed code is only binding to unmanaged code at an intermediate level?

Stormy Peters' Keynote: Nice presentation, though we already know that developers are creators. Good luck getting this across to companies!

Tracker: The metadata store sounds like a cool idea, and once you start thinking in terms of triples it's extremely tempting to extend them to everything. I almost fell victim to a similar hubris a few years ago. But you can't know everything about everyone's data. It's just not possible. There will always be different ways of doing things, and the key is to aggregate them intelligently, not reinvent everyone's wheels.

Doc Searls' Keynote: VRM is a nice idea, but I'm not quite sure how it fits into GNOME... It was a good keynote though.

Federico's Surprise Closing Keynote: Inspiring, and great to hear about GNOME's roots. We really need to think about new kinds of apps and "desktops", as we pretty much have the best "conventional" desktop in the world. How can we go beyond this?

Conclusion

The best thing about GUADEC was meeting people: Gabriel, Patrick, Rodney, Toms, Aidan, Aaron, Jim, Joe, Fabian, and many others. Thanks for making it a fun place to be!

GUADEC has a great experience and made me think a lot about the future desktop and mobile devices, and how Mono fits in with them. My opinion on how proprietary online services affect the Free desktop, which is something I've been thinking about a lot for a few months, has now developed to the point at which I'm prepared to write publicly about it. I shall be posting a series of discussions and ideas over the next month or two.

Going to GUADEC 2007

I'm going to GUADEC 2007, because

  • I hack on a GNOME IDE, MonoDevelop
  • GNOME is cool, and there will be lots of cool people at GUADEC
  • Birmingham is under five hours away by train

If anyone would like to meet up to chat about MonoDevelop, Mono, GNOME, Drupal, or anything else at all, please drop me a line or post a comment, and I'll do my best to find you. I'm afraid that due to other commitments I'll only be around during the Core days.

Pages