ESLint Config

A quick example how to configure your coding style in ESLint.

Where?

You can choose to place your configuration either in your package.json in an eslintConfig field, or an .eslintrc.js file. For ESM, yaml, or json files read here. These files will be picked up by ESLint automatically, but you can also specify a file like so:

eslint --config my_conf.json my_javascript_code.js

How?

Using rules. There are a lot of rules in ESlint, and we want to write the ones that matter to us into the conf file.

Let’s say we want to prefer using the === operator over ==, which is considered good practice and a popular topic in Javascript development. The ESLint rule for that is eqeqeq – aimed at eliminating the type-unsafe equality operators.

{
    "rules": {
        "eqeqeq": "warn"
    }
}

Possible values are off, warn, error – or respectively 0, 1, 2. Very easy. Now you might want to explore the long list of rules for ESLint to see what you need.

Inline Rules

Rules can also be defined inline:

/* eslint eqeqeq: "warn" */

This way you can overwrite a rule locally, or disable it where needed.

Pre-defined rules

It might look like a tedious job to go through all these available rules and decide if you want to throw an error, a warning, or disable them, and it can be a good idea to start off an existing style from a popular project. An often used style, for example, is the AirBnb style which can be extended by your own rules.

npm i eslint-config-airbnb

For more information read the npm instructions or follow this more comprehensive tutorial on Medium.

mutable mutexes

const member functions

If a member function does not change the object it belongs to, it should be marked as const. This does not only help the reader to easier understand the code, but also the compiler to optimize the binary. A const member function can be called on a const object. So far, so good. But what if you need to make such a method thread safe?

logical constness

Logical constness describes when it is Ok to make an object member mutable, and is thoroughly explained in the book Effective C++ by Scott Meyers. Contrary to bitwise constness, logical constness allows to modify some of the members of the object: the ones that are not important or meaningful to the logic of the class. Such members could be technical implementation details as e.g. mutexes, and we should be fine using the mutable keyword here:

class Foo {

    void doSomething() const {
        std::lock_guard<std::mutex> lock;
        readFromStructure();
    };

private:
    mutable std::mutex mutex_;
};

bitwise constness

Bitwise const is when a method doesn’t and isn’t allowed to modify any of the non-static members of the object at all. This is C++’s default behavior, and one should consider carefully which member can be made mutable.

bindService() not working on Android SDK 30 and 31

This can be fixed by adding the following code snippet to the Android Manifest:

<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.app">
  <queries>
    <package android:name="com.example.service" />
  </queries>

  <application>
    ...
  </application>
</manifest>

In SDK 29 it was working, but in SDK 30 and 31 bindService() returned always false and did not throw any exception. The system simply couldn’t find the service, even though the service was exported using android:exported="true".

pre-increment and post-increment in C++

Maybe you have wondered why there are 2 types if increment operators in C++ and why it matters in some situations.

Lets have a variable i of type int. Pre-increment would be ++i, and post-increment is i++ as we learned it in school;

The result in both ways is the same, it increments the variable i by 1. The difference is how it behaves when passing i along to a function:

void doSomething(int i) {
  std::cout << i << std::endl;
}

int i = 12;
doSomething(i++); // prints 12
// i is now 13
int i = 12;
doSomething(++i); // prints 13
// i is now 13

The explanation

Pre-increment increments the value of i and returns a reference to the now increased i.

Post-increment makes a copy of i, then increments i, but returns the copy.

std::map and the 2 evils

The task: store pairs of keys and objects in a map. Sounds simple? Well. std::map offers several ways of accessing its members:

operator[key]
at(key)
find(key)

That all sounds good as long as the key exists in the map. If not, it can get tricky: the operator[] inserts the key and a default constructed element, which often might be undesired, and we also cannot use it with const.

And the at() method? Throws an exception. There is a chance you don’t want neither of them.

What we still can try is getting an iterator using find():

auto it = myMap.find(9);

The iterator needs to be checked to not be end(), in case the element doesn’t exist in the map.

The value type of a map is std::pair<const Key, T>, so we can get the key and element from the iterator like so:

auto key = it->first;
auto value = it->second;

async unit tests in C++

Sometimes we are in the situation where we need to test the result of a callback that is invoked on another thread and we don’t know when this will happen.

The problem? Our test already runs out of scope before the callback gets called. In order to test such a scenario we’ll need the following:

Lets assume we have a downloader that takes a while to download something, and (hopefully) reports true when it was successful:

class Downloader {
    asyncDownload(std::string url, std::function<void(bool)> callback) {
        std::thread downloadThread(download, std::move(callback));
        downloadThread.join();
    }

    download(std::string url, std::function<void(bool)> callback) {

        // perform download which takes a while
        ...
        if (everythingWentWell)
            callback(true);
    }
};

We could start writing our test case like this:

TEST(Downloader, testDownload) {
    auto callback = [](bool success) {
        EXPECT_TRUE(success);
    };
    Downloader downloader;
    downloader.download("http://foo.bar/interesting-file.jpg", std::move(callback));
}

This will leave us in a situation where the test case finishes while the Downloader is still downloading. What we need now is a way for the test case to wait until the callback is invoked, with a maximum timeout.

The way to go here is a promise with a 30s max timeout:

std::promise<void> waitGuard;
...
    EXPECT_EQ(boost::future_status::ready, waitGuard.get_future().wait_for(std::chrono::seconds(30)));

When the callback gets invoked, we inform the wait guard by setting a value. The test case now looks like this:

TEST(Downloader, testDownload) {
    std::promise<void> waitGuard;
    auto callback = [&](bool success) {
        // remember this gets called on the other thread
        EXPECT_TRUE(success);
        waitGuard.set_value();
    };
    Downloader downloader;
    downloader.download("http://foo.bar/interesting-file.jpg", std::move(callback));
    EXPECT_EQ(boost::future_status::ready, waitGuard.get_future().wait_for(std::chrono::seconds(30)));
}

Now, the test will wait until the download finishes and the callback gets called, but not more than 30s.

Swift in CMake

It is possible to use swift files in cmake projects. In my case, I added a swift based UI test to an objc project. Here is the snippet that worked:

set(CMAKE_TRY_COMPILE_PLATFORM_VARIABLES "CMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED")
set(CMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED "NO")

set(CMAKE_Swift_LANGUAGE_VERSION 5.1)
enable_language(Swift)

unset(CMAKE_TRY_COMPILE_PLATFORM_VARIABLES)
unset(CMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED)

xctest_add_bundle(myapp-test myapp
  tests/test.swift
)

initialize_ios_target(myapp-test)

When I used pthread in iOS I ran into a problem where cmake is trying to compile a small tiny program to see if the toolchain is working. Same problem here, it failed for me in the code signing step and therefor I had to turn it off for the swift compiler detection.

I had to upgrade to CMake 3.16 for this to work.

cmake Problem: pthread and iOS

A cmake build issue I came across that occurs when building with cmake and the latest version of XCode. The macro find_package(Threads) fails with

-- Looking for pthread.h - not found

Could NOT find Threads (missing: Threads_FOUND)

Digging into the log file tells it is having problems with code signing. What happens is that try_compile() compiles a very small program using pthread, and even this tiny piece needs to be code signed:

Code Signing Error: Code signing is required for product type ‘Application’ in SDK ‘iOS 13.2’

After playing around a bit, I found this workaround:

set(CMAKE_TRY_COMPILE_PLATFORM_VARIABLES "CMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED")
set(CMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED "NO")

find_package(Threads REQUIRED)

unset(CMAKE_TRY_COMPILE_PLATFORM_VARIABLES)
unset(CMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED)

Now it is able to compile the little test program and configures threads properly in cmake.

measure execution time

Oftentimes we want to know how long a command takes to execute on the command line, may it be for comparing runtime behaviour to a previous version, or to see how a system reacts.

The command that does this is time

Thomass-MacBook-Pro:build thomas$ time git diff
..
real	0m2.999s
user	0m0.757s
sys	0m2.030s
Thomass-MacBook-Pro:build thomas$
  • real – the absolute time it took
  • user – the time the CPU spent in your process
  • sys – the time the CPU spent in the kernel of the operating system

blog init

int main(int argc, char** argv) { ... return 0; }

How do I start a blog?

I don’t really know. There are many blog posts out there, suggesting what we should write in our first blog post, to attract a big audience and so on. But I am not here to become a full time blogger.

I am a software engineer. I write code and solve problems. Since years. Every day. I think I should write about it because it might be fun to look at the stories one day, and maybe there is someone who comes round to this blog who has a similar problem, and gets inspired to find a solution. Much like stackoverflow, just that I don’t want to wait until someone asks the right question.