Just Software Solutions

Blog Archive for / 2013 /

ACCU 2013 and the C++ Standards Meeting

Monday, 06 May 2013

This year's ACCU conference was at a new venue: the Marriott hotel in Bristol. This is a bit closer to home for me than the previous venue in Oxford, which made the trip there and back more comfortable. As ever, the conference itself was enjoyable, educational and exhausting in equal measure.

This year was also BSI's turn to host the Spring ISO C++ committee meeting, which was conveniently arranged to be the week following ACCU, in the same hotel. Having not attended a meeting since the last time the committee met in the UK, I was glad to be able to attend this too.

ACCU 2013

As usual, with 5 tracks running simultaneously, it was hard to choose which sessions to attend. I stuck mostly to C++-centric, or general software development sessions, but there were also sessions on a wide range of other topics, including Ruby, Java, Scala, Git, C#, testing, management and culture, amongst others.

I was invited to contribute to Pete Goodliffe's Becoming a Better Programmer panel session, which was well attended and entertaining, as usual for Pete's sessions. My contribution on "doing things mindfully" seemed well-received, but wasn't the most popular — that honour went to Seb Rose, though Brian Marick called out Anna-Jayne Metcalfe's contribution on "If it ain't broke, do fix it" in the keynote the next morning.

My presentation on "C++11 in the Real World" was also well attended, with some good questions from the audience. A couple of people have asked me for my slides: they are available from the ACCU website.

ISO C++ committee meeting

This was a landmark meeting, for several reasons. Firstly, there were over 100 attendees, making it one of the most well-attended ISO C++ meetings ever. Secondly, this bumper attendee count was complemented by a bumper batch of proposals and position papers to process, which meant that all the working groups were pressed for time, and people met for extra sessions in the evenings to try and get through them all. Finally, the committee voted to publish a new "CD", starting the formal process leading to a C++14 standard.

The meeting was 6 days long, but I was only able to attend for the first 2 days. Unsurprisingly, I spent my time in the Concurrency group (SG1). We had a lot of papers to discuss, and some of the discussions were quite involved. Ultimately, not many papers were forwarded to the full committee, and only one paper other than the basic defect-report fixes was approved.

Lawrence Crowl's paper on Stream Mutexes (N3535) was first up. The problem this paper is trying to address is ensuring that data written to a stream from multiple threads appears in a coherent order — though concurrent writes to e.g. std::cout are guaranteed not to yield undefined behaviour, the output may be interleaved in an arbitrary fashion. This got quite a bit of discussion over the course of the week, and was eventually submitted as a much-modified paper for writing chunks to a stream in an atomic fashion, which was voted down in full committee.

Herb Sutter's late paper on the behaviour of the destructor of std::future (N3630) was up next. This is a highly conterversial topic, and yielded much discussion. The crux of the matter is that as currently specified the destructor of std::future blocks if it came from an invocation of std::async, the asynchronous function was run on a separate thread (with the std::launch::async policy), and that thread has not yet finished. This is highly desirable in many circumstances, but Herb argued that there are other circumstances where it is less desirable, and this makes it hard to use std::future in some types of program.

Much of the discussion focused on the potential for breaking existing code, and ways of preventing this. The proposal eventually morphed into a new paper (N3637) which created 2 new types of future: waiting_future and shared_waiting_future. std::async would then be changed to return a waiting_future instead of a future. Existing code that compiled unchanged would then keep the existing behaviour; code that changed behaviour would fail to compile. Though the change required to get the desired behaviour would not be extensive, the feeling in the full committee was that this breakage would be too extensive, and the paper was also voted down in full committee.

Herb's original paper also included a change to the destructor of std::thread, so that the destructor of a joinable thread would call join() rather than std::terminate(). This was put up for vote as N3636, but again was voted down in full committee.

Like I said, there were lots of other papers up for discussion. Some were concrete proposals, whilst others were less complete, asking for feedback on the approach. Only one paper was approved for the C++14 time frame — whilst there was considerable interest in the idea behind some of the others, there was disagreement about the details, and nothing else was deemed ready. I look forward to seeing the revised versions of some of these proposals when they are ready, especially the executors, continuations and parallel algorithms papers.

The paper that did get approved was Howard Hinnant's paper on shared locking (N3568), but even that didn't go through unchanged. I have serious concerns about the upgrade_mutex proposed in the original paper, and while I didn't manage to get my concerns across via email (this was discussed after I left), there was not enough interest in including it in C++14. The approved paper (N3659) therefore included only shared_mutex and shared_lock, not upgrade_mutex, which is good. N3659 was also approved by the vote in full committee, so will be part of C++14.

Wrap up

Having the conference and ISO meeting back-to-back was intense, but I thoroughly enjoyed attending both. C++14 looks set to be a significant improvement over C++11 — though the individual changes are minor, they offer quite a bit in terms of improved usability of the language and library. See the trip reports by Herb Sutter and Michael Wong (part 2, part 3) for more details on the accepted papers.

Posted by Anthony Williams
[/ news /] permanent link
Tags: , , ,
Stumble It! stumbleupon logo | Submit to Reddit reddit logo | Submit to DZone dzone logo

Comment on this post

If you liked this post, why not subscribe to the RSS feed RSS feed or Follow me on Twitter? You can also subscribe to this blog by email using the form on the left.

just::thread Pro: Actors Edition released

Tuesday, 23 April 2013

I am pleased to announce that the first release of Just::Thread Pro is here. The Actors Edition provides a framework for creating actors that run on separate threads, and communicate via message passing, as well as jss::synchronized_value for synchronizing access to a single object and jss::concurrent_map, a hash map that is safe for concurrent access from multiple threads.

See the overview for more information, or read the full documentation.

Get your copy of Just::Thread Pro: Actors Edition

Purchase your copy and get started now.

Posted by Anthony Williams
[/ news /] permanent link
Tags: , , ,
Stumble It! stumbleupon logo | Submit to Reddit reddit logo | Submit to DZone dzone logo

Comment on this post

If you liked this post, why not subscribe to the RSS feed RSS feed or Follow me on Twitter? You can also subscribe to this blog by email using the form on the left.

ACCU 2013

Saturday, 06 April 2013

I'm presenting on "C++11 features and real-world code" at ACCU 2013 in Bristol on this coming Thursday, 11th April. Here's the abstract:

C++11 has many nifty features, but how do they actually impact developers at the code face? Which C++11 features offer the best bang for the buck?

In this session I'll look at a selection of C++11 language and library features that I've found of real practical benefit in application and library code, with examples of equivalent C++03 code.

The features covered will include the concurrency support (of course), lambdas, and "auto", amongst a variety of others.

Hope to see you there!

Posted by Anthony Williams
[/ news /] permanent link
Tags:
Stumble It! stumbleupon logo | Submit to Reddit reddit logo | Submit to DZone dzone logo

Comment on this post

If you liked this post, why not subscribe to the RSS feed RSS feed or Follow me on Twitter? You can also subscribe to this blog by email using the form on the left.

Duplication in Software

Tuesday, 26 March 2013

Much has been said about the importance of reducing duplication in software. For example, J. B. Rainsberger has "minimizes duplication" as the second of his four "Elements of Simple Design", and lots of the teachings of the Agile community stress the importance of reducing duplication when refactoring code.

Inspired by Kevlin Henney's tweet last week, where he laments that programmers trying to remove duplication often take it literally, I wanted to talk about the different kinds of duplication in software. I've just mentioned "literal" duplication, so let's start with that.

Basic Literal Duplication

This is the most obvious form of duplication: sections of code which are completely identical. This most often arises due to copy-and-paste programming, but can often arise in the form of repetitive patterns — a simple for loop that is repeated multiple places with the same body, for example.

Removing Literal Duplication

The easiest to create, literal duplication is also the easiest to remove: just extract a function that does the necessary operation.

Sometimes, though the code is identical, the types involved are different. You cannot address this with extracting a simple function, so we have a new class of duplication.

Parametric Literal Duplication

Parametric literal duplication can also arise from copy-and-paste programming. The key feature is that the types of the variables are different so you cannot just reuse the code from one place in another, even if it was a nicely self-contained function. If you eliminate all the basic literal duplication, parametric literal duplication will give you sets of functions with identical structure but different types.

With the lack of a portable is_ready() function for std::future, it is common to test whether a future f is ready by writing f.wait_for(std::chrono::seconds(0))==std::future_status::ready. Since std::future is a class template, the types of the various futures that you may wish to check for readiness may vary, so you cannot extract a simple function. If you write this in multiple places you therefore have parametric literal duplication.

Removing Parametric Literal Duplication

There are various ways to remove parametric literal duplication. In C++ the most straightforward is probably to use a template. e.g.

template<typename T>
inline bool is_ready(std::future<T> f){
    return f.wait_for(std::chrono::seconds(0))==std::future_status::ready;
}

In other languages you might choose to use generics, or rely on duck-typing. You might also do it by extracting an interface and using virtual function calls, but that requires that you can modify the types of the objects, or are willing to write a facade.

Parametric literal duplication is closely related to what I call Structural Duplication.

Structural Duplication

This is where the overall pattern of some code is the same, but the details differ. For example, a for loop that iterates over a container is a common structure, but the loop body varies from loop to loop.e.g

std::vector<int> v;

int sum=0;
for(std::vector<int>::iterator it=v.begin();it!=v.end();++it){
    sum+=*it;
}
for(std::vector<int>::iterator it=v.begin();it!=v.end();++it){
    std::cout<<*it<<std::endl;
}

You can't just extract the whole loop into a separate function because the loop body is different, but that doesn't mean you can't do anything about it.

Removing Structural Duplication

One common way to remove such duplication is to extract the commonality with the template method pattern, or create a parameterized function where the details are passed in as a function to call.

For simple loops like the ones above, we have std::for_each, and the new-style C++11 for loops:

std::for_each(v.begin(),v.end(),[&](int x){sum+=x;});
std::for_each(v.begin(),v.end(),[](int x){std::cout<<x<<std::endl;});

for(int x:v){
    sum+=x;
}
for(int x:v){
    std::cout<<x<<std::endl;
}

Obviously, if your repeated structure doesn't match the standard library algorithms then you must write your own, but the idea is the same: take a function parameter which is a callable object and which captures the variable part of the structure. For a loop, this is the loop body. For a sort algorithm it is the comparison, and so forth.

Temporal Duplication

This is where some code only appears once in the source code, but is executed repeatedly, and the only desired outcome is the computed result, which is the same for each invocation. For example, the call to v.size() or v.end() to find the upper bound of an iteration through a container.

std::vector<int> v;
for(unsigned i=0;i<v.size();++i)
{
    do_stuff(v[i]);
}

It doesn't just happen in loops, though. For example, in a function that inserts data into a database table you might build a query object, run it to insert the data, and then destroy it. If this function is called repeatedly then you are repeatedly building the query object and destroying it. If your database library supports parameterization then you may well be able to avoid this duplication.

Removing Temoral Duplication

The general process for removing temporal duplication is to use some form of caching or memoization — the value is computed once and then stored, and this stored value is used in place of the computation for each subsequent use. For loops, this can be as simple as extracting a variable to hold the value:

for(unsigned i=0,end=v.size();i!=end;++i){
    do_stuff(v[i]);
}

For other things it can be more complex. For example, with the database query example above, you may need to switch to using a parameterized query so that on each invocation you can bind the new values to the query parameters, rather than building the query around the specific parameters to insert.

Duplication of Intent

Sometimes the duplication does not appear in the actual code, but in what the code is trying to achieve. This often occurs in large projects where multiple people have worked on the code base. One person writes some code to do something in one source file, and another writes some code to do the same thing in another source file, but different styles mean that the code is different even though the result is the same. This can also happen with a single developer if the different bits are written with a large enough gap, such that you cannot remember what you did before and your style has changes slightly. To beat the loop iteration example to death, you might have some code that loops through a container by index, and other code that loops through the same container using iterators. The structure is different, but the intent is the same.

Removing Duplication of Intent

This is one of the hardest types of duplication to spot and remove. The way to remove it is to refactor one or both of the pieces of code until they have the same structure, and are thus more obviously duplicates of one-another. You can then treat them either as literal duplication, parametric literal duplication or structural duplication as appropriate.

Incidental Duplication

This is where there is code that looks identical but has completely a different meaning in each place. The most obvious form of this is with "magic numbers" — the constant "3" in one place typically has a completely different meaning to the constant "3" somewhere else.

Removing Incidental Duplication

You can't necessarily entirely eliminate incidental duplication, but you can minimize it by good naming. By using symbolic constants instead of literals then it is clear that different uses are distinct because the name of the constant is distinct. There will be still be duplication of the literal in the definition of the constants, but this is now less problematic.

In the case that this incidental duplication is not just a constant then you can extract separate named functions that encapsulate this duplicate code, and express the intent in each case. The duplication is now just between these function bodies than between the uses, and the naming of the functions makes it clear that this is just incidental duplication.

Conclusion

There are quite a few types of duplication that you may get in your code. By eliminating them you will tend to make your code shorter, clearer, and easier to maintain.

If you can think of any types of duplication I've missed, please add a comment.

Posted by Anthony Williams
[/ design /] permanent link
Tags: , ,
Stumble It! stumbleupon logo | Submit to Reddit reddit logo | Submit to DZone dzone logo

Comment on this post

If you liked this post, why not subscribe to the RSS feed RSS feed or Follow me on Twitter? You can also subscribe to this blog by email using the form on the left.

Previous Entries Later Entries

Design and Content Copyright © 2005-2024 Just Software Solutions Ltd. All rights reserved. | Privacy Policy