User Tools

Site Tools


cplusplus:goingnative2013

Going Native 2013

Herb Sutter had a couple of favorite C++ few-liners. Watch the video here: My Favorite C++ 10-liner.

A complete reference-counted object cache.

From C++98 it uses map operator[]'s auto-insertion.

From C++11 it uses:

  • auto
  • mutex, lock_guard
  • Thread-safe fn statics
  • shared_ptr and weak_ptr
  • Thread-safe.lock()
widget_cache.cpp
shared_ptr<widget> get_widget( int id ) {
    static map< int, weak_ptr<widget> > cache;
    static mutex m;
 
    lock_guard<mutex> hold(m);
    auto sp = cache[id].lock();    // cache[id] returns a weak_ptr. lock() returns the shared_ptr
    if( !sp )
        cache[id] = sp = load_widget(id);
    return sp;
}

In C++11, the following code is thread safe! It's the Meyers Singleton.

  • Thread safe fn statics
  • Does destruction. No need for Alexandrescu's various destruction policies anymore!
thread_safe_meyers_singleton.cpp
widget& instance() {
    static widget w;
    return w;
}

This one uses the Cinder C++ Library.

gui_app.cpp
#include "cinder/app/AppBasic.h"
#include "cinder/dx/dx.h"
#include <vector>
using namespace ci;
using namespace ci::app;
 
class MyApp:public AppBasic {
    std::vector< Vec2f > points;
public:
    void mouseDrag( MouseEvent e ) {
        points.push_back( e.getPos() );
    }
 
    void draw() {
        dx::clear( Color( 0.1f, 0.1f, 0.15f ) );
        dx::color( 1.0f, 0.5f, 0.25f );
        dx::begin( GL_LINE_STRIP );
        for( auto& e: points )
          dx::vertex( e );
        dx::end();
    }
};
 
CINDER_APP_BASIC( MyApp, RendererDx )

Advanced Optimization

Use lambda in place of std::bind to save memory. A std::bind() on a pointer-to-member-function will allocate 24 bytes on the heap for the bind structure. If instead you use a lambda, then this fits into 4 bytes and avoids any allocation.

Replace:

  g(this, std::bind(&m_f, this)),

With:

  g(this, [this](){this->m_f();}),

Note that subtle changes to object lifetimes is possible. This code:

  std::bind(f, std::weak_ptr<Object>(n));

is not the same as this code:

  [n]{ f(std::weak_ptr<Object>(n)); }

The above code will bind the shared_ptr<Node> into the lambda's capture, extending the lifetime.
But it is the same as this:

  [wp = std::weak_ptr<Object>(n)]{ f(wp); };

In this case the lambda's capture only has the weak pointer.

cplusplus/goingnative2013.txt · Last modified: 2023/04/12 20:44 by 127.0.0.1