May 10

C++ pimpl thoughts

Recently, I’ve been writing some C++ code that I would like to be ABI compliant. Because of that, I’ve been writing the code that uses a private class that holds all of the private data members. This results in code that looks something like the following:

// myclass.h

#include <memory>

class MyClass{
public:
	MyClass();
	~MyClass();

	int foo() const;
	void setFoo( int val );

private:
	class priv;

	std::unique_ptr<priv> m_priv;
};

// myclass.cpp
#include "myclass.h"

class MyClass::priv {
public:
	priv() :
	m_foo( 5 )
	{}

	int m_foo;
};

MyClass::MyClass(){
	m_priv = std::make_unique<priv>();
}

MyClass::~MyClass(){
}

int MyClass::foo() const {
	return m_priv->m_foo;
}

void MyClass::setFoo( int foo ){
	m_priv->m_foo = foo;
}

However, after some further reading I realized that this creates a new problem with const methods: mainly that you can’t ensure const correctness! That is, if we change MyClass::foo to be the following, it’s perfectly legal:

int MyClass::foo() const {
	m_priv->m_foo += 10;
	return m_priv->m_foo;
}

Obviously, this particular design results in code that may look const-correct, but actually is not. You can get around that with having an actual pointer to the implementation and not just the private data members, but this seems like a lot of overhead and is really just a lot of boilerplate in my mind.

This leads me to some thoughts on what would make this nicer. The main problem seems to be this facet of C++:

Size and Layout: The calling code must know the size and layout of the class, including private data members.

https://herbsutter.com/gotw/_100/

Since the calling code needs to know the size and layout, any change to this causes ABI breakage, which is certainly not ideal, thus needing the pimpl pattern. What would be nice is if we didn’t have to do this. Thus, I bring my very simple 5-minute solution that hasn’t been thought out fully.

Add a new keyword! Called ‘privdata’.

Example usage:

// myclass.h

#include <memory>

class MyClass{
public:
	MyClass();
	~MyClass();

	int foo() const;
	void setFoo( int val );

private:
	privdata int m_foo;
};

// myclass.cpp
#include "myclass.h"

MyClass::MyClass() : m_foo( 5 ){
}

MyClass::~MyClass(){
}

int MyClass::foo() const {
	return m_foo;
}

void MyClass::setFoo( int foo ){
	m_foo = foo;
}

The idea behind this is that just by declaring a private variable with ‘privdata’ effectively turns the code into what I posted before with the unique_ptr, so that no matter how many private variables you add(with the ‘privdata’ keyword) the class will stay the same size.

Advantages:

  • One keyword to add
  • Very easily make a class ABI compatible.
  • No need to worry about a layer of indirection – the compiler takes care of this for you.
  • Most tools(e.g. IDEs) will still work correctly. One problem with how I’ve been implementing is that Qt Creator doesn’t have nice auto completion for m_priv->…. That’s not the end of the world, but it would be nice!
  • The compiler could still check for const correctness and only allow access in const methods and editing in non-const methods.

Disadvantages:

  • I’ve spent longer writing this post than thinking about this, so I’m certainly missing something.
  • Compilation speedups may not be possible at this point(assuming that you’re using make), since changing something in the header would cause all dependent files to be rebuilt. Maybe we need a new version of make that can parse code to know when things change and only rebuild when something important changes?
  • This requires a lot of compiler changes. New standards require compiler changes anyway, but this probably can’t be implemented without compiler changes.

I did also start looking at some more recent posts from Herb Sutter, and I found this interesting post on making a clonable class. This makes me wonder if this would be possible to do using just standard C++ and some sort of reflection library…


If you want to learn more about the pimpl patter, check out the cppreference page, which also leads to Herb Sutter’s GotW page on pimpl. Herb Sutter’s page was useful for me in terms of learning about the alternatives and how they work.


ADDENDUM NEXT DAY: It turns out, this is possible using some experimental features(std::propagate_const). See this post on Stack Overflow for more information, or on cppreference!

May 02

SSH Key Length Error

I wanted to SSH into a server of mine earlier today, but I was met with this error when I tried to SSH in using the key:

$ ssh -i private-key username@host
Load key "private-key": Invalid key length
username@host's password:

There is some information on this about the exact SSH version that I was using, but one thing that was not clear was if this was a server error or a client error.

As it turns out, this is a client error, the server itself is still fine. There’s a lot of information on the internet, but suffice to say that as of OpenSSH 7.9, you need a key at least 2048 bits long. So to solve this issue, you just need to use an older version of ssh.

If you don’t have an older version of the SSH client available, you could probably get around the issue by installing a virtual machine with an older version of the SSH client. Debian 9(stretch) comes with a version of openssh-client that will work.

Jan 05

Signing VMWare Drivers for UEFI

Earlier today, I had to install VMWare on a Linux host that had UEFI. Fortunately, there is a guide to how to do this on the VMWare KB, however at the end, the part “Reboot your machine. Follow the instructions to complete the enrollment from the UEFI console” is not clear on what exactly you need to do.

In order to get this to work on my Acer Aspire, I did the following(note: I’m not sure what exactly is required, as I was messing around with several settings).

  1. Reboot your system and add a password in the BIOS. Smash F2 when the system boots. Alternatively, GRUB should have an option to go to the BIOS. (this step may not be required)
  2. Generate the keys as shown in the VMWare KB article.
  3. Copy the .der file to /boot/efi/EFI/debian
  4. Reboot the system.
  5. You should get a screen that says ‘Perform MOK Management’. Enroll your key from here. See this site for more details.

And that should be it. It’s not hard to do, but it is not clear and may be different for each manufacturer.

Oct 11

London vs Washington DC

A few weeks ago, I took a trip to London and saw some very cool things! While I was there, I took the Underground most of the time and figured that I would make a quick list for anybody who ever wants to visit Washington, DC and is familiar with London.

First things first: some terminology. In London, the system is the Underground. In DC, the system is Metro. The long name of the system is WMATA, or Washington Metropolitan Area Transit Authority. Nobody actually calls it WMATA though, Metro would be the proper term.

Metro and Bus

Like the London Oyster card, the DC Metro uses a contactless card called Smartrip. Put it close to the reader, and the gates will open, allowing you to enter the system. Paper farecards were accepted until 2016, and were largely replaced because the maintenance of the machines to process the paper farecards became prohibitively expensive. Fares are based off of time(rush-hour or non-rush) and distance traveled.

Metro buses also accept the Smartrip card, making it easy to pay for the buses and trains. The convenient part about using a Smartrip card on the bus is that you get free two-hour transfers between buses, which can be useful if you need to travel on more than one bus.

A number of other local jurisdictions also have their own bus services. This includes Arlington Transit, Fairfax Connector, Alexandria Dash, Ride On, and DC Circulator. As far as I am aware, all of the other local bus services also take Smartrip cards as payment.

If you’re comfortable taking a bus, it is definitely a plausible way to travel around, but may be slow and not always direct.

You can pick up a Smartrip card at any Metro station(go to the fare machines). Cards can also be topped up there, or if you’re on a bus you can use the card reader on the bus to add more money to the card. If you need to do this, you probably want to wait until everybody else has boarded the bus. Press the button to add more money(left side of reader), tap Smartrip, insert money, and tap Smartrip again to have the fare loaded.

Other Metro Thoughts

The DC Metro is not as dense or have trains as often as the Underground, but it does have a few advantages. Like London, the trains display the last line on the route that they are going to. For example, the Silver line has two endpoints: Largo Town Center and Wiehle-Reston East. You need to know which direction you are going in order to get on the correct train. On the new 7000-series cars, the announcer on the train is a computerized voice; the earlier cars have the engineer making the announcements, which can be notoriously unclear.

Like London, each platform has an LED board showing the next train coming into the station. This board shows the line that the train is for(Green/Yellow/Blue/Orange/Silver/Red), the station it is going to, and how many cars the train has. There is a push to hopefully have all 8-car trains, however there are still many 6-car trains on the Metro, so those trains will be a little shorter. Since the Metro makes large use of having multiple lines share the same physical tracks, depending on where you are going you may not need to get on the same color train. For example, to get between Rosslyn and Smithsonian stations, you can take either the Orange line going to New Carrolton, the Blue line to Largo Town Center, or the Silver line to Largo Town Center.

The DC Metro is nicer than London in at least two respects: the accessibility of the stations, and the transfer from one line to another. On the accessibility side, all of the Metro trains are on straight platforms and have no steps up(or down!) into the cars. This also makes it very easy to use if you are disabled. If you need an elevator though, if the elevator at the station you are going to is broken you can get a bus transfer from another station; listen for station announcements or check the Metro website. Transferring from one line to another is also very easy, since the trains go to the same station, and at most you have one escalator to go up(or down). Why the Underground stations are very cramped and have a ton of stairs and turns between the stations is a mystery to me.

Walking Around

If you’re visiting DC as a tourist, you’re probably planning on going to the museums. The good news is that for the most part, all of the museums are situated around the national mall. This means that they are walkable, although you may walk a lot! Some places you probably want to want to take the Metro to so that you’re not walking a large distance. Unlike London, where the crosswalk is a separate stage in the light cycle, for the most part US traffic light cycles have you crossing with traffic at the same time. This makes it difficult for traffic to turn left or right, and so sometimes the cycle will allow pedestrians or traffic to go first. The indicators for if you can walk are also nice and clear, with either a walking man or a hand telling you to stop. When the hand comes up, nearly all of the walking indicators also have a separate display counting down the seconds that you have left until the light will change. This is very useful so that you can see how long you have until you need to clear the intersection, and is one thing that I missed when I was in London.

Conclusion

I don’t really have a conclusion, this is just some information for people who may be interested. There’s much more information that I could put here, but this post is long enough as-is. Have fun!

Aug 19

C++17 and Fold Expressions

So I’ve just come across this very cool feature in C++17 that I plan on using called ‘fold expressions’. This is basically a way of expanding a bunch of operations. It is also very hard for me to wrap my head around, so we’re going to go through a (very simple) example here, since people don’t seem to explain what exactly happens.

This simple example prints out everything that is passed into the method to stdout:

template <typename... argn>
void fold_test_types( argn... params ){
    (std::cout << ... << params);
}

int main(){
    fold_test_types( 3, 4, "hi", 8);
}

The output is 34hi8, because we forgot to add any newlines or spaces, but that’s fine for this example.

Now what really tripped me up here is the fact that in the fold expression, we’re using the << operator to distinguish things, and it makes it very confusing as to what is actually happening. With fold expressions, the data between the parentheses is expanded, kinda like a template. Let’s look at the rules real quick:

( pack op ... ) (1)
( ... op pack ) (2)
( pack op ... op init ) (3)
( init op ... op pack ) (4)


1) unary right fold
2) unary left fold
3) binary right fold
4) binary left fold


op – any of the following 32 binary operators: + – * / % ^ & | = < > << >> += -= *= /= %= ^= &= |= <<= >>= == != <= >= && || , .* ->*. In a binary fold, both ops must be the same.
pack – an expression that contains an unexpanded parameter pack and does not contain an operator with precedence lower than cast at the top level (formally, a cast-expression)
init – an expression that does not contain an unexpanded parameter pack and does not contain an operator with precedence lower than cast at the top level (formally, a cast-expression)
Note that the open and closing parentheses are part of the fold expression.

https://en.cppreference.com/w/cpp/language/fold

This is a bit hard to understand, but the … is basically a keyword when it is in the parentheses like this. ‘pack’ is the name of the parameters, e.g. in our example it is ‘params’.

Looking at these rules, the rule that we are following in this example is #4, the binary left fold. Let’s look at the fold expression again, with some comments:

(std::cout << ... << params);
|    |      |  |   |    |  ^----ending paren
|    |      |  |   |    ^---- pack(params) - see definition above
|    |      |  |   ^---- operator(<<)
|    |      |  ^---- ...(keyword?)
|    |      ^---- operator(<<)
|    ^--- init(std::cout) - see definition above
^----Starting paren   

With these broken out, it should now be clear why this is #4, the binary left hold. The rules on how it folds are as follows:

1) Unary right fold (E op …) becomes (E1 op (… op (EN-1 op EN)))
2) Unary left fold (… op E) becomes (((E1 op E2) op …) op EN)
3) Binary right fold (E op … op I) becomes (E1 op (… op (EN−1 op (EN op I))))
4) Binary left fold (I op … op E) becomes ((((I op E1) op E2) op …) op EN)

https://en.cppreference.com/w/cpp/language/fold

Since we are using #4, apply the rule for #4. When the compiler runs, the code effectively becomes the following with the template substitution and the fold expression expansion:

void fold_test_types( int arg1, int arg2, std::string arg3, int arg4 ){
    ((((std::cout << arg1) << arg2) << arg3) << arg4);
}

int main(){
    fold_test_types( 3, 4, "hi", 8);
}

Jul 28

Thoughts on Nuclear Power

A few weeks ago on Slashdot, there was an article on safer nuclear reactors.  It sounded interesting, but of course since it was on Slashdot the comments turned into a not quite a flame-fest, but certainly there tends to be an undercurrent of “I’m right and you’re wrong” whenever something like this comes up(see also: systemd).

Anyway, while I don’t have anything against nuclear power per se, there are a bunch of problems that make it at least somewhat impractical.  First of all, what are the good things about nuclear power?

  • It’s low carbon – see this Wikipedia article for the exact numbers, but suffice to say that once it is running, it is low carbon.
  • It is cheap electricity once it is running.

The ‘once it is running’ is a rather large caveat though – as we’ve seen in Georgia, building new plants is expensive.  Currently, about 27 billion dollars.  That’s quite a lot of money.  Even once it is on-line, there are very expensive long-term costs from personnel to long-term storage of nuclear waste.  A brother of a family friend of mine works at a nuclear power plant, and he’s now retired at ~50.  He still goes back as a contractor, and apparently makes >$100/hour.

One other problem that probably can’t be solved easily is the NIMBY problem – people are afraid of nuclear power due to the accidents that have happened.  I don’t see a way to solve this, since it is a similar problem to people not liking to fly.  Even though flying is the safest mode of transportation, there are many people who don’t like flying.  My suspicion is this is due to the lack of feeling in control, as well as the fear that if something bad does happen, you feel like you will certainly die.  Most plane accidents that people probably think about are the ones where pretty much everybody dies, so they are afraid that there’s no way out if something bad does happen.

The next question of course, assuming that we don’t have nuclear power, is can we actually generate all of our power from renewable sources such as wind and solar?  The answer may be yes, given that Scotland can(under favorable conditions) generate enough power to power it twice over.

Let’s take the above example of the Vogtle nuclear plant, and assume we were to put all of that $27 billion into wind turbines as well.  Assuming that each turbine costs $4 million to install and has a capacity of 2 MW, that means we could install 6,750 turbines for the cost of the nuclear plant, giving us an installed capacity of 13,500 MW.  Actual numbers will probably be lower, given that the wind does not blow all the time, but that’s the theoretical maximum.  According to Wikipedia, the new reactors will have a capacity of 1117 MW each, giving us  a grand total of 2234 MW capacity.

Assuming my math here is correct, it makes much more sense to build wind turbines than to build a nuclear plant(at least in the US).  I suspect(but don’t have the numbers to back it up) that long-term costs are also lower for turbines, since I don’t think that they need much maintenance, plus you don’t have a problem with guarding spent fuel.

If we throw solar in the mix as well, that also has some interesting numbers.  According to Dominion Energy(pg 19), a solar plant array lifetime is 35 years, with one year for construction/destruction takes it to 37 years.  Given that building the Vogtle plant is at least an 8+ year project, it doesn’t seem very feasible to continue on the path of nuclear.

Conclusion: nuclear, while not a bad source of power, has quite a few practical problems compared to modern wind and solar energy.  Of course, each power source has its own pros and cons.  This is not intended to be a fully exhaustive comparison of all energy sources, so you may want to take this with a grain of salt.

Apr 25

Fun with templates

As you may be aware, I maintain dbus-cxx, and I’ve been working on it lately to get it ready for a new release. Most of that work is not adding new features, but updating the code generator to work correctly. However, this post today is not about that work, it is about the work that I am doing on the next major version of dbus-cxx(2.0). Part of this work involves using new C++ features, due to libsigc++ needing C++17 to compile now. With the new variadic templates that C++ has(actually since C++11), we can have more than 7 template parameters to a function. (This limit of 7 is arbitrarily chosen by libsigc++, it’s not a C++ limitation.)

Because of this however, some of the code in dbus-cxx needs to change in order to work correctly. The main portion that I’m working on right now has to do with getting the DBus signatures to work properly. Here’s a small piece of code that is currently in dbus_signal.h(after running dbus_signal.h.m4 through m4):

  /** Returns a DBus XML description of this interface */
  virtual std::string introspect(int space_depth=0) const
  {
    std::ostringstream sout;
    std::string spaces;
    for (int i=0; i < space_depth; i++ ) spaces += " ";
    sout << spaces << "<signal name=\"" << name() << "\">\n";

    T_arg1 arg1;
    sout << spaces << "  <arg name=\"" << m_arg_names[1-1] << "\" type=\"" << signature(arg1) << "\"/>\n";
    T_arg2 arg2;
    sout << spaces << "  <arg name=\"" << m_arg_names[2-1] << "\" type=\"" << signature(arg2) << "\"/>\n";
    sout << spaces << "</signal>\n";
    return sout.str();
  }

This method is created once for each overloaded type that we have. The important part is that T_arg is created once for each argument that we have. With variadic templates, this is impossible to do. The way to get the template arguments out of the variadic call is to do recursion.

Recursion + templates is not something that I’m very familiar with, so this took me a while to figure out. However, I present the following sample code for getting the signature of a DBus method:

  inline std::string signature( uint8_t )     { return "y"; }
  inline std::string signature( bool )        { return "b"; }
  inline std::string signature( int16_t )     { return "n"; }
  inline std::string signature( uint16_t )    { return "q"; }
  inline std::string signature( int32_t )     { return "i"; }
  inline std::string signature( uint32_t )    { return "u"; }

  template<typename... argn> class sig;

   template<> class sig<>{
   public:
   std::string sigg() const {
     return "";
   }
   };

   template<typename arg1, typename... argn>
   class sig<arg1, argn...> : public sig<argn...> {
   public:
   std::string sigg() const{
     arg1 arg;
     return signature(arg) + sig<argn...>::sigg();
   }
   };

int main(int argc, char** argv){
  std::cout << sig<uint32_t,uint32_t,bool,int64_t>().sigg() << std::endl;
}

Output: 
uubx

This took me a few hours to figure out exactly how to do it, so I’m at least a little proud of it! The other confusing part that I had to work out was how to use a recursive call(with signature()) also with the recursive call for the templates, which leads us to the following observation:

It’s recursion all the way down.

Mar 15

One large program or many little programs?

Earlier this week, I came across this question on softwareengineering.stackexchange.com.  This has some relevance for me, since at work two of our main projects follow the two sides of this design philosophy: one project is a more monolithic application, and the other follows more of a microservices model(e.g. many applications).  There are some reasons for this which I will now attempt to explain.

Option 1: Monolithic Application

The first project that I will explain here is our project that has a more monolithic application.  First of all, a brief overview of how this project works.  Custom hardware(running Linux) collects information from sensors(both built-in and often third-party over Modbus) and aggregates it and classifies it.  The classification is due to the nature of the project – sensor data falls into one of several classes(temperature, voltage, etc.).  This information is saved off periodically to a local database, and then synchronized with a custom website for viewing.  The project, for the most part, can be split into these two main parts:

  • Data collector
  • Web viewer
  • Local viewer(separate system, talks over ethernet)

Due to the nature of the hardware, there is no web interface on the hardware directly, it is on a cloud server.

Now, the data collector application is a mostly monolithic application.  However, it is structured similarly to the Linux kernel in that we have specific ‘drivers’ that talk with different pieces of equipment, so the core parts of the application don’t know what hardware they are talking to, they are just talking with specific interfaces that we have defined.

In this case, why did we choose to go with a monolithic application?  Well, there are a few reasons and advantages.

Reason 1: As primarily a data collector device, there’s no real need to have different applications send data to each other.

Reason 2: The development of the system is much easier, since you don’t need to debug interactions between different programs.

Reason 3: Following from the first two, we often have a need to talk with multiple devices on the same serial link using Modbus.  This has to be siphoned in through a single point of entry to avoid contention on the bus, since you can only have one modbus message in-flight at a time.

Reason 4: All of the data comes in on one processor, there is no need to talk with another processor.  Note that this is not the same as talking with other devices.

Reason 5: It’s a lot simpler to pass data around and think about it conceptually when it is all in the same process.

Now that we have some reasons, what are some disadvantages to this scheme?

Disadvantage 1: Bugs.  Since our application is in C++(the ability to use C libraries is important), a single segfault can crash the entire application.

Disadvantage 2: The build can take a long time; the incremental build and linking isn’t bad, but a clean build can take a few minutes.  A test build on Jenkins will take >10 minutes, and it can still take several minutes to compile on a dev machine if you don’t do parallel make.

Overall, the disadvantages are not show-stoppers(except for number 1, there is some bad memory management happening somewhere but I haven’t figured out where yet).  The separation into three basic parts(data collection, local GUI, web GUI) gives us a good separation of concerns.  We do blend in a little bit of option 2 with multiple applications, but that is to allow certain core functionality to function even if the main application is down – what we use that for is to talk with our local cell modem.  Given that the data collection hardware may not be easily accessible, ensuring that the cellular communications are free from bugs in our main application is important.

Option 2: Multiple Applications

If you don’t want to make a monolithic application, you may decide to do a lot of small applications.  One of my other primary projects uses this approach, and the reason is due to the nature of the hardware and how things need to interact.

In our project with multiple applications, we have both multiple compute units and very disparate sensor readings that we are taking in.  Unlike the monolithic application where data is easily classified into categories, this project has even more disparate data.  Moreover, we take in a lot of different kinds of data.  This data can come in on any processor, so there is no ‘master’ application per se.  This data also needs to be replicated to all displays, which may(or may not) be smart displays.  We also want to insulate ourselves from failure in any one application.  A single bug should not take down the entire system.

To handle this, we essentially have a common data bus that connects all of the processors together.  We don’t use RabbitMQ, but the concept is similar to their federation plugin, in that you can publish a message on any processor and it will be replicated to all connected processors.  This makes adding new processors extremely easy.  All of the data is basically made on a producer/consumer model.

Advantage 1: Program resiliency.  With multiple applications running, a bug in one application will not cause the others to exit.

Advantage 2: You can easily add more processors.  This is not really a problem for us, but since data is automatically synchronized between processors, adding a new consumer of data becomes very simple.

Advantage 3: Data can come and go from any connected system, you need not know in advance which processor is giving out information.

This design is not without some caveats though.

Disadvantage 1: Debugging becomes much harder.  Since you can have more than one processor in the system, your producer and your consumer can be on different processors, or you could have multiple consumers.

Disadvantage 2: Because this is a producer/consumer system(it’s the only way that I can see to effectively scale), there’s no way to get data directly from an application(e.g. there’s no remote procedure call easily possible over the network).

Conclusion

There are two very different use cases for these two designs.  From my experience, here’s a quick rundown:

Monolithic Application

  • Generally easier to develop, since you don’t have to figure out program<->program interactions
  • Often needed if you need to control access to a resource(e.g. physical serial port)
  • Works best if you only have to run on one computer at a time

Multiple Applications

  • Harder to develop due to program<->program interactions
  • Better at scaling across multiple computers
  • Individual applications are generally simpler

Due to the nature of engineering, there’s no one way to do this that is best.  There are often multiple ways to solve a given problem, and very rarely is one of them unequivocally the best solution.

Jan 31

Counting lines of code

So a few years ago, me and a coworker had to figure out how many lines of code we had. This was either for metrics or for because we were curious, I can’t really remember why. I came across the script again today while going through some old code. Here it is in all its glory:

#!/bin/bash

let n=0; for x in "$@"; do temp1=`find $x | grep '\\.cpp$\|\\.c$\|\\.java$\|\\.cc$\|\\.h$\|\\.xml$\|\\.sh$\|\\.pl$\|\\.bash$\|\\.proto$'`; temp=`cat /dev/null $temp1 | grep -c [.]*`; let n=$n+$temp; if [ $temp -gt 0 ]; then printf "%s: " $x ; echo $temp; fi; done ; echo Total: $n

This took us at least an hour(or perhaps more), I’m not really sure.

Anyway, it was after we had done all of that work that we realized that wc exists.