Docker in Action

Jon Jagger from less code, more software

is an excellent book by Jeff Nickoloff. As usual I'm going to quote from a few pages.

The docker stop command tells the program with PID #1 in the container to halt.
Like most Docker isolation features, you can optionally create containers without their own PID namespace.
If a situation arises where the name of a container needs to change, you can always rename the container with the [docker rename] command.
There are two types of volume... The first type of volume is a bind mount. Bind mount volumes use any user-specified directory or file on the host operating system. The second type is a managed volume. Managed volumes use locations that are created by the Docker daemon in space controlled by the daemon, called Docker managed space.
When you mount a volume on a container file system, it replaces the content that the image provides at that location.
You can copy volumes directly or transitively.
The third situation where you can't use --volumes-from is if you need to change the write permission of a volume.
Remember that containers maintain IP address leases only when they're running. So if a container is stopped or restarted, it will lose its IP lease and any linked containers will have stale data.
It's not common to see minimum requirements published with open source software.
CPU shares differ from memory limits in that they're enforced only when there is contention for time on the CPU.
The union file system on your computer may have a layer count limit. These limits vary, but a limit of 42 layers is common on computers that use the AUFS system.
The most curious thing about this Dockerfile is that the ENTRYPOINT is set to a file that doesn't exist.
You have no way way to specify a bind-mount volume or read-only volume at image build time.
The examples in this chapter use the cURL command-line tool. Because this is a book about Docker, you should use cURL from inside a container.


Visual Lint 6.0.2.276 has been released

Products, the Universe and Everything from Products, the Universe and Everything

Visual Lint 6.0.2.276 is now available. This is a recommended maintenance update for Visual Lint 6.0, and includes the following changes:
  • Migrated the Visual Studio 2017 VSIX extension to VSIX v3 to prevent Visual Studio 2017 from issuing a "This extension is not compatible with Visual Studio 2017" warning when the VSIX extension is installed.
  • Eclipse/CDT path variables of the form ${workspace_loc://include} are now internally aliased to ${project_loc}/include while expanding project include folder paths. This prevents issues expanding folder locations for projects which are physically located outside of the workspace.
  • The Analysis Status and Projects Display context menu "Troubleshooting | Save Preprocessed File As..." commands no longer erroneously include a reference to a PC-lint environment indirect file on the generated command line. This prevents PC-lint Plus from issuing an erroneous error 900 message at the end of the preprocessed file, which could cause an analysis error when the file is subsequently analysed.
  • Fixed a bug which could cause an out of date issue count to be displayed for a file while it was being analysed.
  • Added a "Browse" button to the "Location" combo box in the VisualLintGui "Find in Files" Dialog.
  • Updated the help to make it clear that VisualLintConsole and VisualLintGui can both analyse standalone projects as well as complete solutions/workspaces.
Download Visual Lint 6.0.2.276

Getting tuple elements with a runtime index

Anthony Williams from Just Software Solutions Blog

std::tuple is great. It provides a nice, generic way of holding a fixed-size set of data items of whatever types you need.

However, sometimes it has limitations that mean it doesn't quite work as you'd like. One of these is accessing an item based on a runtime index.

std::get needs a compile-time index

The way to get the nth item in a tuple is to use std::get: std::get<n>(my_tuple). This works nicely, as long as n is a compile-time constant. If you've got a value that is calculated at runtime, this doesn't work: you can't use a value that isn't known until runtime as a template parameter.

std::tuple<int,int,int> my_tuple=...;
size_t index;
std::cin>>index;
int val=std::get<index>(my_tuple); // won't compile

So, what can we do? We need a new function, which I'll call runtime_get, to retrieve the nth value, where n is a runtime value.

template<typename Tuple>
... runtime_get(Tuple&& t,size_t index){
  ...
}

The question is: how do we implement it?

Fixed return type

The return type is easy: our function must have a single return type for any given Tuple. That means that all the elements in the tuple must have the same type, so we can just use the type of the first element. std::tuple_element will tell us this, though we must first adjust our template parameter so it's not a reference.

template<typename Tuple>
typename std::tuple_element<
  0,typename std::remove_reference<Tuple>::type>::type&
runtime_get(Tuple&& t,size_t index){
  ...
}

Note: C++17 includes std::variant, so you might think we could use that to hold the return type, but that wouldn't actually help us: to get the value from a variant, you need to call std::get<n>(v), which requires n to be a constant (again)!

OK, so the return type is just a reference to the type of the first element. How do we get the element?

Retrieving the nth element

We can't do a straightforward switch, because that requires knowing all the cases in advance, and we want this to work for any size of tuple.

One way would be to have a recursive function that checked the runtime index against a compile-time index, and then called the function with the next compile-time index if they were different, but that would mean that the access time would depend on the index, and potentially end up with a deeply nested function call if we wanted the last element in a large tuple.

One thing we can do is use the index value as an array index. If we have an array of functions, each of which returns the corresponding element from the tuple, then we can call the appropriate function to return the relevant index.

The function we need is of course std::get; it's just a matter of getting the function signature right. Our overload of std::get has the following signature for const and non-const tuples:

template <size_t I, class... Types>
constexpr tuple_element_t<I, tuple<Types...>>&
get(tuple<Types...>&) noexcept;

template <size_t I, class... Types>
constexpr const tuple_element_t<I, tuple<Types...>>&
get(const tuple<Types...>&) noexcept;

so, we can capture the relevant instantiation of std::get for a given tuple type Tuple in a function pointer declared as:

using return_type=typename std::tuple_element<0,Tuple>::type&;
using get_func_ptr=return_type(*)(Tuple&) noexcept;

The signature is the same, regardless of the index, because we made the decision that we're only going to support tuples where all the elements are the same.

This makes it easy to build a function table: use a variadic pack expansion to supply a different index for each array element, and fill in std::get<N> for each entry:

template<
  typename Tuple,
  typename Indices=std::make_index_sequence<std::tuple_size<Tuple>::value>>
struct runtime_get_func_table;

template<typename Tuple,size_t ... Indices>
struct runtime_get_func_table<Tuple,std::index_sequence<Indices...>>{
    using return_type=typename std::tuple_element<0,Tuple>::type&;
    using get_func_ptr=return_type (*)(Tuple&) noexcept;
    static constexpr get_func_ptr table[std::tuple_size<Tuple>::value]={
        &std::get<Indices>...
    };
};

template<typename Tuple,size_t ... Indices>
constexpr typename
runtime_get_func_table<Tuple,std::index_sequence<Indices...>>::get_func_ptr
runtime_get_func_table<Tuple,std::index_sequence<Indices...>>::table[
  std::tuple_size<Tuple>::value];

We need the separate redeclaration of the table to satisfy a pre-C++17 compiler; with C++17 inline variables it is no longer needed.

Our final function is then just a simple wrapper around a table lookup:

template<typename Tuple>
constexpr
typename std::tuple_element<0,typename std::remove_reference<Tuple>::type>::type&
runtime_get(Tuple&& t,size_t index){
    using tuple_type=typename std::remove_reference<Tuple>::type;
    if(index>=std::tuple_size<tuple_type>::value)
        throw std::runtime_error("Out of range");
    return runtime_get_func_table<tuple_type>::table[index](t);
}

It's constexpr safe, though in a constexpr context you could probably just use std::get directly anyway.

So, there you have it: a constant-time function for retrieving the nth element of a tuple where all the elements have the same type.

Final code

Here is the final code for a constant-time function to retrieve an item from a tuple based on a runtime index.

#include <tuple>
#include <utility>
#include <type_traits>
#include <stdexcept>

template<
  typename Tuple,
  typename Indices=std::make_index_sequence<std::tuple_size<Tuple>::value>>
struct runtime_get_func_table;

template<typename Tuple,size_t ... Indices>
struct runtime_get_func_table<Tuple,std::index_sequence<Indices...>>{
    using return_type=typename std::tuple_element<0,Tuple>::type&;
    using get_func_ptr=return_type (*)(Tuple&) noexcept;
    static constexpr get_func_ptr table[std::tuple_size<Tuple>::value]={
        &std::get<Indices>...
    };
};

template<typename Tuple,size_t ... Indices>
constexpr typename
runtime_get_func_table<Tuple,std::index_sequence<Indices...>>::get_func_ptr
runtime_get_func_table<Tuple,std::index_sequence<Indices...>>::table[std::tuple_size<Tuple>::value];

template<typename Tuple>
constexpr
typename std::tuple_element<0,typename std::remove_reference<Tuple>::type>::type&
runtime_get(Tuple&& t,size_t index){
    using tuple_type=typename std::remove_reference<Tuple>::type;
    if(index>=std::tuple_size<tuple_type>::value)
        throw std::runtime_error("Out of range");
    return runtime_get_func_table<tuple_type>::table[index](t);
}

Posted by Anthony Williams
[/ cplusplus /] permanent link
Tags: ,

| Stumble It! stumbleupon logo | Submit to Reddit reddit logo | Submit to DZone dzone logo

Comment on this post

Follow me on Twitter

C++ Concurrency in Action 2nd edition Early Access

Anthony Williams from Just Software Solutions Blog

I am happy to announce that the second edition of my book, C++ Concurrency in Action, is now available under the Manning Early Access Program.

The second edition is being updated to cover C++14, C++17 and the Concurrency TS, along with general improvements throughout the book.

This includes full coverage of the library changes from C++14 and C++17:

  • std::shared_mutex and std::shared_timed_mutex. These provide for multiple-reader/single-writer mutex locks.
  • std::scoped_lock from C++17 for locking multiple mutexes together.
  • Parallel overloads of many standard library algorithms include std::sort, std::for_each and std::transform_reduce.

Plus, full coverage of the library extensions from the concurrency TS:

  • std::experimental::latch to allow waiting for a set number of events to occur
  • std::experimental::barrier and std::experimental::flex_barrier to synchronize groups of threads
  • std::experimental::atomic_shared_ptr to allow atomic accesses to a single shared_ptr instance from multiple threads, as a better alternative that the std::atomic_load and std::atomic_store free functions.
  • Extended futures that allow continuations, so additional functions can be scheduled for when a future is ready.
  • std::experimental::when_all and std::experimental::when_any to allow waiting for either all of a set of futures to be ready, or the first of a set of futures to be ready.

Only the first few chapters are available at the moment, but if you sign up now, then you will get those chapters in PDF form now, as well as updated PDFs including the later chapters as they become ready, along with updates for the earlier ones, and a final print copy of the book when it's done.

50% Discount

If you use the code mlwilliams4 at the checkout when you sign up for the MEAP before 27th March 2017 then you'll get a 50% discount.

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

Follow me on Twitter

Siddhartha

Jon Jagger from less code, more software

is an excellent book by Herman Hesse. As usual I'm going to quote from a few pages.

He learned more from the river than Vasudeva could teach him. He learned from it continually. Above all, he learned from it how to listen, to listen with a still heart, with a waiting, open soul, without passion, without desire, without judgement, without opinions.
It also happened that curious people came along, who had been told that two wise men, magicians or holy men lived at the ferry. The curious ones asked many questions but they received no replies, and they found neither magicians nor wise men. They only found two friendly old men, who appeared to be mute, rather odd and stupid. And the curious ones laughed and said how foolish and credible people were to spread such wild rumours.
Is it not perhaps a mistake on your part not to be strict with him, not to punish him? Do you not chain him with your love? Do you not shame him daily with your goodness and patience and make it still more difficult for him?
Within Siddhartha there slowly grew and ripened the knowledge of what wisdom really was and the goal of his long seeking. It was nothing but a preparation of the soul, a secret art of thinking, feeling and breathing thoughts of unity at every moment of life.
From that hour Siddhartha ceased to fight against his destiny. There shone in his face the serenity of knowledge, of one who is no longer confronted with conflict of desires, who has found salvation, who is in harmony with the streams of events, with the stream of life, full of sympathy and compassion, surrendering himself to the stream, belonging to the unity of all things.
In every truth the opposite is equally true. For example, a truth can only be expressed and enveloped in words if it is one-sided. Everything that is thought and expressed in words is one-sided, only half the truth; it lacks totality, completeness, unity.
The sinner is not on the way to a Buddha-like state; he is not evolving, although our thinking cannot conceive things otherwise. No, the potential Buddha already exists in the sinner; his future is already there. The potential Buddha must be recognized in him, in you, in everybody. The world, Govinda, is not imperfect or slowly evolving along a path to perfection. No, it is perfect at every moment; every sin already carries grace within it, all small children are potential old men, all sucklings have death within them, all dying people - eternal life.
In order to learn to love the world, and no longer compare it with some kind of desired imaginary world, some imaginary vision of perfection, but to leave it as it is, to love it and be glad to belong to it.
It may be a thought, but I confess, my friend, that I do not differentiate very much between thoughts and words. Quite frankly, I do no attach great importance to thoughts either. I attach more importance to things.
I think it is only important to love the world, not to despise it, not for us to hate others, but to be able to regard the world and ourselves and all beings with love, admiration and respect.
The thing to me is of greater importance than the words; his deeds and life and more important to me than his opinions. Not in speech or thought do I regard him as a great man, but in his deeds and life.
Uncontrollable tears trickled down his old face. He was overwhelmed by a feeling of great love, of the most humble veneration.