Have you ever needed the ability for an ImageButton to act as an <input type="Image" /> with the javascript most of the time, but under certain conditions fire a server-side event? Well before you start writing custom postback code and putting it into your javascript, consider this.
If you have an OnClientClick --or onclick on the html rendering-- specified for the <asp:ImageButton> element as well as an OnClick event handler, the server-side handler will only be called if your javascript method returns true or void. If you have your OnClientClick handler return false, the server-side event will not be called. This will allow you the ability to make your ImageButton behave client-side until you decide it is necessary to do other wise.
For example:
<div style="float: left; text-align: center;">
<h4>Visitor Stations</h4>
<asp:DataList ID="dlVisitorStations" runat="server" RepeatColumns="6" CellSpacing="5"
OnSelectedIndexChanged="dlvisitorStations_SelectedIndexChanged"
DataKeyField="StationID" OnItemDataBound="dlVisitorStations_ItemDataBound" RepeatDirection="Horizontal">
<ItemTemplate>
<asp:ImageButton ID="btnVisitorStation" runat="server" ImageUrl="~/images/status/available.png" OnClick="btnVisitorStation_click" /><br />
<asp:Label ID="lblStationID" runat="server" Text='<%# Eval("StationID") %>' ></asp:Label><br />
<asp:Label ID="lblStationName" runat="server" Text='<%# Eval("StationName") %>' ></asp:Label><br />
<asp:Image ID="imgConnectArrow" Visible="false" ImageUrl="~/Images/greenConnectionArrow.gif"
Width="40px" runat="server" />
<asp:Label ID="lblInmateStation" Text='<%# Eval("ConnectedStation") %>' Visible="false" runat="server"></asp:Label>
</ItemTemplate>
<ItemStyle Width="75px"/>
</asp:DataList>
</div>
Pretty self explanatory here. We have a DataList that has an ImageButton inside it amongst other things. Also notice that I have a server-side handler specified.
Here it is in the code-behind:
//This event handler will only be called if the button is in the connected or paused state.
//see the javascript btnVisitorStationClick for more information
protected void btnVisitorStation_click(object sender, ImageClickEventArgs e)
{
//irrelevant to post. This code gets called.
}
Also in the ItemDatabound I do this:
Image btnVisitorStation = (Image)e.Item.FindControl("btnVisitorStation");
btnVisitorStation.Attributes.Add("onclick", String.Format("return btnVisitorStationClick('{0}', '{1}')", DataBinder.Eval(e.Item.DataItem, "StationID").ToString(), btnVisitorStation.ClientID));
Notice, that you could also use the OnClientClick, if you don't need to worry with the databinding. Also, see that there is a return statement in the newly generated onclick javascript handler. This is what will do the magic.
Ok, here is the javascript:
function btnVisitorStationClick(stationID, img) {
var imgStation = document.getElementById(img);
var hfVisitorStation = document.getElementById('<%= hfSelectedVisitorStation.ClientID %>');
var inmateStation = document.getElementById('<%= hfSelectedInmateStation.ClientID %>').value;
var hfVisitorButton = document.getElementById('<%= hfSelectedVisitorButton.ClientID %>');
if (imgStation.src.indexOf('offline') == -1 && imgStation.src.indexOf('connected') == -1 && imgStation.src.indexOf('paused') == -1) {
imgStation.src = 'images/status/selected.png';
if (hfVisitorStation.value != '') {
var stationToDeselect = document.getElementById(hfVisitorButton.value);
stationToDeselect.src = 'images/status/available.png';
}
if (hfVisitorStation.value != stationID)
hfVisitorStation.value = stationID;
else
hfVisitorStation.value = '';
hfVisitorButton.value = imgStation.id;
var monitorBtn = document.getElementById('btnMonitor');
var startButton = document.getElementById('<%= btnRestart.ClientID %>');
if (inmateStation != '' && hfVisitorStation.value != '') {
monitorBtn.src = 'images/controls/monitor.png';
startButton.src = 'images/controls/play.png';
monitorBtn.disabled = false;
startButton.disabled = false;
}
else {
monitorBtn.src = 'images/controls/monitor_disabled.png';
startButton.src = 'images/controls/play_disabled.png';
monitorBtn.disabled = true;
startButton.disabled = true;
}
return false;
}
else if (imgStation.src.indexOf('connected') != -1 || imgStation.src.indexOf('paused') != -1) {
return true;
}
return false;
}
As you can see, most of this code doesn't need a post-back. However, I needed to call a postback if the status of the button was connected or paused, though most of the time it just needed to process client-side.
Happy coding.
Ever have that moment when you design or discover something cool and think to yourself, "Damn! I wish I had someone I could share this with to help them out?" Well, that is what this blog is about.
Wednesday, July 20, 2011
Monday, July 18, 2011
CS 101 in plain English: Abstraction Explained
This is the first post among many to come. I plan on writing several posts on computer science concepts using non-computer science language. Do you know that moment when you are working in the yard or talking to your 17 month old son, and you realize that you were just provided with an exceptional way to explain something that is normally somewhat complex? No? Well it happens to me all of the time. Here are a couple right off of the top of my head. Bad pointer aliasing can be explained using pronouns and antecedents--or the lack thereof--, when and when not to use multiple threads can be explained with gardening, and how to use abstraction in software design can be explained with a conversation you had with your wife about the culture's overuse of the word "thing". OK, maybe that wasn't off the top of my head. Anyways, this post is about the last of the three. Unfortunately for someone who doesn't like to read my philosophical musings in the process of my getting to the point, well ... you get the point. So here we go.
Lemma 1: The fundamental function of language is to name things.
There is a reason why the Judeo-Christian mythology begins with the fundamental role of mankind's gift of language being to name the animals. Imagine the usefulness of the ability to speak without names. You are back at the sorority party. Speaking may as well be hissing or some other cleaver-given-the-metaphor sound that all other creatures can only make one of. Imagine trying to communicate to your wife, "Don't eat that apple or we will both die." In this simple sentence we have named that delicious, bright, red-colored fruit that originated somewhere in Kazakhstan which was almost wiped out by the American temperance movement because it made excellent cider. We also named many other things such as the act of eating and death, but this will be sufficient to prove my point and to introduce Lemma 2.
Lemma 2: Naming things is the heart of abstraction.
When Adam should have been using the word apple in instructing his wife on how not to royally screw all of humanity, he would have been using a single word to describe all of the things that we know about apples. The word "apple" is shorthand for that sweet fruit that grows on a tree, can't be planted from seed or it will end up being completely different from the fruit that produced it, and was used to plunge all of humanity into wars, death, and calamity. But of course, the previous sentence only makes sense if you understand the definition of each of the terms used in that sentence and then the meaning of the terms in each of the sentences used to describe each of the terms and so on. You see, you can't communicate without names to point to collections and groups of ideas. In other words, the fundamental function of language is to name things. Q.E.D.
Also, notice that a name is a pointer to collections of ideas. In other words, you name something because you have found an idea or collection of ideas that need to be generalized for communication sake. Using this name allows us to deal with a complex idea simply without having to say or think about its complexity. We can throw around an idea with a simple word instead of a thousand. But there's more. We can actually do really cool things with these complex ideas once we start using names. We can link multiple complex ideas with other complex ideas and form even more complex ideas giving them names as well. In fact, this is exactly what we did with the name "Apple". "Apple" is the combination of other ideas represented by the names "fruit", "core", "red", and so on. This is what abstraction is all about: greater and greater generalization. This is what makes language work. Abstraction only works because of our ability to name things. Or, to put it another way, naming things is the heart of abstraction. Q.E.D.
So, back to the name "thing". "Thing" is the ultimate abstraction. "Thing" includes all other names which brings on another lemma.
Lemma 3: The more and more abstract the idea a name represents, the less meaning that name possesses.
This principle is sort of like the one mentioned in the video above. Here is my adaptation of this brilliant Disney indoctrination. When a name means everything, it means nothing at all. So, when I am riding in the car with my wife, and she says, "Watch out for that thing in the road!" I will most likely not watch out for the cat that I caught sleeping on top of my freshly washed and waxed 1994 bronco which is now giving birth to kittens in the middle of the road--yeah right, like I would wash my bronco. Or when I say, "Hey babe, bring me one of those cold things out of the fridge", I shouldn't be surprised when she chunks a rotten tomato at me (for multiple reasons). Q.E.D. OK, so I am tired of the whole Q.E.D thing. I'm going to stop doing that. It is a name which basically points to the idea that I have amply demonstrated the point that I was trying to make.
So when is the word "thing" actually useful? Well, observe my wording for Lemma 1 and Lemma 2. Those sentences actually would lack their ability to communicate so generally if I didn't have "thing" a.k.a super abstraction. That is the actual cool thing about abstractions. You can use them to manipulate multiple complex ideas simultaneously. You simply must be able to apply the idea back down to lower abstractions. This is usually what people mean by "Bring that down to my level" or "That was over my head": they mean that you need to apply that general idea's properties down to lower abstractions.
This is a "representational" painting. In other words, the artist tries very hard to represent --or for our purposes model-- something from the real world onto the canvas. Let's call this a real, concrete, or non-abstract painting.
Of course, right away you have a problem. Each variety of tree will grow at different rates, multiply at different rates, respond to droughts differently, and some will even produce geriatric, mutant, ninja squirrels which will take out other competing tree varieties. It would be very easy, without a well designed abstraction, for this program to get out of hand, unreadable, and unmaintainable quickly. So here is how I would approach the problem, and here is the catch: you could design your entire program in plain English before writing the first stitch of code.
"The beginning of wisdom is the ability to call things by their right names" -- ConfuciousHave you ever noticed that "thing" is one of the most useless words in the majority of English sentences? No? Well it is. And if you don't believe me, you should crash a sorority party or go to your average evangelical church, and try and make sense out of anything that is said. You would leave the sorority party with a firm conviction that thingies of a certain thingy makes someone's thingy look big . Or you would learn that someone's thingy looks smaller than a really small thingy, and that pissed off some girl in their thingy. Likewise, you would leave the church with the firm assurance if you believe some thing then that thing will magically make your life better. Anyhow, at the end of the day, we tend to say that we disdain such statements because they are "abstract". Well, let me add a slight correction to that critique. The problem is not that these statements are "abstract", the problem is that the statements are "poor abstractions". Allow me to explain.
Lemma 1: The fundamental function of language is to name things.
There is a reason why the Judeo-Christian mythology begins with the fundamental role of mankind's gift of language being to name the animals. Imagine the usefulness of the ability to speak without names. You are back at the sorority party. Speaking may as well be hissing or some other cleaver-given-the-metaphor sound that all other creatures can only make one of. Imagine trying to communicate to your wife, "Don't eat that apple or we will both die." In this simple sentence we have named that delicious, bright, red-colored fruit that originated somewhere in Kazakhstan which was almost wiped out by the American temperance movement because it made excellent cider. We also named many other things such as the act of eating and death, but this will be sufficient to prove my point and to introduce Lemma 2.
Lemma 2: Naming things is the heart of abstraction.
When Adam should have been using the word apple in instructing his wife on how not to royally screw all of humanity, he would have been using a single word to describe all of the things that we know about apples. The word "apple" is shorthand for that sweet fruit that grows on a tree, can't be planted from seed or it will end up being completely different from the fruit that produced it, and was used to plunge all of humanity into wars, death, and calamity. But of course, the previous sentence only makes sense if you understand the definition of each of the terms used in that sentence and then the meaning of the terms in each of the sentences used to describe each of the terms and so on. You see, you can't communicate without names to point to collections and groups of ideas. In other words, the fundamental function of language is to name things. Q.E.D.
Also, notice that a name is a pointer to collections of ideas. In other words, you name something because you have found an idea or collection of ideas that need to be generalized for communication sake. Using this name allows us to deal with a complex idea simply without having to say or think about its complexity. We can throw around an idea with a simple word instead of a thousand. But there's more. We can actually do really cool things with these complex ideas once we start using names. We can link multiple complex ideas with other complex ideas and form even more complex ideas giving them names as well. In fact, this is exactly what we did with the name "Apple". "Apple" is the combination of other ideas represented by the names "fruit", "core", "red", and so on. This is what abstraction is all about: greater and greater generalization. This is what makes language work. Abstraction only works because of our ability to name things. Or, to put it another way, naming things is the heart of abstraction. Q.E.D.
So, back to the name "thing". "Thing" is the ultimate abstraction. "Thing" includes all other names which brings on another lemma.
Lemma 3: The more and more abstract the idea a name represents, the less meaning that name possesses.
This principle is sort of like the one mentioned in the video above. Here is my adaptation of this brilliant Disney indoctrination. When a name means everything, it means nothing at all. So, when I am riding in the car with my wife, and she says, "Watch out for that thing in the road!" I will most likely not watch out for the cat that I caught sleeping on top of my freshly washed and waxed 1994 bronco which is now giving birth to kittens in the middle of the road--yeah right, like I would wash my bronco. Or when I say, "Hey babe, bring me one of those cold things out of the fridge", I shouldn't be surprised when she chunks a rotten tomato at me (for multiple reasons). Q.E.D. OK, so I am tired of the whole Q.E.D thing. I'm going to stop doing that. It is a name which basically points to the idea that I have amply demonstrated the point that I was trying to make.
So when is the word "thing" actually useful? Well, observe my wording for Lemma 1 and Lemma 2. Those sentences actually would lack their ability to communicate so generally if I didn't have "thing" a.k.a super abstraction. That is the actual cool thing about abstractions. You can use them to manipulate multiple complex ideas simultaneously. You simply must be able to apply the idea back down to lower abstractions. This is usually what people mean by "Bring that down to my level" or "That was over my head": they mean that you need to apply that general idea's properties down to lower abstractions.
A Case Study on Abstraction: Picasso
The artwork of Pablo Picasso is an excellent example on how abstraction is performed.Olga Picasso - 1923
Three Musicians
Notice that in this painting, Picasso has begun to see real figures in terms of more general and basics shapes. He has grouped colors, curves, and shapes into basic groupings and has diminished the individuality of each individual pixel of the painting into more generalized shapes. So, I like to suppose that his dialog went something like this, "Hmm, the shape of that face is basically rectangular, the shape of that hat is basically triangular." As a result, he diminished the nitty-gritty details on the real representation in order to abstract the particulars into greater and greater generalities. This is what abstraction is fundamentally about: either diminishing particulars or naming them so that we can forget about them for the sake of working with greater and greater complexities more easily.
Guernica
Now here is where abstraction becomes more useful to Picasso. How do you show the absolute horror of a Nazi Blitzkrieg on a defenseless Spanish town? Picasso chose to do so by taking his already abstract rendering of shapes and to distort them. I suppose, that for him this communicated the unreal or anti-beauty of the situation. This is part of the usefulness of abstraction: it enables us to perform operations--such as distortions-- upon representations of reality which would not be possible if we were using concrete representations.
A Case Study on Poor Abstraction: Pollock
Eyes in the Heat--Jackson Pollock
This painting is a classic example of pure dog shit. Though this painting is considered "abstract" by genre, it is a very poor abstraction. This is the art equivalent of the incorrect usage of "thing". It has no actual connection to reality, so there is actually nothing being abstracted to begin with. "Eyes in the Heat" is an example of a useless abstraction. I don't care what Peggy Guggenheim says. This is simply abstraction for the sake of abstraction. In order for an abstraction to be useful, it must be actual generalizations of the real world. Even then, in order for it to communicate in full or in part, the actual reality being represented must be communicated in part or in full.
Case Study: Modeling Trees
(Warning I am about to gradually drift back into CS specific stuff here)
Suppose you just got a new job working for the U.S. forestry service. Your task is to write a program which will simulate all of the tree growth of the Sipsey Wilderness in Bankhead National Forest. By the way, if you haven't been to the Sipsey Wilderness, you need to go. It is the closest thing to a virgin forest that I have found in all of Alabama.
Of course, right away you have a problem. Each variety of tree will grow at different rates, multiply at different rates, respond to droughts differently, and some will even produce geriatric, mutant, ninja squirrels which will take out other competing tree varieties. It would be very easy, without a well designed abstraction, for this program to get out of hand, unreadable, and unmaintainable quickly. So here is how I would approach the problem, and here is the catch: you could design your entire program in plain English before writing the first stitch of code.
#1. I would write down a list of each variety of tree in this forest. So for example,
Pin Oak,
Water Oak,
Cypress,
Cedar,
Pine,
Geriatric Ninja Producing White Oak.
#2. Write down what each tree has in common.
They all grow,
The all have leaves (yeah, yeah, I know we will deal with that in a minute),
They all multiply,
They all perform photosynthesis.
#3. Write down general ways that the trees can be different
Some have needles while some have leaves (see, I told you I would get to it),
Some are angiosperms while others are gymnosperms,
#4. (Possibly number 1) Write down the aspects of the trees that you need to model.
Everything relevant to growth.
Everything relevant to reproduction.
So, as a result we end up with a lot of ways to form our abstraction tree (i.e. your inheritance hierarchy).
Every concrete unit (the element of smallest reduction) is a tree.
However a tree could be an angiosperm or a gymnosperm.
Also, some trees have needles while others don't.
We have three angiosperms, the Pin Oak, the Water Oak, and the ninja producing White Oak.
We have three gymnosperms, the Cypress, the Cedar, and the Pine.
Trees with needles (conifers): the Cypress, the Cedar, and the Pine.
Trees with leaves: The Pin Oak, the Water Oak, and the ninja producing White Oak.
So, as a result we get something like.
Tree
|
/\
/ \
Gymnosperm Angiosperm
| |
| |
Conifer Oak Trees
/ | \ / | \
/ | \ / | \
Cypress Cedar Pine Pin Water Ninja_Variety
OK, so what is the usefulness of this diagram? Think of it this way. Suppose you are walking through a forest doing some research and you come across the Geriatric Mutant Ninja Squirrel producing Oak tree. After defeating four squirrels who attacked you upon approach, you need to talk about that particular tree. However, the name is really long, and each time you say the name, Geriatric Mutant Ninja Squirrel producing Oak tree, another squirrel attacks--and that just isn't cool. So, you simply call the thing, a tree. You can talk about that tree (using the generic name of tree) growing and reproducing even though each tree does each of those tasks differently. So for instance, you can say that tree reproduces which will refer to the angiosperm style of reproducing as opposed to the gymnosperm style of reproducing. Also, this particular type of tree has mutant squirrels that fend off predators of its acorns. All of this is implicitly understood when you say that that particular tree reproduces.
Meanwhile, you get chased off by another batch of squirrels, and you walk over to a majestic pine tree. You call this object a tree and talk about it reproducing. Except for this time, you mean an entirely different process. A pine tree is a gymnosperm which means that it doesn't produce any fruit-like structures like nuts. It produces its offspring in an entirely different way. However, so long as your usage of the term "tree" is directed at that particular pine tree, when you talk about it reproducing you are implying everything specific to that pine tree's reproductive system.
This is the usefulness of abstraction! If you understand this principle then you understand everything you need to know to use inheritance, dynamic binding, and even type casting.
So, to show it in pseudo-code (for our friends here who aren't programmers):
Tree t references a tree that is also a pine tree.
t ---- reproduce references the reproduce function of the pine tree.
Tree o references a tree that is also an Pin Oak tree.
o ----- reproduce references the reproduce function of the Pin Oak tree.
Or for my C++ understanding friends:
Tree* t = new PineTree();
t->Reproduce(); //this will call PineTree::Reproduce if it is defined, not Tree::Reproduce
Tree* o = new PinOakTree();
o->Reproduce(); //this will call PinOakTree::Reproduce if it is defined, not Tree::Reproduce
This means that your main program can be completely ignorant of how the particular tree reproduces. It can just focus on counting the years, raining, and sun-shining. The individual implementations will handle the rest. Also, this means that should you ever need to add a new tree to your model, then you just have to plug it into the abstraction. The main application will need little to no modification.
This is what all programming languages do. Think about an int in a c program. An int is usually 4 bytes strung together. Some very kind man, I suppose Dennis Ritchie, decided that programmers did not need to worry every time they wanted to add two numbers together about allocating 4 bytes of memory, calculating the binary value of the 4 bytes together, performing binary addition, and storing the new value back into the 4 bytes of memory. An int is an abstraction because it generalizes this operation. Of course this is different than inheritance, but it is a similar idea. You always want to hide complexity from your main application, especially when you have other programmers on the project.
Conclusion
My goal is not to teach the syntax for implementing such abstractions--merely to try and teach how to begin thinking in the abstract. Ultimately see it this way. When you name things, you are grouping ideas together, and are therefore abstracting. Learn to do this in each of your software projects and you will find your code easier and easier to write, organize, and maintain. Think to yourself, "Hmm... can this code be generalized any?" "Is there some name I can apply to this section of code?" Eventually you will find yourself writing better and better code.
However, be sure to avoid abstraction merely for the sake of abstraction. Never create complexity, only hide it. Remember, for an abstraction to be useful, it must be derived from something that is a concrete representation of something real.
Thursday, May 19, 2011
Create a Paging Button for each slide in an ASP.NET AjaxControlToolkit SlideShowExtender
I had been searching for days for a way to have pretty little buttons for each slide in my slideshow extender.
Here is the always sexy nivo slider. Notice that you can have a bullet for each slide. Also, it would be cool if you could extend this guy to show tiles of the slides instead of just bullets.
Here is what every other tutorial for the SlideShowExtender for the ASP.NET AjaxControlToolkit produced:
eeek! Try and sell that shit to a customer and see what happens.
So why not just use JQuery you might ask?
1. I don't believe in rewriting code that is already well designed. That is like wiping my ass with hard earned $100 bills.
2. The SlideShowExtender has some really cool functionality that I haven't found in the JQuery controls.
Regardless, here is how to extend the control to use paging buttons that you can easily customize to look as you please with CSS. I didn't do any pretty stuff here-- just the secret to making it work.
I am assuming that you already have your slideshow extender on the page and working as all the other 5000 tutorials on the subject show you how to do. Here is the key addition:
Here is the always sexy nivo slider. Notice that you can have a bullet for each slide. Also, it would be cool if you could extend this guy to show tiles of the slides instead of just bullets.
Here is what every other tutorial for the SlideShowExtender for the ASP.NET AjaxControlToolkit produced:
eeek! Try and sell that shit to a customer and see what happens.
So why not just use JQuery you might ask?
1. I don't believe in rewriting code that is already well designed. That is like wiping my ass with hard earned $100 bills.
2. The SlideShowExtender has some really cool functionality that I haven't found in the JQuery controls.
Regardless, here is how to extend the control to use paging buttons that you can easily customize to look as you please with CSS. I didn't do any pretty stuff here-- just the secret to making it work.
I am assuming that you already have your slideshow extender on the page and working as all the other 5000 tutorials on the subject show you how to do. Here is the key addition:
<div style="text-align: center; "> <div class="SlideShowMainTitle"> <asp:Label ID="lblSlideTitle" runat="server"></asp:Label> </div> <div class="SlideShowImage"> <asp:Image ID="imgSlide" runat="server" /> </div> <div class="SlideShowSubTitle"> <asp:Label ID="lblSlideDescription" runat="server"></asp:Label> <br /> <asp:Repeater ID="rpPagingButtons" runat="server" OnItemDataBound="rpPagingButtons_OnItemDataBound"> <ItemTemplate> <a ID="lbtnPager" runat="server"></a> </ItemTemplate> </asp:Repeater> </div> <asp:SlideShowExtender ID="slExtender" runat="server" AutoPlay="true" Loop="true" PlayInterval="3000" TargetControlID="imgSlide" ImageTitleLabelID="lblSlideTitle" ImageDescriptionLabelID="lblSlideDescription" SlideShowServiceMethod="GetSlides" SlideShowServicePath="~/WebServices/SlideShowService.asmx"> </asp:SlideShowExtender> </div>
Then in the code behind:
protected void rpPagingButtons_OnItemDataBound(object sender, RepeaterItemEventArgs e) { if (e.Item.ItemIndex > -1) { HtmlAnchor lbtnPageLink = (HtmlAnchor)e.Item.FindControl("lbtnPager"); if (lbtnPageLink != null) { string behaviorID = slExtender.BehaviorID; lbtnPageLink.HRef = "javascript:$find('" + behaviorID + "')._currentIndex= " + e.Item.ItemIndex.ToString() + ";" + " $find('" + behaviorID + "').setCurrentImage();"; lbtnPageLink.InnerHtml = (e.Item.ItemIndex + 1).ToString(); } } }The key is in the href for the anchor tag. You will need to bind some data to your repeater. The dataset needs to have a row for each image in your slide show. I am assuming that you already are a decent programmer and know how to customize this to your own needs. Basically, set your bullet image in the css for the anchor tag in your repeater. You can do all of your formatting there. Now go make daddy some bloody money.
Thursday, May 5, 2011
Clearing Up Some Space on Your Main Partition: Coping with a love for the Intel SSD, but a programmer's budget)
I recently built the best machine that I could buy parts for. This thing had everything: the ASUS P6T6 rev with an Intel I7 extreme, the NVidia three-way-sli (well, you get the picture). However, when it came down to the hard drive decision, a co-worker of mine convinced me that I just had to buy the new Intel SSD-- so I did. The problem? While Windows 7 booted in under 6 seconds--and Fedora in under 3--, I had already spent most of my budget on the "important" stuff. Thus, I bought an 80GB drive for Windows, a 40GB drive for Linux, and an eSATA 1TB external drive for all of my "non-essential" data: which is cheaper than buying a single 160GB Intel SSD. I don't know if you have priced the Intel SSDs lately, but they are EXPENSIVE! So, I think to myself, "This should be fine, I'll just store all of my music, movies, and such on the external drive." This would have been fine if the data that took up the most space was music, movies, and such. Then reality hit.
Visual Studio and all of its dependencies > 7 GB
Microsoft office and all of its dependencies > 2GB
and so on.
As a developer, I have all of these tools that I have acquired over the years, and they add up quickly.
I failed to mention that I have one other secret love. I like to, on occasion, waste my time on really fun and cool video games--I mean, we can't let that three-way-sli go to waste can we? Here is the biggest problem:
Call of Duty Black Ops (looks amazing on this machine compared to X-Box 360 b.t.w) > 12GB
Empire Total War > 16 GB
This left me with no space. Dang it! So what do you do, when you have enough friends to party like its 1999, but nowhere to put them? You store them somewhere else, and project them to where you are as holograms--except for the women, they should actually be there. Anyhow, back to the point. Since Microsoft has finally figured out that all of the *NIX s are amazing--all of them except MAC at least :)--, they have finally begun copying them. In Vista, Server 2008, and Windows 7, Microsoft finally gave Windows users an invaluable tool: The Symbolic Link. For those of you who are not familiar with UNIX derivatives, a symbolic link is a file or a directory that is stored in one place but is linked to another location. This file or directory can then be accessed as if it physically resided at the target of the link. Why is this so helpful? Well, since many software programs on Windows will not allow you to install to a location outside of the partition that the OS resides on, you previously had no choice but to install to your precious SSD space. But now .....
Move the files that are space hogs over to a folder on your external hard drive-- say F:\ProgramFiles\Steam. Then run the following as an administrator from the command line:
mklink /D "C:\Program Files (x86)\Steam" F:\ProgramFiles\Steam
Voila! The OS won't know the difference, and you get your space back for the things you get paid for. Let's just call this the tasks where it actually matters how fast the data can be accessed. By the way, I can't tell the difference in speed when I run these programs from a symbolic link.
Visual Studio and all of its dependencies > 7 GB
Microsoft office and all of its dependencies > 2GB
and so on.
As a developer, I have all of these tools that I have acquired over the years, and they add up quickly.
I failed to mention that I have one other secret love. I like to, on occasion, waste my time on really fun and cool video games--I mean, we can't let that three-way-sli go to waste can we? Here is the biggest problem:
Call of Duty Black Ops (looks amazing on this machine compared to X-Box 360 b.t.w) > 12GB
Empire Total War > 16 GB
This left me with no space. Dang it! So what do you do, when you have enough friends to party like its 1999, but nowhere to put them? You store them somewhere else, and project them to where you are as holograms--except for the women, they should actually be there. Anyhow, back to the point. Since Microsoft has finally figured out that all of the *NIX s are amazing--all of them except MAC at least :)--, they have finally begun copying them. In Vista, Server 2008, and Windows 7, Microsoft finally gave Windows users an invaluable tool: The Symbolic Link. For those of you who are not familiar with UNIX derivatives, a symbolic link is a file or a directory that is stored in one place but is linked to another location. This file or directory can then be accessed as if it physically resided at the target of the link. Why is this so helpful? Well, since many software programs on Windows will not allow you to install to a location outside of the partition that the OS resides on, you previously had no choice but to install to your precious SSD space. But now .....
Move the files that are space hogs over to a folder on your external hard drive-- say F:\ProgramFiles\Steam. Then run the following as an administrator from the command line:
mklink /D "C:\Program Files (x86)\Steam" F:\ProgramFiles\Steam
Voila! The OS won't know the difference, and you get your space back for the things you get paid for. Let's just call this the tasks where it actually matters how fast the data can be accessed. By the way, I can't tell the difference in speed when I run these programs from a symbolic link.
Saturday, April 16, 2011
Mercurial Tutorial by Joel Spolsky
For those of you fed up with spending an hour helping one of your programmers with a botched subversion merge,-- because you told them that if they change the tree they need to "add", "delete", or "move", but they didn't and so now the time you could be spending watching old Southpark episodes while eating Chinese food is being taken up by someone complaining about how they hate having to use version control-- this post by Joel Spolsky on switching to mercurial would be a good read. I will be playing with this tonight and possibly begin the move next week sometime.
http://hginit.com/
http://hginit.com/
Friday, April 15, 2011
Treating a Thread as a Service
For those of you who have had to design software with many different logical components, you may have found it difficult to manage these components. Will they be in different applications, services, or daemons? Will they be in different threads or processes? The former may be a nightmare to maintain and the latter can be a nightmare to keep organized and bug free. I am going to propose a solution that is multi-threaded and well organized. So, here we go.
Voila! You have a reusable Threading Class. This is a very simple class. First, we encapsulate a System.Threading.Thread:
Next, we have an abstract (the same as virtual void method() = 0; in your c++ header) method that all subclasses must implement.
Finally, in the constructor, we just tell our thread to use the Main method.
Here, we just wrote a normal class (in this case, our own signaling protocol), except for we give it its own Main loop by overriding the Main method. This allows us to write virtually any component that we need to run on its own thread. All we had to do was override the Main Method. Then, to use this component, you would just initialize this class in your application at whatever scope you want it to run on. However, make sure you end the thread when it goes out of scope or it will keep going; thankfully, C# still has destructors. This allows you to have as many different services running inside your application as you would like, and each will run on its own thread.
If you have ever tried to write a multi-threaded application, you may have found that object-oriented is a difficult goal to achieve. This is largely because you usually have to use static methods and such to spawn your threads. I wasn't too surprised when I discovered this with C/C++ and pthreads on Unix systems, but I was absolutely shocked when I tried to do this in C# using the System.Threading namespace. However, inspiration struck when I was working on an application using the ptlib library in Linux. They have this wonderful class called PThread which you can inherit from: overriding the virtual Main method and allowing you to treat each thread like an individual program in memory making it much easier to organize as a component in your overall architecture. So I thought, hmmm...., there has to be something like this in the .NET environment, but as I searched, I found nothing. So, I decided why not write one?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace LionFront
{
///
/// This class is an attempt to handle a thread in a completely object oriented manner.
/// The attempt is to make this class similar in concept and funtion to the PTLib PThread class.
/// To use this class, create a class which inherits from this class. Override the Main() method to
/// call the code you want invoked. This will allow you to create mini-programs from within your main thread
/// and to treat them that way
///
public abstract class ThreadClass
{
private Thread thread;
private static int count;
protected bool continue = false;
///
/// Constructor. Initializes a thread to use your class.
///
///
/// The priority for the OS to place on this thread.
///
///
/// Whether or not to start the thread upon construction.
///
///
/// Then name of the class using this one. This will be part of the thread name attribute.
///
public ThreadClass(ThreadPriority priority, bool start, string className)
{
thread = new Thread(new ThreadStart(Main));
thread.Priority = priority;
count++;
thread.Name = className + count.ToString();
if (start)
thread.Start();
}/// Override this method to call the code from your class. protected abstract void Main();
/// This will be invoked by the thread upon startup.
///
public ThreadState State
{
get { return thread.ThreadState; }
}
public string Name
{
get { return thread.Name; }
}
public int ThreadID
{
get { return thread.ManagedThreadId; }
}
public virtual void Start()
{
continue = true;
thread.Start();
}
public virtual void Pause()
{
thread.Suspend();
}
public virtual void Resume()
{
thread.Resume();
}
public virtual void End()
{
continue = false
thread.Abort();
}
}
}
Voila! You have a reusable Threading Class. This is a very simple class. First, we encapsulate a System.Threading.Thread:
private Thread thread;
Next, we have an abstract (the same as virtual void method() = 0; in your c++ header) method that all subclasses must implement.
protected abstract void Main();
Finally, in the constructor, we just tell our thread to use the Main method.
thread = new Thread(new ThreadStart(Main));
Now, how do we use this?
Here is a sample. The following class listens to a socket for input from a remote server and processes the information. If it receives the signal, it will fire the event back to the main program via a delegate.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace LionFront
{
public enum DigitalInput : ushort
{
input1 = 0,
input2,
input3
}
public delegate void DigitalInputCallback(string ipAddress, DigitalInput input);
public class DigitalIO : ThreadClass
{
private static DigitalInputCallback inputCallback;
private static DigitalIO instance;
private static bool initialized;
private static ListipAddressList;
public DigitalIO(DigitalInputCallback callback)
: base(System.Threading.ThreadPriority.Highest, false, "DigitalIO")
{
inputCallback = callback;
if (!initialized)
{
ipAddressList = new List();
initialized = true;
instance = this;
instance.Start();
}
}
~DigitalIO()
{
this.End();
ipAddressList.Clear();
}
protected override void Main()
{
SendReceivePackets inputSignal = new SendReceivePackets(SendReceivePackets.GetIPAddress(), 35100);
inputSignal.BeginListen();
byte[] data = new byte[1000];
while (inputSignal.ReceiveData(ref data))
{
if (continue)
{
int startPos = 0;
int endValue = SendReceivePackets.ParseStream(startPos, data) - startPos;
string ipAddress = Encoding.UTF8.GetString(data, startPos, endValue);
startPos = endValue + startPos + 1;
endValue = SendReceivePackets.ParseStream(startPos, data) - startPos;
ushort input = Convert.ToUInt16(Encoding.UTF8.GetString(data, startPos, endValue));
inputCallback(ipAddress, (DigitalInput)input);
}
}
}
}
Here, we just wrote a normal class (in this case, our own signaling protocol), except for we give it its own Main loop by overriding the Main method. This allows us to write virtually any component that we need to run on its own thread. All we had to do was override the Main Method. Then, to use this component, you would just initialize this class in your application at whatever scope you want it to run on. However, make sure you end the thread when it goes out of scope or it will keep going; thankfully, C# still has destructors. This allows you to have as many different services running inside your application as you would like, and each will run on its own thread.
That is all for now. Happy Coding!
Subscribe to:
Posts (Atom)