Every once in a while I really want a burrito. I've detailed my travails of fighting the Mexican craving before and it isn't like the Brown in me is going anywhere anytime soon. Thankfully, I've found a new favorite eatery in Cork that does good, fairly cheap (around 5 EUR for the burrito), Mexican: Speedy Gonzalez, next to Fast Al's, in front of The Raven:
View Larger Map
Now, this ain't no Chipotle, Baja Fresh or Del Taco. But it just might be better than Taco Bell (OK - it definitely is - its just that Taco Bell has a special place in my heart and so I let even the most god-awful sloppy wrapping pass by there).
If you're in the city and enjoy Mexican, I'd very much recommend it. At least for the Veg burrito, the ingredients stay fairly true to all the burritos I have had before (and I've probably had more than a lot of Mexicans). They seem to use a mix of kidney and pinto beans, which I haven't seen before but it tastes great! One thing - make sure they put the cheese first on the hot beans/rice before putting the other Veggies and sauces. The cheese is supposed to be slightly melted when you take a bite out of it so it has to be right on the hot ingredients - they don't always get this right.
They also do Middle Eastern food but I have not tried it yet. Having been there several times so far with the goal of trying the Middle Eastern, I've somehow managed to forget I was not there for the Mexican. Anyway, I really don't get the Mexican and Middle Eastern combination under one roof - WTF is with that?
Anyhow, do try it - and if you try the Falafel there, let me know how that is.
One final note - I really haven't tried any other Mexican in Cork so this is the best I know. I have passed by Cafe Mexicana several times nearly going in to sit down and try the burrito. But several things always get in the way: First, the bean burrito is 18 EUR! That's beyond ridiculous - you get a bean burrito in Taco Bell for 99c! It's a burrito damnit, not some luxury steak. (Trying real hard not to go on a rant about how so many places in Ireland nearly rob your money) Second, the place looks like a formal restaurant. Burritos are what you usually find in a fast food place or a Taqueria. Totally wrong atmosphere if it's a restaurant - like praying to the lord in a bar.
Wednesday, March 4, 2009
Wednesday, December 5, 2007
SWTBot
For those who have tried to test GUI-based Eclipse plug-ins - i.e., Wizards, Dialogs, Editors, and a lot of other useful things in Eclipse, you know that there is a scarcity of options - and especially non-commercial ones. So, when it came time to write functional tests for the Eclipse-based toolset that the team I am part of is developing, it was really a matter of choosing one among a few frameworks that are still in the early stages - meaning minimal documentation, and constant changes.
Though the situation was less than ideal, I decided to go with one that looked promising - SWTBot. Although the documentation is almost non-existent as of yet, you will still be able to pick it up quickly after going through the samples and the code. You start with a SWTBot and use its various methods to locate the controls you want to test, and then use custom bots to manipulate (simulating clicks, key-presses, etc) and verify (testing value of label, etc.) aspects of those controls. Its trivial to include the SWTBot testing code within JUnit test cases and run it using the Eclipse JUnit runners. By the end of day one with SWTBot, I had tests for some dialogs and preference pages, and was well on my way to satisfying my testing requirements.
Now this is great and all but be aware that this framework is still in a relatively early stage of development: expect to go through the framework code to fix issues you encounter. In fact, I had several issues related to getting the appropriate timeouts (especially with the editor content-assist tests), making sure my event listeners were fired, etc. But the guy behind the framework - Ketan Padegaonkar is very committed to the project and is very approachable - he has already addressed the issues I have brought up. If you need to do functional testing of your SWT and Eclipse applications, SWTBot is definitely worth considering.
Though the situation was less than ideal, I decided to go with one that looked promising - SWTBot. Although the documentation is almost non-existent as of yet, you will still be able to pick it up quickly after going through the samples and the code. You start with a SWTBot and use its various methods to locate the controls you want to test, and then use custom bots to manipulate (simulating clicks, key-presses, etc) and verify (testing value of label, etc.) aspects of those controls. Its trivial to include the SWTBot testing code within JUnit test cases and run it using the Eclipse JUnit runners. By the end of day one with SWTBot, I had tests for some dialogs and preference pages, and was well on my way to satisfying my testing requirements.
Now this is great and all but be aware that this framework is still in a relatively early stage of development: expect to go through the framework code to fix issues you encounter. In fact, I had several issues related to getting the appropriate timeouts (especially with the editor content-assist tests), making sure my event listeners were fired, etc. But the guy behind the framework - Ketan Padegaonkar is very committed to the project and is very approachable - he has already addressed the issues I have brought up. If you need to do functional testing of your SWT and Eclipse applications, SWTBot is definitely worth considering.
Tuesday, July 3, 2007
Mechanizations - Towards an ActiveRecord for Gears
With the recent hoopla over ECMA/JavaScript on Rails, and the advent of Google Gears (albeit beta), there is definitely a potential bubble waiting to happen. It's reasonable to expect a lot of APIs and frameworks to appear around Gears, and around the idea of making the browser an even thicker client in general.
Towards that end, I started Mechanizations to ease development of Gears, and JavaScript applications in general. While it is very rudimentary at the moment, supporting only a basic RoR ActiveRecord's ConnectionAdapter-style API, I think it can still help others working with Gears. Eventually, I hope to evolve it into an ActiveRecord for Gears (who didn't think of how great it would be to have a JavaScript ActiveRecord when they first saw Gears?), and a more generic framework beyond that.
As an introduction, I think the following snippet from the tests for the GearsConnector object is useful:
Just a bit more from the test for select:
Towards that end, I started Mechanizations to ease development of Gears, and JavaScript applications in general. While it is very rudimentary at the moment, supporting only a basic RoR ActiveRecord's ConnectionAdapter-style API, I think it can still help others working with Gears. Eventually, I hope to evolve it into an ActiveRecord for Gears (who didn't think of how great it would be to have a JavaScript ActiveRecord when they first saw Gears?), and a more generic framework beyond that.
As an introduction, I think the following snippet from the tests for the GearsConnector object is useful:
testMigrate: function() {
var migrations = [
{ // version 0
up: function(c) {
c.createTable('test_table', {id: 'INTEGER', name: 'TEXT'});
},
down: function(c) {
c.dropTable('test_table');
}
},
{ // version 1
up: function(c) {
c.createTable('test_table1', {id: 'INTEGER'});
},
down: function(c) {
c.dropTable('test_table1');
}
},
{ // version 2
up: function(c) {
c.dropTable('test_table');
c.dropTable('test_table1');
},
down: function(c) {
c.createTable('test_table', {id: 'INTEGER', name: 'TEXT'});
c.createTable('test_table1', {id: 'INTEGER'});
}
},
{ // version 3
up: function(c) {
c.renameTable('test_table', 'test_table1');
},
down: function(c) {
c.renameTable('test_table1', 'test_table');
}
}
];
this.connector.migrate(migrations, 0);
assertEquals(this.connector.tables(), ['_migrations','test_table']);
this.connector.migrate(migrations, 2);
assertEquals(this.connector.tables(), ['_migrations']);
this.connector.migrate(migrations, -1);
assertEquals(this.connector.tables(), ['_migrations']);
// This migrations fails, so we remain at version -1
this.connector.migrate(migrations, 3);
assertEquals(this.connector.tables(), ['_migrations']);
}
Just a bit more from the test for select:
testSelect: function() {
this.connector.createTable('test_table', {id: 'INTEGER', name: 'TEXT'});
this.connector.insert('test_table', [0, 'R1']);
this.connector.insert('test_table', [1, 'R2']);
this.connector.insert('test_table', [2, 'R3']);
assertEquals(this.connector.select('test_table').length, 3);
assertEquals($.keys(this.connector.select('test_table', [])[0]).length, 2);
assertEquals($.keys(this.connector.select('test_table', ['*'])[0]).length, 2);
assertEquals(this.connector.select('test_table', {headers: true}).length, 4);
assertEquals(this.connector.select('test_table', {where: ['id=?', 0]}).length, 1);
assertEquals(this.connector.select(
'test_table', ['id'], {where: ['id>?', 0], limit: 1})[0]['test_table_id'], 1);
assertEquals(this.connector.select(
'test_table', {where: ['id>?', 0], limit: 1, offset: 1})[0]['id'], 2);
assertEquals(this.connector.select(
'test_table', ['id'], {orderBy: 'id DESC'})[0]['test_table_id'], 2);
this.connector.dropTable('test_table');
}
Saturday, June 16, 2007
What is OpenID?
Let's start with the problem:
Whether its for your blog, your email, or a news site, it's hard to get by on the Internet these days without encountering a login screen:

Whenever a site wants to make sure you are you (known as authentication), you have to sign in. Of course, this also means that you have to create a new account for each site. If you are like most people, you end up using the same username and password combination for almost every site. So, you go through the same process, with almost the same keystrokes every single time!
To put it concisely, each site has its own separate (but similar) process to identify and authenticate you. This is the problem.
How does OpenID solve this?
Well, it gives you a way to identify yourself across sites. That's right! You no longer have to create a separate account for each site that wants to authenticate you. You just have to create one OpenID for yourself and use this on every site that supports it.
Let's consider the login process for OpenID:

Behind the scenes
Now that you have seen the typical sequence for logging in with OpenID, let's talk a bit about what's actually happening behind the scenes. First thing you should notice is that my OpenID, http://rchodava.myopenid.com, is actually a URL. This is a key point - with OpenID, you identify yourself with a URL just like you identify other resources on the web with a URL. Since your identity is a URL, you can actually go to it in a browser. Try it - go to my identity page: http://rchodava.myopenid.com. You'll see something like:

Why is an OpenID also being a URL such a big deal? Well, it is very important to what is going on behind the scenes. After I clicked sign in on Pibb in Step 1 above, the URL that Pibb redirected my browser to for the second step was my OpenID (http://rchodava.myopenid.com)! Of course, it added along a few special parameters when it redirected me. This is the same thing that would happen on any site that works with your OpenID.
At this point, let me talk about what myOpenID is. In OpenID jargon, it is an Identity Provider. Basically, it's a service which hosts my identity page, and keeps track of my password. When sites like Pibb (called a Consumer in OpenID jargon) redirect to my OpenID URL, the Identity Provider first asks me for my password. This is how I authenticate (prove its me) with my Identity Provider, and prove to it that I am the owner of http://rchodava.myopenid.com.
Once my Identity Provider has verified with me, it needs to in turn tell the Consumer (Pibb) that I own my OpenID. This is basically what happens between Steps 2 and 3 above when I am redirected from my Identity Provider (myOpenID) back to the Consumer (Pibb). Again, special parameters are passed along so that the Consumer knows I have been authenticated.
A bit of a correction and a bit on Delegation
I should make a bit of a correction to the description above because it is not exactly what happens. After I enter my OpenID in Pibb and sign on, it does not immediately redirect my browser to my OpenID URL. Instead, the Pibb server first connects to my OpenID URL to check a few things. It checks whether my identity page contains a tag like the following:
If it is present, this tag basically tells the Consumer (Pibb) that instead of redirecting the user to their identity page to login, redirect them to the URL given in that tag. In fact, this kind of tag is exactly what is present on my identity page at myOpenID. So, Pibb does not redirect me to http://rchodava.myopenid.com but rather to http://www.myopenid.com/server to do my login.
This is a good place to mention a second special tag that can be present on an identity page:
This tag, together with the other "openid.server" tag above allow you to do delegation of your OpenID. What does this mean? It means that you can take any web-page which you control and use it as your OpenID. For example, if I were to own a website like
After I have done this, I could now use
Summing it up
Having gone through that long explanation, let me try to end by describing OpenID in the concise but loaded terms many other sites start with:
Where to go from here
The official site
I want my OpenID!
Note: In some of the screenshots above, the actual layout of the sites was changed a bit for brevity/bringing focus to the right areas.
Whether its for your blog, your email, or a news site, it's hard to get by on the Internet these days without encountering a login screen:

Whenever a site wants to make sure you are you (known as authentication), you have to sign in. Of course, this also means that you have to create a new account for each site. If you are like most people, you end up using the same username and password combination for almost every site. So, you go through the same process, with almost the same keystrokes every single time!
To put it concisely, each site has its own separate (but similar) process to identify and authenticate you. This is the problem.
How does OpenID solve this?
Well, it gives you a way to identify yourself across sites. That's right! You no longer have to create a separate account for each site that wants to authenticate you. You just have to create one OpenID for yourself and use this on every site that supports it.
Let's consider the login process for OpenID:

- We start out on a site which supports OpenID (here we are using Pibb). A site that supports OpenID will have a textbox for you to enter your OpenID. You enter your OpenID (mine is http://rchodava.myopenid.com, which I've entered) and click to sign in.
- The browser is now re-directed to a page where I enter the password for my OpenID. Since my OpenID is with myopenid.com, you will notice that the OpenID login page is somewhere on the myopenid.com server. So I enter my password and click to sign in again.
- Now I am brought back to Pibb, logged in using my OpenID!
Behind the scenes
Now that you have seen the typical sequence for logging in with OpenID, let's talk a bit about what's actually happening behind the scenes. First thing you should notice is that my OpenID, http://rchodava.myopenid.com, is actually a URL. This is a key point - with OpenID, you identify yourself with a URL just like you identify other resources on the web with a URL. Since your identity is a URL, you can actually go to it in a browser. Try it - go to my identity page: http://rchodava.myopenid.com. You'll see something like:

Why is an OpenID also being a URL such a big deal? Well, it is very important to what is going on behind the scenes. After I clicked sign in on Pibb in Step 1 above, the URL that Pibb redirected my browser to for the second step was my OpenID (http://rchodava.myopenid.com)! Of course, it added along a few special parameters when it redirected me. This is the same thing that would happen on any site that works with your OpenID.
At this point, let me talk about what myOpenID is. In OpenID jargon, it is an Identity Provider. Basically, it's a service which hosts my identity page, and keeps track of my password. When sites like Pibb (called a Consumer in OpenID jargon) redirect to my OpenID URL, the Identity Provider first asks me for my password. This is how I authenticate (prove its me) with my Identity Provider, and prove to it that I am the owner of http://rchodava.myopenid.com.
Once my Identity Provider has verified with me, it needs to in turn tell the Consumer (Pibb) that I own my OpenID. This is basically what happens between Steps 2 and 3 above when I am redirected from my Identity Provider (myOpenID) back to the Consumer (Pibb). Again, special parameters are passed along so that the Consumer knows I have been authenticated.
A bit of a correction and a bit on Delegation
I should make a bit of a correction to the description above because it is not exactly what happens. After I enter my OpenID in Pibb and sign on, it does not immediately redirect my browser to my OpenID URL. Instead, the Pibb server first connects to my OpenID URL to check a few things. It checks whether my identity page contains a tag like the following:
<link rel="openid.server" href="http://www.myopenid.com/server" />If it is present, this tag basically tells the Consumer (Pibb) that instead of redirecting the user to their identity page to login, redirect them to the URL given in that tag. In fact, this kind of tag is exactly what is present on my identity page at myOpenID. So, Pibb does not redirect me to http://rchodava.myopenid.com but rather to http://www.myopenid.com/server to do my login.
This is a good place to mention a second special tag that can be present on an identity page:
<link rel="openid.delegate"
href="http://someuser.somedomain.com/" />This tag, together with the other "openid.server" tag above allow you to do delegation of your OpenID. What does this mean? It means that you can take any web-page which you control and use it as your OpenID. For example, if I were to own a website like
http://ravi.chodavarapu.com, I can add the following two tags to the page at http://ravi.chodavarapu.com:<link rel="openid.server" href="http://www.myopenid.com/server" /><link rel="openid.delegate"
href="http://rchodava.myopenid.com" />After I have done this, I could now use
http://ravi.chodavarapu.com as my OpenID. That is, I could have typed that as my OpenID in Pibb. Once I clicked to sign in, the Pibb server would have seen those two tags, and known that it had to redirect me to http://www.myopenid.com/server and asked that server to log-in the user whose OpenID is http://rchodava.myopenid.com. The rest of the process works the same.Summing it up
Having gone through that long explanation, let me try to end by describing OpenID in the concise but loaded terms many other sites start with:
- OpenID is an identity system which lets you authenticate on the web
- Your OpenID is a URL, just like any other resource on the web
- OpenID is a single sign-on system (you sign on with your Identity Provider only)
- OpenID is open and decentralized. Pibb was just one example of a Consumer - anyone who implements a Consumer based on the specifications can support OpenID in their own right! Same with an Identity Provider - myOpenID is only one example of an OpenID provider. Anyone who implements the requirements of a provider as described in the specs can become a provider.
Where to go from here
The official site
I want my OpenID!
Note: In some of the screenshots above, the actual layout of the sites was changed a bit for brevity/bringing focus to the right areas.
Thursday, June 14, 2007
Getting through that damn proxy! (using Java)
If you are on a corporate network, you know how annoying it can be to try and get through the proxy. And if you are a developer, it can be even more frustrating because you can't even test your networked application until you first get through the proxy.
Sun has a great article on what is built in to Java to handle network proxies. This one covers the latest features available since Java 1.5 that let you control use of a proxy at a per-socket and per-connection level. Check it out first:
Java Networking and Proxies
Now, that article is pretty good but it doesn't cover how to do proxy authentication. Thankfully, there is another article from Sun which covers how to use java.net.Authenticator. This class, and its related classes, is how you will be doing authentication. How you go about doing authentication with these classes is covered here:
Http Authentication
But wait! There is one prominent piece missing from what's built in to Java for dealing with proxies. And this is that it cannot make regular TCP tunnels through a HTTP proxy (using a Proxy.Type.HTTP Proxy with a Socket won't work). This support is provided in HTTP & HTTP proxies through the CONNECT method. Before getting into how to handle this in Java, let me just give a quick overview of how the process works:
Now, this HTTP CONNECT method for establishing a tunnel through a HTTP proxy is typically used for establishing SSL connections through the proxy. This means the proxy is usually not going to monitor the actual traffic that goes out once the tunnel is established (if it were SSL traffic, it would be encrypted anyway). But the typical use of this method for SSL tunnels means that HTTP proxies are most likely going to have the following restriction: If you try to establish a tunnel through the proxy to a remote port other than 443 (the SSL port), the proxy is probably going to reject your request. That is, you couldn't use the CONNECT method to connect to somehost.com:3001 because 3001 is not the SSL port.
So, keeping all that in mind, do you have to write your own implementation for dealing with HTTP proxy tunneling? Nope - luckily, there is the Jakarta Commons HttpClient. It has a ProxyClient class which can set all this up for you and return the socket which is ready to have actual data sent over it (that is, after the HTTP OK response has been received from the proxy). For a quick start, check out the ProxyTunnelDemo sample.
Sun has a great article on what is built in to Java to handle network proxies. This one covers the latest features available since Java 1.5 that let you control use of a proxy at a per-socket and per-connection level. Check it out first:
Java Networking and Proxies
Now, that article is pretty good but it doesn't cover how to do proxy authentication. Thankfully, there is another article from Sun which covers how to use java.net.Authenticator. This class, and its related classes, is how you will be doing authentication. How you go about doing authentication with these classes is covered here:
Http Authentication
But wait! There is one prominent piece missing from what's built in to Java for dealing with proxies. And this is that it cannot make regular TCP tunnels through a HTTP proxy (using a Proxy.Type.HTTP Proxy with a Socket won't work). This support is provided in HTTP & HTTP proxies through the CONNECT method. Before getting into how to handle this in Java, let me just give a quick overview of how the process works:
- First, the client starts a socket and sends out a HTTP CONNECT request to the HTTP proxy. This request indicates what host and port we are actually interested in connecting to through the proxy.
- The proxy establishes a connection to the host and port we request.
- The proxy then sets up a tunnel which allows data we send to the proxy to pass through to the actual host, and vice-versa.
- Now, the proxy sends back a HTTP OK response on the socket we used to send it the request (if everything goes right - if not, you'll get a response with a HTTP error code).
- Right after the HTTP OK response, the same socket is now what we use to do all communications with the actual host we wanted to connect to. The proxy will tunnel data between us and that remote host.
Now, this HTTP CONNECT method for establishing a tunnel through a HTTP proxy is typically used for establishing SSL connections through the proxy. This means the proxy is usually not going to monitor the actual traffic that goes out once the tunnel is established (if it were SSL traffic, it would be encrypted anyway). But the typical use of this method for SSL tunnels means that HTTP proxies are most likely going to have the following restriction: If you try to establish a tunnel through the proxy to a remote port other than 443 (the SSL port), the proxy is probably going to reject your request. That is, you couldn't use the CONNECT method to connect to somehost.com:3001 because 3001 is not the SSL port.
So, keeping all that in mind, do you have to write your own implementation for dealing with HTTP proxy tunneling? Nope - luckily, there is the Jakarta Commons HttpClient. It has a ProxyClient class which can set all this up for you and return the socket which is ready to have actual data sent over it (that is, after the HTTP OK response has been received from the proxy). For a quick start, check out the ProxyTunnelDemo sample.
Wednesday, June 6, 2007
STAs: The Basics
That's an A, not a D. If you were looking for the D, I hope its not serious. But if you were looking for Single-Threaded Apartments, you're at the right place.
Note: this is really not about STAs in COM but just a way to think conceptually about objects, threads and STAs. You should really know what objects and threads are to enjoy this (actually, you should probably know them pretty well).
Anyway, let's get right to it.
Here's an object:

Now, nothing special about that. We've got an object that's in some circular state. But, how do we interact with it? Well, one way we developers typically do that is by passing messages:

And lo and behold, our object responded to our message with a message of its own! Also notice, it changed its state to some new lopsided-mess state. But wait... that's not exactly right is it? An object is really just inanimate data. The real picture is something more like this:

Who's the little dude in there? Well, for this discussion, that little guy is a thread. So, really, a thread is the one that accepts a message, and based on what that message is, he does some work and changes the object. Here, he's gone in and changed it from a circular state to the new lopsided-mess state. But wait, did he really go straight from circular state to lopsided-mess state? Nah... there was actually an intermediate step:

So, our thread first changed the object from circular state to the circle-with-beak state, and then finally changed that to the lopsided-mess state. Simple enough right? Let's now experiment with adding a second thread which can go in there and do some work of its own:

OK, so, let's look at what happened. Our black thread accepted the message and went in and started work. He changed the object from circular state to circle-with-beak state. But here's where we ran into some trouble. The lazy bum suddenly decided to go off and sleep. That's when blue thread accepted another message for the object, and started working on it. By the time black thread got up, blue thread had brought the object into balls-with-beak state and left. So, what's going to happen now? Have a look:

The left side shows what black thread should have changed the object to, now that blue thread has put it in the balls-with-beak state. But this means that black thread must have actually noticed the new state of the object once he woke up. What is more likely going to happen though is what is on the right side. That is, he will wake up and will go on thinking that the object is still in the circle-with-beak state it was in before he fell asleep. Wtf?, you say? (Well, if you don't really understand the metaphor, you should Google multi-threading and thread synchronization and come back later.)
So, thinking the object is in the circle-with-beak state (when it is actually in the balls-with-beak state), he will change it to lopsided-mess state. He should have really changed it to upside-down-shoe state like shown on the left. What we have left with is a classic thread synchronization problem. And of course, there are several ways to address the problem.
Let's talk about one of those ways: single-threaded apartments. So, here's an object in a single-threaded apartment:

That's right! It's an apartment for the object! Now, you're probably thinking WTF?!? again at this point. But, let's see how this plays out. We will begin with how the objects living in single-threaded apartments receive messages now:

So messages enter the apartment for the object (through a mail slot?) and wait there till they are processed. Of course, our threads are the ones who are going to process them:

Our thread comes in to the apartment, accepts the message waiting for the object, and starts work immediately. But wait:

Shit, its sleepy thread. But look what happens when blue thread comes along:

He can't get in! Why? Well, remember: This is a Single-Threaded apartment. The policies state that when a thread goes in, he locks the door after him from the inside. No other thread can get in while he's in there with the object. Nice, eh?
What about messages for the object? Well:

If a new message comes in, it gets placed in the apartment and waits for processing. It doesn't matter if there is a thread in there, or if the thread inside is sleeping. The messages just pile up.
We're almost done. Let's follow through and observe after the thread wakes up:

Black thread finishes work, bringing the object to a new state, and leaves the apartment. Now that the single-threaded apartment is free, blue thread can come in and do some work. But remember, while blue thread is inside, no other thread can enter.
We ensure that only one thread is ever working with the object at a time.
Note: this is really not about STAs in COM but just a way to think conceptually about objects, threads and STAs. You should really know what objects and threads are to enjoy this (actually, you should probably know them pretty well).
Anyway, let's get right to it.
Here's an object:

Now, nothing special about that. We've got an object that's in some circular state. But, how do we interact with it? Well, one way we developers typically do that is by passing messages:

And lo and behold, our object responded to our message with a message of its own! Also notice, it changed its state to some new lopsided-mess state. But wait... that's not exactly right is it? An object is really just inanimate data. The real picture is something more like this:

Who's the little dude in there? Well, for this discussion, that little guy is a thread. So, really, a thread is the one that accepts a message, and based on what that message is, he does some work and changes the object. Here, he's gone in and changed it from a circular state to the new lopsided-mess state. But wait, did he really go straight from circular state to lopsided-mess state? Nah... there was actually an intermediate step:

So, our thread first changed the object from circular state to the circle-with-beak state, and then finally changed that to the lopsided-mess state. Simple enough right? Let's now experiment with adding a second thread which can go in there and do some work of its own:

OK, so, let's look at what happened. Our black thread accepted the message and went in and started work. He changed the object from circular state to circle-with-beak state. But here's where we ran into some trouble. The lazy bum suddenly decided to go off and sleep. That's when blue thread accepted another message for the object, and started working on it. By the time black thread got up, blue thread had brought the object into balls-with-beak state and left. So, what's going to happen now? Have a look:

The left side shows what black thread should have changed the object to, now that blue thread has put it in the balls-with-beak state. But this means that black thread must have actually noticed the new state of the object once he woke up. What is more likely going to happen though is what is on the right side. That is, he will wake up and will go on thinking that the object is still in the circle-with-beak state it was in before he fell asleep. Wtf?, you say? (Well, if you don't really understand the metaphor, you should Google multi-threading and thread synchronization and come back later.)
So, thinking the object is in the circle-with-beak state (when it is actually in the balls-with-beak state), he will change it to lopsided-mess state. He should have really changed it to upside-down-shoe state like shown on the left. What we have left with is a classic thread synchronization problem. And of course, there are several ways to address the problem.
Let's talk about one of those ways: single-threaded apartments. So, here's an object in a single-threaded apartment:

That's right! It's an apartment for the object! Now, you're probably thinking WTF?!? again at this point. But, let's see how this plays out. We will begin with how the objects living in single-threaded apartments receive messages now:

So messages enter the apartment for the object (through a mail slot?) and wait there till they are processed. Of course, our threads are the ones who are going to process them:

Our thread comes in to the apartment, accepts the message waiting for the object, and starts work immediately. But wait:

Shit, its sleepy thread. But look what happens when blue thread comes along:

He can't get in! Why? Well, remember: This is a Single-Threaded apartment. The policies state that when a thread goes in, he locks the door after him from the inside. No other thread can get in while he's in there with the object. Nice, eh?
What about messages for the object? Well:

If a new message comes in, it gets placed in the apartment and waits for processing. It doesn't matter if there is a thread in there, or if the thread inside is sleeping. The messages just pile up.
We're almost done. Let's follow through and observe after the thread wakes up:

Black thread finishes work, bringing the object to a new state, and leaves the apartment. Now that the single-threaded apartment is free, blue thread can come in and do some work. But remember, while blue thread is inside, no other thread can enter.
We ensure that only one thread is ever working with the object at a time.
Subscribe to:
Posts (Atom)