Announcing: libstratcom 1.0rc1 on github

June 19th, 2014 No comments

libstratcom is a cross-platform library for interacting with the Microsoft SideWinder Strategic Commander digital game controller.

The latest version can be found on github now. The new 1.0 RC1 version comes with added cross-platform support (Windows, OS X, Linux and FreeBSD) thanks to HIDAPI. I also redesigned the API to use C library interface instead of a full fledged C++ interface to make it easier for people to generate bindings for other languages.

I have been working on a DirectInput joystick driver based on the library and work is coming along quite well. Check back soon for more.

Categories: Programming

pbrt: ReleaseSemaphore Error 298 on Windows

February 8th, 2014 No comments

I love the pbrt raytracer and the accompanying book. Unfortunately, the latest version has a habit of crashing when trying to render large images on Windows.

The error message

Error: Error from ReleaseSemaphore: 298

leads to the src/core/parallel.cpp file, which has a Semaphore implementation using the native operating system semaphores on Windows. Querying Visual Studio’s handy Error Lookup Tool for the error code 298 reveals the nature of the error:

Too many posts were made to a semaphore. 

Bummer.

Looking closely at the CreateSemaphore function in the Windows API, we notice the lMaximumCount parameter, which specifies how high the semaphore can count. The implementation of pbrt currently sets this to a default of 65535 which does not seem to enough for large images. But what would be a reasonable default here? Are there any performance drawbacks if we make this number too high? Why do I even have to think about a maximum at all…

Fortunately, with C++11’s library we can easily roll our own Semaphore implementation that does not suffer from this limitation. If your compiler does not ship with a working thread library yet, the following fix works just as well with Boost.Thread (simply use namespace boost instead of std).

The interface of pbrt’s Semaphore is simple: Whenever a resource is produced, the Producer thread calls Post, optionally specifying the number of resources produced. A Consumer can call Wait or TryWait to consume an existing resource. The former will block in case no resources are available, while the latter always returns immediately, indicating through its return value whether a resource was consumed or not.

[src/core/parallel.h]
#include <mutex>
#include <condition_variable>
 
[...]
 
class Semaphore {
public:
    // Semaphore Public Methods
    Semaphore();
    ~Semaphore();
    void Post(int count = 1);
    void Wait();
    bool TryWait();
private:
    std::mutex m_mutex;
    std::condition_variable m_cond;
    int m_count;
};

Instead of an operating system semaphore, we roll our own counter. I use a simple int here, which worked fine for my ~2M pixel renderings, but if you are paranoid about overflows, feel free to crank that up to a uint64_t. We use a mutex for protecting the counter from concurrent access and throw in a condition variable for waiting.

The implementation is the typical usage pattern of a condition variable: The condition in our case is the availability of a resource, represented by a counter. We start the counter with 0; calls to Post increment it, while calls to Wait decrement it:

[src/core/parallel.c]
 
Semaphore::Semaphore()
    :m_count(0)
{
}
 
Semaphore::~Semaphore()
{
}
 
void Semaphore::Post(int count)
{
    std::lock_guard<std::mutex> lk(m_mutex);
    m_count += count;
    for (int i=0; i<count; ++i) {
        m_cond.notify_one();
    }
}
 
void Semaphore::Wait()
{
    std::unique_lock<std::mutex> lk(m_mutex);
    m_cond.wait(lk, [this]() -> bool { return m_count > 0; } );
    --m_count;
}
 
bool Semaphore::TryWait()
{
    std::unique_lock<std::mutex> lk(m_mutex);
    bool const success = m_cond.wait_for(lk, std::chrono::seconds(0),
        [this]() -> bool { return m_count > 0; });
    if (success) {
        --m_count;
    }
    return success;
}

Fortunately, the original implementation for Semaphore was not very robust, so this is fairly straightforward. The counter can still overflow, so feel free to add an assert here if that bothers you. Also note that destroying the Semaphore while there are still unnotified Consumers blocked on the condition variable is not a good idea.

There is one minor thing left to make this compile: pbrt defines a number of fixed-width integer types, which, at least on Visual Studio, clash with the ones from the standard library that get pulled in via the thread headers. This can be easily fixed by throwing out the respective typedefs in src/core/pbrt.h and replacing them with the ones from <cstdint>.

With all of that in place I can finally render the Buddha in 3000×6000 again. Well worth the hassle 😀

Categories: Programming

C++11: Lambdas and C-Function Pointers

March 3rd, 2012 No comments

Just when you think you know everything about lambdas: This thread on comp.lang.c++.moderated made me realize, that lambdas do convert to old-school C-function pointers if their capture list is empty. Which means the following code compiles perfectly fine:

int (*funptr)(void) = []() -> int { return 42; };

Unfortunately, as soon as you do capture anything, be it by reference or by value, this will no longer work and you will have to rely on good-old std::function again.

Categories: IT, Programming

C++11 Detection with CMake

February 15th, 2012 7 comments

Currently when developing C++, I usually target three different compilers: MSVC, GCC and Clang. While all three offer a pretty good support ISO-C++98, things get a little more difficult with the new C++11, as they all implement different subsets of the new features.

While CMake has its disadvantages, I know of no other tool that works as well in situations like this. Unfortunately, CMake does not offer C++11-detection out-of-the-box as of this writing (version 2.8.6). A little search around the web lead to a post on CMake’s mailing list by Rolf Eike Beer. I found that script to work quite well for simple feature detection and modified it a little to better match my needs.

You can download my script from here.

Also, here’s a quick outline on how it works: Most of this is Rolf Eike Beer’s work, I just made a few minor modifications. Most of the code comes from the CXX11_CHECK_FEATURE macro. In particular, you can add your own feature tests simply by adding another call to that macro. It takes as arguments

  • FEATURE_NAME – A single-word string identifier for the feature
  • FEATURE_NUMBER – The number of the proposal paper where the feature was initially specified. This is optional and may just be set to the empty string.
  • RESULT_VAR – The name of the CMake variable that will be set to indicate whether the feature is present. It is a good idea to chose a name like HAS_CXX11_FOO, so that you can later set a preprocessor constant of the same name to inform your code of the availability of a feature.

For example, the check for the auto keyword calls

CXX11_CHECK_FEATURE("auto" 2546 HAS_CXX11_AUTO)

With this, the macro searches for a file c++11-test-auto-N2546.cpp and tries to compile it. Only if the file compiles succesfully and returns 0 upon execution, the feature is marked as supported (when cross-compiling it suffices that the test file compiles, as CMake has no means of executing it).

As an optional, second step, if a file c++11-test-auto-N2546_fail_compile.cpp is found, that file must not compile for the feature to be marked as supported. This is useful for checking things like static_assert(false), but is not needed in most cases. There was actually a small bug in the original code that messed up handling of the fail case, but that has been corrected (it did not dereference the RESULT_VAR before assigning).

If all tests pass, the specified RESULT_VAR is set in CMake and also added to the CXX11_FEATURE_LIST list variable.
That way you can easily add them as preprocessor definitions by calling something like

include(CheckCXX11Features.cmake)
foreach(flag ${CXX11_FEATURE_LIST})
set_property(TARGET your_target
APPEND PROPERTY COMPILE_DEFINITIONS ${flag}
)

in your CMakeLists.txt.

I added a small number of simple test scripts, which I hope are bug-free. I tested them on Clang, GCC and MSVC 10, so they should at least give correct results there. Currently I test for auto, nullptr, lambdas, static_assert, Rvalue references, decltype, the cstdint-header, long long, variadic templates, constexpr, sizeof() of non-static class members and __func__. If you happen to have some more tests, I’d be glad to hear from you.

Categories: IT, Programming

Announcing: libstratcom Beta1

January 11th, 2012 No comments

libstratcom is a Windows C++ library for interacting with the Microsoft Sidewinder Strategic Commander gaming device. It currently offers full support for all buttons, axis and sliders; as well as the button LEDs of the device.

You can get the source code from the project’s SVN repository here.

Since Microsoft has officially canceled support for the device, users were unable to use the Stratcom under x64 versions of Windows, as well as all versions of Windows Vista and newer. I was planning on writing an alternative GUI client for a while now, but unfortunately the project got swamped a while back. But since the library part was already working quite well, I realized it should be shared with the public, even if the client is not finished yet.

Although the library requires the Windows Driver Development Kid for compilation, the actual library code runs entirely in userland (thanks to USB HID). I also intend to write a small blog post during the next couple of days explaining the details of interacting with the device.

If you want to use the library for your own Stratcom-related projects, you are very welcome to do so. The library is released under the MIT/X11 license and ships with a few examples demonstrating its use. I still plan to finish the GUI client one day, although my motivation for doing so is currently rather low. However, if you are interested in the project and want to help out, feel free to contact me.

Categories: Programming