Thursday, July 9, 2009

Going AFK with Bazaar

One thing I've really liked about distributed VC systems is that they handle merging really well. Of course, this is not limited to DVCSs. Subversion and Perforce have very good merging but do not support offline work very well.

I've been using Bazaar for a little while now for my app because I knew that I would need to be offline every now and then. I just had one of those periods and thought it would be a great chance to see how well AFK mode works with Bazaar.

This is more for my own future reference rather than for you :-)

laptop $ rsync -avz -e ssh sohail@desktop:/home/sohail/bzr ~/bzr
laptop $ bzr branch ~/bzr/code/master project
laptop $ bzr bind ~/bzr/code/master

Now I can work offline in the "project" directory and all checkins go to ~/bzr .

Upon return:

laptop $ rsync -avz -e ssh ~/bzr/ sohail@desktop:/home/sohail/bzr

NOTE TRAILING SLASH ON SOURCE DIRECTORY!!!!!1111oneone....

Note: I think the above is insane. Ideally, I'd just do something like:

laptop $ bzr checkout bzr+ssh://sohail@desktop/home/sohail/bzr bzr
laptop $ cd bzr
laptop $ bzr work-offline

Return from afk:

laptop $ bzr I'm back

Or something like that.

Sunday, June 28, 2009

Software developer, businessman or problem solver?

[Warning: Soap box post. I reserve the right to use this blog as such and you reserve the right not to read it! Please let me know if it reads like a Steve Yegge post. You can tell if it is like Steve Yegge if you hate it more and more as you read it. If this is so, please inform me and I will revise the article.]

As a software developer and still fledgling businessman, I am faced with many problems I need to solve each day. From how to accept payments online to maintenance renewals to how to write as little code as possible to do something useful, sometimes it boggles the mind how much we really have to deal with each day in our profession. Good thing I don't think about it much!

Some time back, I had lunch with a friend and we got to talking about needed skills for a software developer. This friend is quite possibly one of the smartest guys I know, not because he knows at what point Newton's theories break down or how generational garbage collection works, but because I think he really understands people. So I was very interested when he stated that the most important skill needed is the ability to search out solutions to problems. Not coding or encyclopedic knowledge of C++, .NET, Java, or functional programming but simply, the ability to take a problem, go away and come back with a solution.

I don't recall whether we talked about it more but it's been sitting in the back of my mind. Ever since then, I've come across situations where this statement jumps to the forefront and I think, "Yeah, this person could be a really good problem solver!" or "Hmm, I really should have tried to put on my problem solving hat here."

Is software development or growing a business actually problem solving? Maybe the answer is obvious to you but I have never thought about it consciously. To answer that question, I have to think about what a problem is. To me, a problem is an obstacle in the way to achieving a goal.

A goal one should probably have when starting a software business is to get paid. Now, unless I am experienced at achieving this goal, I will have no idea where to start. So one of two things will happen:

  • I will give up because I don't know the answer already
  • I will start to look for the answer
I know, it's obvious right? Every time there is a bug I don't know how to fix, or a feature I don't know how to implement, I am faced with these two choices. I'd like to think that I never choose the first option, but I'd be lying to myself.

Fixing bugs is something I'm generally good at. I've fixed some whoppers (mmm whopper) in the past, self-inflicted or otherwise. So I rather like the example above of choosing a way to get paid because I've never done it before. I've no idea how it works. I'm deathly afraid to screw up. But I've bought lots of software online. I know people who sell software online. So I start by asking people I know or people I trust. I recall situations in which I hated the purchasing process and situations in which it was the best process ever. I go back to these online stores and find out what I liked or hated. I make a list and check it twice.

With all this research, I have not written a line of code, yet I now have a very good idea of what a good solution should look like. Problem solved? Not quite. Now I have to decide whether to buy or build. I've already decided ahead of time that writing it myself is not really something I'm interested in but to ensure I understand what is going on, I research this topic as well. Indeed, it is not worth it. Eventually, I settle on a reseller and move on to achieving the next goal.

There is nothing magical about solving the problem above. In fact, it is almost mechanical. But the key point is the decision that was taken at the first point. That is, the decision to actually solve the problem.

I am fairly convinced that software development as well as growing a fledgling business are very much problem-centric. They are filled with goals along with many obstacles to achieving them. At each obstacle, you have two choices: to give up or keep going. We need to keep going. This does not mean being stubborn and trying the same thing over and over again. This often means trial and error, hypothesizing and experimentation (Carl Sagan might like that!) Above all, don't give up and say it is impossible.

Anyway, just thought I'd put the thought in your heads since it's been in mine for a while. I think I'm going to try calling myself Chief Problem Solver from now on.

Monday, June 8, 2009

VanCPP June meeting

If you are in Vancouver and interested in programming (who isn't?!) you might want to make your way to the VanCPP meeting in June. The announcement is below:

Our June 2009 meeting will be held on Thursday, June 18. Please note the new venue.

Topic: Concurrent Programming in the D Programming Language

Presented by Walter Bright

Abstract: Many-core concurrent programming offers exciting and compelling advantages. The single core, single thread programming model is assumed by imperative programming languages. This model offers sequential consistency as its fundamental characteristic.Because many-core systems use layered cache memory systems,sequential consistency is not guaranteed among threads.Because imperative programming languages allow implicit sharing of data between threads, many misguided idioms and optimizations are possible that erroneously assume sequential consistency.One example of this is the double checked locking optimization.The pernicious nature of these sorts of bugs is they defy programmers' natural intuition about how programs behave,they are not statically detectable, and there is no way to reliably test a program to rule out the existence of such bugs.A program may appear to work, but have problems appear years later, fail when ported to a different platform, and such problems may be extremely hard to reproduce and track down.In essence, the correctness of the program relies entirely on the expertise and care of the programmer.This is not an acceptable situation for developers of programs that require high reliability.

The D programming language is an imperative programming language with an innovative type system that prevents implicit sharing and also fosters a complete, integrated pure functional subset. It is possible to statically verify that D programs do not have sequential consistency bugs. The double checked locking optimization bug is not possible. Type support for shared data and immutable data, as well as pure functions, means that mutating data interactions between threads can occur only under carefully controlled conditions.This dramatically reduces the problem space for concurrency bugs from the whole of the source code to a small subset of it, making it a much more tractable problem.

Speaker bio: Walter Bright graduated from Caltech in 1979 with a degree in mechanical engineering. He worked for Boeing for three years on the development of the 757 stabilizer trim system. He then switched to writing software, in particular compilers, and has been writing them ever since.

The meeting will be held at:
Workspace
21 Water Street
Vancouver, BC
V6B 1A

Regards,

Vladan Vidakovic

Thursday, May 7, 2009

Using C++0x lambda to replace Boost Bind in C++03 code

[Note: This post looks ugly under Internet Explorer. If you want to tell me how to fix my CSS, that would be much appreciated]
[Note: This post was written using the Intel C++ compiler with -std=c++0x.]

As some of you know, I work on Worklog Assistant which is written using C++/Qt.

One thing that I've made very good use of is a slightly modified version of the code in an earlier post titled "Using Boost Bind and Boost Function with Qt".

As an example, consider the following code from the above app which creates a popup menu to toggle the visibility of table columns. This is done by creating a "toggle" action for each column header that... toggles the visibility. It might help to think how this action would be created in plain Qt (hint: it would be painful.) It would certainly not have the locality it does now.

void
showColumnHeaderContextMenu(ssci::CustomTableView * self,const QPoint & pos)
{
QMenu columns(ssci::CustomTableView::tr("Visible Columns"));
columns.setIcon(QIcon(QString::fromLatin1(":/ui/icons/grid.png")));

QHeaderView * headers(self->horizontalHeader());

std::vector<std::pair<QString,int> > sorted_columns;
getSortedColumns(self->model(),headers,sorted_columns);

for(int ii = 0; ii < headers->count(); ++ii)
{
QAction * action =
new QAction(sorted_columns[ii].first,
&columns);

bool is_hidden = headers->isSectionHidden(sorted_columns[ii].second);

action->setCheckable(true);
action->setChecked(!is_hidden);

using boost::bind;
using boost::function;

function<void()> toggle =
bind(&QHeaderView::setSectionHidden,headers,
sorted_columns[ii].second,!is_hidden);

ssci::connect(action,SIGNAL(triggered()),
toggle);

columns.addAction(action);
}

QMenu menu;
menu.addMenu(&columns);

menu.exec(self->mapToGlobal(pos));
}


Of particular interest is the code in the for loop which sets up the actions:
    function<void()> toggle =
bind(&QHeaderView::setSectionHidden,headers,
sorted_columns[ii].second,!is_hidden);

ssci::connect(action,SIGNAL(triggered()),
toggle);



This creates a function object on the fly which hides the selected column using code from the above linked post. To do this in plain Qt is a gigantic pain. LibQxt has a solution as well but mine is much better!

Anyway, the point is that you might find a lot of code using bind and function in an app like this. Binding member function pointers, member data pointers and function pointers is fairly normal and is really the only way to maintain sanity and reduce boiler plate. Nested binds are also used where appropriate.

Boost Bind is a way to create closures, or at least as close as you can get in C++ to true closures. Therefore it is natural to try and replace some uses of Boost Bind with C++0x lambda. There is good coverage of how C++0x lambda works here so I won't repeat the same information. However, I will cover the cases of bind I could convert and (horrifically) the cases I couldn't!

Using automatic variables



Consider the following code:

const int LICENSING_TAB_INDEX = 1;

ssci::connect(lblImportNewLicense,SIGNAL(linkActivated(QString const &)),
boost::function<void()>(
boost::bind(&QTabWidget::setCurrentIndex,
tabWidget,
LICENSING_TAB_INDEX)
)
);



The above function call sets things up so that when a link is clicked in the interface, the LICENSING_TAB_INDEX tab is selected in the configuration.

One thing Boost Bind does is that it stores all bound arguments by value. That means &QTabWidget::setCurrentIndex, tabWidget and LICENSING_TAB_INDEX are all stored by value. C++0x lambda calls this capturing. This can be done using implicit capture (by parsing the lambda body) or by you. By default, C++0x lambda captures variables by reference. It is potentially buggy to capture function-local variables by reference automatically. Therefore, the above code translated to C++0x lambda is:
[=]()
{ tabWidget->setCurrentIndex(LICENSING_TAB_INDEX); }

The first element of a lambda-introducer (the []) can be a capture default which can be one of = or &. The capture default tells the compiler how to capture those variables that are implicitly captured. The assignment is supposed to make you think of copy assignment and the & is supposed to make you think of reference to. So in the above case, to get the exact same behaviour as the bind, we need to intentionally copy all variables by value.

Great! Not so bad :-)

A simpler example... Or is it?



Consider the following code:

ssci::connect(clearSelectedRole,SIGNAL(clicked()),
boost::function<void()>(
boost::bind(
&QComboBox::setCurrentIndex,
projectRoles,
-1)
)
);


This code sets things up so that when the clearSelectedRole button is clicked, the corresponding QComboBox has an invalid index.

The C++0x version of this is really straightforward:

ssci::connect(clearSelectedRole,SIGNAL(clicked()),
boost::function<void()>(
[&](){projectRoles->setCurrentIndex(-1);}
)
);

In this case, the pointer object (not the value) projectRoles is captured by reference. This is not an issue because the pointer object is guaranteed to outlive the closure. Now you know why closures and garbage collection go together :-)

Verbosity or Why I wish C++0x used polymorphic lambdas



Consider the following code:

static
void
updateThreadSetup(QObject * parent,ssci::MainWindow * self);

m_checkForUpdatesThread(boost::bind(updateThreadSetup,_1,&parent))


The bound function in this case is an object that calls the function updateThreadSetup with a to-be-determined value for the first parameter and a fixed value for the second parameter.

The C++0x version of this is horrible:
m_checkForUpdatesThread([&parent](QObject * obj){updateThreadSetup(obj,&parent);});


First, since parent is a local variable (was passed into the function), you can't implicitly capture it. So you have to explicitly capture it. In this case, we want to capture it by reference, hence [&parent] in the lambda-introducer. Then, since this thread setup function is passed in a QObject* we have to tell the compiler to accept this argument. Apparently it isn't smart enough. Ask someone why it is this way, you'll hear some hand waving about the callable concept. Whatever.

That is some ugly code.

Anyway...

What you cannot convert without making your code super ugly



Consider the following simple code:
vector<int> d = {1,2,3,4,5};
vector<function<int()>> funcs;

for(vector<int>::iterator it = d.begin(), end = d.end();
it != end;
++it)
{
funcs.push_back(boost::bind(add5,*it));
}


This creates a vector of function objects that presumably add 5 to their bound argument and return the result.

Here is the equivalent in C++0x lambda:

vector<int> d = {1,2,3,4,5};
vector<function<int()>> funcs;

for(vector<int>::iterator it = d.begin(), end = d.end();
it != end;
++it)
{
int &i = *it; // WTF?
funcs.push_back([i](){add5(i);});//THIS IS REDUNDANT. REDUNDANT.
}


Naively, one might have done:

funcs.push_back([it](){add5(*it);});

in the loop. But this is a bug waiting to happen. Add the following line right after the for loop:
d.push_back(0)

Now all those iterators that are captured by value can be invalidated! YAY! The only way to avoid this issue is to manually extract the value referenced by the iterator and pass that into the closure which is what I did in my translation.

Conclusion



This exercise showed me that C++0x lambda is of some interest to me. I'd really like to get rid of the verbosity (I know, too late!) A couple of things would make this the perfect lambda for me:

  • Polymorphic lambdas (or at least let me specify auto for the arguments)

  • An easy way to capture computed values (the *it bug above)



I don't know how these problems would be solved, or whether they could be but until they are, I think there is still a future for function binding ala Boost Bind which is fine by me!

Sunday, May 3, 2009

BoostCon 2009

BoostCon starts tomorrow.

I went to the first and second Boost conferences. The first as an attendee, the second as a speaker. I was blown away by the quality of the talks, particularly the author's corner series of talks. I think that if the organizers are smart about it, this can be one of the best conferences. For me, it is already on par with conferences like SD West for quality and relevance.

I am extremely disappointed that I could not make it this year due to my schedule being way too busy. I hope that some of you reading this have been able to schedule better than me and go to BoostCon.

If you are attending, please ask at least one very difficult on-topic question in each of your talks for me.

Also, ask Joel de Guzman about Boost.GUI. Apparently he's got something cooking (you didn't hear it from me!)

Thursday, March 19, 2009

A seemingly complete Qt API for CL

Just came across this library called CommonQT.

It is more complete than the API I developed earlier. It is also using the KDE Smoke libraries which make it damn easy to create the API on the fly.

Very exciting.

Sunday, February 15, 2009

Latest NVIDIA drivers, Ubuntu Edgy

NVIDIA drivers not loading after the latest Ubuntu update? Low resolution mode?

They used to work didn't they?

Before you start uninstalling Ubuntu packages and installing the official NVIDIA drivers, throwing your hands up and generally having a bad day, try this:

(as root): echo nvidia >> /etc/modules

Reboot. Should work now.

For some reason, you need to explicitly load the module with the latest nvidia packages (I'm using nvidia-glx-new)