Archive for February, 2008
Pitfalls of Equality
Consider the fallowing example:
SomeClass class1 = new SomeClass();
SomeClass class2 = new SomeClass();
bool result = (class1 == class2);
Due to class1 and class2 are exactly the same, you should expect result == true. However, result is false. The reason is operator (==) actually compares references of the objects, rather the objects itself. In case you want to compare objects, override and/or use ‘Equals’ method. Some points of interest:
-
By default, Equals method calls to GetHashCode() method and then compares it.
-
string type is immutable, it overrides == operator and inside it calls to actual string comparison.
-
Interlocked.CompareExchange method comparing objects by references (!!)
-
If anyone cares, in Java operator (==) works in same way
Add comment February 16, 2008
Is Interlocked.Equals really atomic ?!
Recently I had to check for equality of two long variables in synchronized fasion. Since in c# you can’t declare volatile on long values, I had to consider other high performance options, such as Interlocked class. If you using intellisense to see methods of Interlocked class, you will noticed it has an Equals method. Sound like exactly what I need! However, this method has signature (object arg1, object arg2). This is a bad news, because for each comparison I will had to box my values – hit performance. But this is only beginning! I refered MSDN for this method, and… Interlocked class HAS NO Equals method! Analysing with Reflector and observing Interlocked class metadata confirmed – it has no Equals method. But why Intellisense saying opposite, and why my compilation succeeded? If you will observe Interlocked.Equals method metadata (press F12 on it in VS), you will jump to.. System.Object class! Interlocked class, as any other class in .NET is object, and Equals method actually belongs to System.Object and not to System.Threading.Interlocked class. In the bottom line, what all this mean? This mean that Interlocked.Equals method is not atomic, unless System.Object.Equals already implemented as atomic operation, which is I doubt.
So how you can check for equality of two variables? I prefer to avoid locks where possible, so I recommending to not use lock here . Instead, declare where possible variables as volatile. This will make them synchronized for multithreading. In case you working with long variable (as I do in this example), and in case you using .NET 2.0 or greater, you can use Interlocked.Read method to read your value (atomic operation) to some other local variable, and then check for equality. For example:
long global_variable_I_want_to_check = 125;
long my_local_variable = 0;
my_local_variable = Interlocked.Read(ref global_variable_I_want_to_check);
if(my_local_variable = 435)
…
Add comment February 16, 2008
Revealing synchronization magic of ArayList.Synchronized collection
Today I looked (and still looking) for some kind of synchronized non blocking container. When I saying “non blocking”, I mean while threads are waiting to take access over a container, they continue to do their work – performance improvement (on multi processors machine only, of cause).
I always prefer to find some existing, working and well tested solution, instead of reinventing wheel. One my colleague suggested to use ArrayList.Synchronized method, which is creates synchronized collection from requested type (ArrayList or any other collection implementing IList interface). He claimed that synchronization of ArrayList.Synchronized collection is implemented better than an ordinary lock, and its performance is better as well. I decided to test this collection, and used Reflector to dig inside it.
After locating Synchronized method inside the ArrayList class, I noticed that actually SyncArrayList wrapper created around provided collection (ArrayList ot IList), and looks as the following:
public static ArrayList Synchronized(ArrayList list)
{
if (list == null)
{
throw new ArgumentNullException(“list”);
}
return new SyncArrayList(list);
}
Ok, now the question is: how Add method implemented inside SyncArrayList? Here is the answer:
public override int Add(object value)
{
lock (this._root)
{
return this._list.Add(value);
}
}
SyncArrayList actually using the same lock we all know! Therefore, there is nothing special about ArrayList.Synchronized synchronization, performance is exactly the same. Moreover, if you have to add 200 items to your synchronized collection, you going to lock and unlock it 200 times! On the other hand, if you are the one who controlling synchronization (manually locking) – then you will lock and unlock only once – just before and after adding all the 200 items.
From the all stated above, the conclusion is obvious: use ArrayList.Synchronized collection only when you want to guarantee its synchronization, even by cost of performance.
P.S. As I said, I still looking solution to my problem. I will appreciate any help on this.
Add comment February 14, 2008
CAB and SCSF – Part1: Introduction (with example)
For the last couple of years I hearing about CAB and Smart Client Software Factory projects, but until recently I never had a chance to play with them. Now this is the time to change that, partly because I hate to have gaps in education, but mostly because now it is very relevant for the work I doing for living. I am planning to write series of the articles on this subject, from the design considerations to actual implementation. In this one I introduce CAB and SCSF, cover some basics and finally create “hello world” CAB application.
CAB (which is stands for Composite Application Block) is part of the Microsoft Enterprise Library. The best description I can do for it, is: CAB is kind of generic client. For example, let say we want create addin for Visual Studio. Our addin is completely separated dll, which can be activated or not. But when we plugging it into the VS, we want our tab will be added to VS tabs, toolbar buttons will be added to main toolbar, and our menu items will be added to the main menu. We want in our dll (module) use all services that VS provides, and when someone clicks our menu item in the main menu, we want to catch click event inside our module and handle it somehow. Trust me, from my own experience – doing such a framework from a scratch and doing it right is not trivial task at all.
That is exactly what CAB is doing. When you creating an application using CAB, it composed from different modules and each module can have different views, services, buttons and menus – but end user can never notice that. CAB can host WPF views. Also it provides all sources, so debugging is not the problem. And the most important thing: it’s free. Officially it has to run on VS 2005, but there is a way to run it on VS2008 – information here. I didn’t succeed to run it on VS2008 Express version. In the next few months expected release of fully WPF CAB version.
The possibilities here are endless. For instance, you can create some base application, and allow to third parties develop addins for it (VS is one example for such an application). Or maybe you want to have ability to add or remove some functionality in your application, according to customer’s license/demand. Other situation is where you have number of different applications and you want to compose them together to one main application.
From architecture view point, it is very comfortable way to develop application: it can be easily extended and modified. It well structured. Developers can concentrate on development of each module like it stand alone application, without knowledge about any other modules. And deployment and versioning is very easy task – just add or change dlls you need. By the way, CAB supports click-once deployment technology.
Now you can ask: ok, I got what the CAB is. But this article named “CAB and SCSF”. What is SCSF? And what its relationship to the CAB? The answer is that SCSF using CAB to build initial solution and makes it easy adding new CAB modules. You can consider SCSF as collection of wizards, to make your life a bit easier. For example, when you adding new CAB module you need to register it in the ProfileCatalog.xml (I will talk about it), register WorkItem and to do couple other registrations. SCSF provides nice wizards to do all that for you. It generates necessary code, initial shell and it even creates method stubs, which you most likely will want to implement.
There are very much I can write about CAB architecture, but due to lack of spare time, better download documentation about it from here – they have nice pictures also. The basic idea is that application has a base shell and then developers creating modules, which will hook views, buttons and menus on it. CAB provides EventBroker service, which provides ability to communicate between modules, without coupling between them. Each module has a WorkItem, and the whole application is a tree of WorkItems. Menus and toolbars which is meant to be populated by items from other modules, called “UIExtensionSites”, and should be registered properly.
In example I provide here, I created 3 different stand alone modules (first I created new Smart Client Application (C#), then using SCSF wizard added 3 business modules to the solution). You can open and observe ProfileCatalog.xml file – it contains registrations of each module.
First module has view (user control, which is also added using wizard), and that view contains tree view control. Each time selected node in the tree, fired event with the text of the selected item. Second module has simple label. This module subscribing to events from first module (without actually knowing it), and changing label text according to text from received event. Last module adds Help\About menu item to the main menu. When item is clicked, fired event is catch, and about dialog is displayed.
Points of interest:
This is how I declaring my event, when node in tree view is selected:
//declaration of “TextChanged” event
[EventPublication("event://TextChanged", PublicationScope.Global)]
public event EventHandler TextChanged;
Notice ‘ PublicationScope.Global’ – this mean every module can see my event.
This is how second module subscribes to that event:
[EventSubscription("event://TextChanged", Thread = ThreadOption.UserInterface)]
public void OnTextChanged(object sender, EventArgs args)
{
textLabel.Text = args.Data;
}
Thread option saying, that event should be received in UI thread. It can be caller or background threads. Nice!
This is how I adding menu item to the main menu, and registering to click event (this is kind of Command Design Pattern):
//create menu items and add them to main menu.
ToolStripMenuItem helpMenu = new ToolStripMenuItem(“Help”);
ToolStripMenuItem aboutItem = new ToolStripMenuItem(“About”);
helpMenu.DropDownItems.Add(aboutItem);
WorkItem.UIExtensionSites[UIExtensionSiteNames.MainMenu].Add(helpMenu);
//register to ‘Click’ event of the about menu item.
WorkItem.Commands["AboutCommand"].AddInvoker(aboutItem, “Click”);
And here I handling click event:
[CommandHandler("AboutCommand")]
public void ShowCustomerHandler(object sender, EventArgs e)
{
AboutDialog aboutDialog = new AboutDialog();
aboutDialog.ShowDialog();
}
Conclusion: for the first look, this framework promises very much and looks good. However, for me is too early to make final decision. How high performance of this thing? Is it adaptive to changes? Is it forcing me to some specific way of programming? I will try to answer these questions in the near future.
1 comment February 6, 2008
Error Link2028: unresolved token
Yesterday during convertion of some C++ project from VS2003 to VS2008, I had error ‘Link2028′ during linking. In other circumstances I would sure I missing function body which I was declared in .h file. However, this project was perfectly building in VS2003. Here is how I solved this: in project properties, locate C/C++ \CommandLine. I removed /Zl switch, and that was worked for me)
Add comment February 4, 2008
Visual Studio addon for World of Warcraft released!!!
Recently, released addon for VS2008, which allowing creation of addins for WoW (yes, this is an addon to create addons – confusing a bit ;-) ). So, as a hardly addicted WoW player and professional programmer, I felt a personal duty to test it and see what is all about. Prior to this addin, WoW addins were done primarily using Notepad (although there is an entire community of developers who advancing to abandon Visual Studio and develop using notepad – I’m not sure it is a good idea). With the VS WoW addon it is easier than ever to create addons for WoW. It takes an advantage of powerful VS designer and providing many components to create any GUI you want, such as frames, buttons and text boxes. It has an Intellisense support for almost every function you have in your disposal (later I will talk about this “almost”). Personally I love Visual Studio, and I think many WoW developers will appriciate this wonderful tool.
Ok, enough talking – lets do some example! Initially my task was to create Orcish - Human translator. In WoW Alliance cannot understand Horde talking, and vice versa. So, many times killing started because of misunderstanding
What I really wanted to do, is to create addin, which will translate from Orcish to Human. Sounds easy - all I need to do is register somehow to ‘new message’ event in chat window, pass message text to translating function, and print translated text back to the chat window. Unfortunately, for now I not able to translate Orcish, and according to this article i doubt I ever will. Therefore I just printing the original text – echo addin. Here are the steps to create this addin:
-
Install WoW addin for Visual Studio – get it from here. I installed it successfully with VS2008 Express Edition (free version of VS which is available on www.microsoft.com).
-
Create new project – Basic WoW Addon. It creates for you Frame.xml and Frame.lua. Xml file describes GUI, and lua file holds all logic behind.
-
Double click on xml file will open VS designer. You can drag and drop components from toolbox on the left. The designer will generate all xml for you – no coding needed.
-
As far as I know, you can catch events only from GUI objects such as frames. For this purpose, we will use frame which was generated by wizard on project creation.
-
Locate it in designer and click on it left click. Properties grid on the right should appear.
-
Locate ‘name’ property and change it to ‘_invisibleFrame’.
-
Locate ‘hidden’ property and set it to True.
-
Locate OnLoad property. Name it ‘OnLoad()’ and press Create. Stub for this method will be created in the lua file.
-
Inside it, write the following code:
function OnLoad()
this:RegisterEvent(“CHAT_MSG_SAY”);
end
-
CHAT_MSG_SAY – is event which is fired on new ’say’ message. How I know that? Well, this is the part about “almost” of Intellisense. It is not provides support for events, and you have to discover name of the right event on your own. I used Internet, and found it in 2 minutes. It missing many other things, as you will see soon.
-
Now we need to catch fired event. Go back to designer. In property grid, locate ‘OnEvent’ property. Name it ‘_invisibleFrame_OnEvent()’ and press Create button.
-
About event mechanics: WoW has 8 predefined variables for holding event arguments (maybe not only) – arg1, arg2, … arg8. If some event has arguments, they stored in these variables. As I discovered, CHAT_MSG_SAY event has 3 arguments: arg1 is text of the message, arg2 is the name of speaking person, arg3 says if the language is Common or Orcish. All other args are nil. This addin meant to be translator, therefore I had to check speaking language – I want translate only Orcish:
function _invisibleFrame_OnEvent()
if(event == “CHAT_MSG_SAY”) then
if(arg3 == “Orcish”) then
local translated = Translate(arg1);
AddMessage(translated);
end
end
end -
Translate function have to translate text (for now it returns original text). AddMessage function prints specified text in the chat window. Here these 2 functions:
function AddMessage(msg, r, g, b)
if ( not msg ) then
msg = ” {NIL Value Passed}”;
end
msg = “Translated : “..msg;
if ( not r ) then
r, g, b = 0.64, 0.21, 0.93;
end
if DEFAULT_CHAT_FRAME then
DEFAULT_CHAT_FRAME:AddMessage(msg, r, g, b);
end
end
function Translate(orcishText)
return orcishText;
end
-
DEFAULT_CHAT_FRAME is another example of what you can’t find with Intellisense. I searched for function to print my text to chat window, and finally found this one in other addin.
That’s all! After you building solution, it will itself deploy your addin in WoW folder. In general, I very impressed with the work done by developers of this addin. Creating complex UI was never easy as now, and there is no need to mess with xml. Neverless it’s Intellisense needs future improvements, I think this is an awesome tool with great potential, and hope this project will continue evolve.
3 comments February 3, 2008