28 lutego 2016

Android USB tethering

Android tethering i magiczny zestaw komend. Ale najpierw linki:
Należy rozpocząć od zainstalowania klienta DHCP jeżeli go nie ma, np.:
$ sudo apt-get install isc-dhcp-client
# Albo
$ sudo apt-get install dhcpcd5
Po podłączeniu telefonu do komputera i włączenie opcji tetheringu (Udostępnianie internetu | Router USB).
# Należy odnaleźć interfejs sieciowy podłączonego telefonu, będzie to np. enx01234
$ ifconfig -a

$ sudo dhclient enx01234
# Albo
$ sudo dhcpcd enx01234

# Test
$ route
$ wget -c example.com
Problem, który napotkałem to nie działające DNS-y, trzeba więc było dodać do /etc/resolv.conf publiczne DNS-y google:
$ cat /etc/resolv.conf

# Dynamic resolv.conf(5) file for glibc resolver(3) generated by resolvconf(8)
#     DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN
nameserver 127.0.1.1
nameserver 8.8.8.8
nameserver 8.8.4.4
Wszystko co pozostało to zautomatyzowanie całego procesu. Prawie ...

W przypadku mojego domyślnego ISP, pojawił się problem "powrotu". Najwyraźniej stara sesja DHCP, została utracona, a serwer nie chciał utworzyć nowej. Pomogły dwie komendy, które usunęły i zażądały nowej sesji.
$ sudo dhclient -r -v eth0
$ sudo dhclient -v eth0

27 lutego 2016

Reinstalacja VirtualBox-a wraz z extension pack-iem

Reinstalacja VirtualBox wraz z extension pack-iem. Najpierw należy ściągnąć pakiet (.deb) oraz extension pack (.vbox-extpack) w odpowiedniej wersji:
VirtualBox zaprotestuje, jeżeli mamy zainstalowaną starszą wersję, trzeba ja odinstalować:
$ sudo apt-get remove virtualbox-4.3
Proces instalacji:
$ sudo dpkg -i virtualbox-5.0_5.0.14-105127-Ubuntu-wily_amd64.deb

$ sudo VBoxManage list extpacks
Extension Packs: 1

$ sudo VBoxManage extpack uninstall "Oracle VM VirtualBox Extension Pack"
0%...10%...20%...30%...40%...50%...60%...70%...80%...90%...100%
Successfully uninstalled "Oracle VM VirtualBox Extension Pack".

$ sudo VBoxManage extpack install Oracle_VM_VirtualBox_Extension_Pack-5.0.14-105127.vbox-extpack 
0%...10%...20%...30%...40%...50%...60%...70%...80%...90%...100%
Successfully installed "Oracle VM VirtualBox Extension Pack".

$ sudo VBoxManage list extpacks
Extension Packs: 1
Pack no. 0:   Oracle VM VirtualBox Extension Pack
Version:      5.0.14
Revision:     105127
Edition:      
Description:  USB 2.0 and USB 3.0 Host Controller, Host Webcam, VirtualBox RDP, PXE ROM, Disk Encryption.
VRDE Module:  VBoxVRDP
Usable:       true 
Why unusable: 

13 stycznia 2016

[CppCon 2015] C++11/14/17 atomics and memory model: Before the story consumes you

Model pamięci jest największą zmianą jaką przyniósł nowy standard. A mechanizm atomic-ów na razie sprawiają mi najwięcej problemów. Być może znajdę kiedyś motywację, by bliżej się im przyjrzeć. W tej chwili wszystko co zrobiłem w tym kierunku to sucha lektura. Poniżej, bardzo fajny wykład z tegorocznego CppCon 2015 autorstwa Michaela Wonga, który rozjaśnił mi wiele kwestii.


2 stycznia 2016

[python] collections

Trzy klasy z pakietu collections, których nigdy wcześniej nie korzystałem, a okazały się niezwykle przydatne.
Bywa że do krotki chcemy wstawić na tyle dużo danych, że zaczynamy się gubić w tym, na której pozycji znajduje się to co nas interesuje. Zamiast tworzyć klasę z polami, można skorzystać z namedtuple.
from collections import namedtuple

User = namedtuple('User', ['name', 'address', 'email'])

user = User('Bob', 'blog.example.com', 'bob@example.com')
print('Name:  ' + user.name)
print('Web:   ' + user.address)
print('Email: ' + user.email)
Wynik:
Name:  Bob
Web:   blog.example.com
Email: bob@example.com
Counter pozwala na zliczanie elementów - zamiast dedykowanej pętli for.
from collections import Counter

indexer = Counter(['Bob', 'Alice', 'Bob', 'Bob'])
print(indexer['Bob'])
Wynik:
3
defaultdict jest klasą pozwalają na ustawienie domyślnej wartości, dla nowych elementów. Przydatne, gdy dodajemy coś do wartości i nie chcemy robić testu na to, czy taki element już istnieje.
from collections import defaultdict

d = defaultdict(lambda: '-')
d['Bob'] += 'one_'
d['Alice'] += 'two_'
d['Bob'] += 'three_'

print(d)
Wynik:
defaultdict(<function <lambda> at 0x7fbf33b27578>, {'Bob': '-one_three_', 'Alice': '-two_'})

17 października 2015

[C++11] std::future - programowanie oparte na zadaniach

W programowaniu współbieżnym preferowanym podejściem powinno być programowanie oparte na zadnich, a nie na wątkach [1]. Kilka przydatnych linków:
std::future jest obiektem, przechowującym wyniki (także wyjątki) asynchronie działających funkcji - czyta wynik ze współdzielonego stanu. Wynik można pozyskać za pomocą metody get(). W takim scenariuszu wątek główny zostanie zablokowany do chwili aż wynik będzie dostępny, lub zwróci wynik natychmiast, jeżeli asynchroniczna operacja zakończyła się wcześniej.

Do asynchronicznego wołania funkcji służy std::async. Jest to rozwiązanie najbardziej wysokopoziomowe, gdyż sam std::async dba o to by ustawić std::future w stan ready. Wywołanie oprócz ewentualnych argumentów jakie mają być przekazane do funkcji wymaga również podania policy:
  • std::launch::async - nowy wątek zostanie uruchomiony do wykonania zadania
  • std::launch::deferred - wykonanie zadania zostaje odroczone do momentu wywołania metod get() lub wait()
  • std::launch::async | std::launch::deferred - kombinacja flag, jednak zachowanie jest zależne od implementacji
Wszystkie przykłady kompilowałem w ten sam sposób, z dodatkowo włączonym sanitizerem, który pomógł wykryć kilka błędów w kodzie.
$ clang++ -std=c++14 -fsanitize=thread -lpthread -g main.cpp
Przykład obliczania ciągu Fibonacciego z zastosowaniem std::async.
#include <iostream>
#include <future>

using namespace std;

int fibonacci(int n)
{
    std::cout << "Current n: " << n << std::endl;
    if (n == 0)
        return 0;
    else if (n == 1)
        return 1;
    return fibonacci(n - 1) + fibonacci(n - 2);
}

int main()
{
    std::future<int> result = std::async(std::launch::async | std::launch::deferred,
                                         fibonacci, 3);
    std::cout << "Result: " << result.get() << std::endl;

    return 0;
}
Wynik:
Current n: 3
Current n: 2
Current n: 1
Current n: 0
Current n: 1
Result: 2
std::packaged_task także pozawala na tworzenie obiektów std::future. Można go porównać do std::function, a więc jako wrapper do tworzenia obiektów callable. W przeciwieństwie do std::async, nie uruchamia on jednak przekazanej funkcji automatycznie. Najważniejszą właściwością std::packaged_task jest możliwość pozyskania z niego obiektu std::future, i przekazania go do innego wątku, gdzie zostanie wykonany.

Przykład:
#include <iostream>
#include <thread>
#include <future>

using namespace std;

int fibonacci(int n)
{
    std::cout << "Current n: " << n << std::endl;
    if (n == 0)
        return 0;
    else if (n == 1)
        return 1;
    return fibonacci(n - 1) + fibonacci(n - 2);
}

int main()
{
    std::packaged_task<int(int)> task{fibonacci};
    std::future<int> result = task.get_future();

    std::thread t{std::move(task), 3};
    t.join();

    std::cout << "Result: " << result.get() << std::endl;

    return 0;
}
Wynik:
Current n: 3
Current n: 2
Current n: 1
Current n: 0
Current n: 1
Result: 2
std::promise można rozważyć jako początek kanału komunikacyjnego, na którego końcu znajduje się std::future. Do jego zadań, należy zapisanie wyniku do współdzielonego stanu. Czasami dane, które nas interesują są już dostępne (obliczone) i nie musimy czekać na zakończenie jakiegoś wątku. Za pomocą std::promise możemy w wątku głównym wytworzyć obiekt std::future (czyli końcówka kanału - dzięki metodzie get_future()), a następnie przekazać go (std::promise) do innego wątku. W wątku pobocznym, gdy interesujące nas dane zostaną obliczone wołamy metodę set_value() (początek kanału). W ten sposób obiekt std::future zostanie ustawiony w stan ready, i dane będą mogły być odczytane w wątku głównym. W porównywaniu do std::async, jest to rozwiązaniem bardziej nisko poziomowe, lecz czasami zachodzi potrzeba aby z niego skorzystać.

std::promise ma jeszcze jedno zastosowanie, można go wykorzystać jako mechanizm do sygnalizacji pomiędzy wątkami (std::promise<void> - typ obiektu jako void). Coś na kształt std::condition_variable, z tym że taka sygnalizacja może zadziać się tylko raz. Aby odblokować pracę na współdzielonych danych należy wywołać set_value(). Aby wstrzymać pracę wątku do momentu, aż dane będą dostępne, należy wywołać metodę wait().

Przykład:
#include <iostream>
#include <thread>
#include <future>

using namespace std;

struct Fibonacci {
    std::promise<int> p;
    bool isSatisfied;
    const int index;
    int partialIndex;

    Fibonacci(std::promise<int> p_, int index_)
        : p(std::move(p_))
        , isSatisfied(false)
        , index(index_)
        , partialIndex(0)
    {
    }

    int fibonacci(int n)
    {
        std::cout << "Current n: " << n << std::endl;

        int result = 0;
        if (n == 0)
            result = 0;
        else if (n == 1)
            result = 1;
        else
            result = fibonacci(n - 1) + fibonacci(n - 2);

        if (isSatisfied == false and partialIndex == n) {
            isSatisfied = true;
            std::cout << "Passing partial result" << std::endl;

            p.set_value(result);
        }
        return result;
    }

    void operator()(int partialVal_)
    {
        partialIndex = partialVal_;
        fibonacci(index);
    }
};

int main()
{
    std::promise<int> p;
    std::future<int> result = p.get_future();

    std::thread t{ Fibonacci{ std::move(p), 5 }, 3 };

    std::cout << "Result: " << result.get() << std::endl;
    t.join();

    return 0;
}
Przykładowy wynik:
Current n: 5
Current n: 4
Current n: 3
Current n: 2
Current n: 1
Current n: 0
Current n: 1
Passing partial result
Current n: 2
Current n: 1
Current n: 0
Current n: 3
Current n: 2
Result: 2Current n: 
1
Current n: 0
Current n: 1
Bibliografia:
  • [1] Scotta Meyersa: Skuteczny nowoczesny C++. APN PROMISE SA, 2015. Rozdział 7, str. 289.
  • [2] Anthony Williams: C++ Concurency in Action. USA Manning publications Co., 2012. Rozdział 7, str. 67.