寫起來,免得忘記。
在程式Crash前直接呼叫gdb
1 | void dump(int signo) |
寫起來,免得忘記。
1 | void dump(int signo) |
對最近的心得做個總結。
這篇Boost application performance using asynchronous I/O描述了幾種常用的IO Model。
首先要先解釋兩個很像,卻又部太相同的名詞
最常見的I/O Model,就是在Event未結束前不會將控制權交還給Application。
1 | int len = recv(s, .....); |
在這種Model之下,為了要解決Blocking的問題,就得使用Multi-Porcess或是Multi-Thread的方式來做。
隨著Java8推出,新增了一堆新特性。其中有一項就是C# 3.0有的Extension Method。紀錄一下。
在OOP的世界裡,一旦介面推出之後,就不能在更改了。否則依賴於這介面開發的程式必須更著改動。如果Source Code都在自己手上還好。如果是3rd party或是已不在維護的Library,這就變成問題。
1 | public interface MyInterface { |
如果如果現在Interface需要增加一個myFunc2的功能,該怎麼作。
Docker跟Virtual Box這種Virtual Machine上的虛擬化不同,他是基於64 bit linux上,由cgroups/AUFS/LXC為基礎發展出來的Linux virtualization,目前也僅能在Linux上跑,相對於VM等級,更輕量化且更省資源。
由於Docker需要Linux kernel 3.8以上的,如果版本比較舊的要先更新
1 | $ sudo apt-get install linux-image-generic-lts-raring linux-headers-generic-lts-raring |
由於Ubuntu 14.04直接收入Docker
所以直接安裝docker.io就好,然後以下的指令全部用docker.io
取代docker
1 | $ sudo apt-get install docker.io |
將Docker的PGP Key跟Repository加入環境中
1 | $ sudo sh -c "wget -qO- https://get.docker.io/gpg | apt-key add -" |
跟新Source且安裝LXC-Docker
1 | $ sudo apt-get update |
開始玩虛擬化之後,紀錄如何用VirtualBox + Vagrant打造自己的開發環境。
可以把Box想像成光碟,需要安裝的時候,就拿出光碟開始安裝環境。
1 | $ vagrant box list # 列出目前所有的Box |
從網路下載的Box會存在`~.vagrant.d\boxes’下。
有兩種方式,從Box衍生出來,或是寫個VagrantFile衍生。
1 | $ vagrant init {title} |
後者會將box存到Box List中。
兩者都會產生一個VagrantFile
檔案。
看了這篇 C11 - Generic Selections。
第一直覺感覺和C++ Template很像,不過也不太一樣。
這是C11的Code
1 | #include <stdio.h> |
在電腦裡面,有很多Resource的存在,除了最常見的Memory之外,還有FILE
,HANDLE
等以指標為形,卻有自己的Destroy function的資源。而這種資源該怎麼管理比較好,就是一門學問了。
翻閱很多Open source的Project之後,發現大部分的作法都類似這樣
1 | typedef void(*freefunc)(void *); |
由於任何指標型態都能跟void 互轉,所以這種作法行得通。
不過由於C語言的Type system很弱,一旦轉成void之後,無法檢查支援先的Type,如果上面的fclose換成free,編譯器不會警告你任何東西,只有在Runtime才會知道這邊會Core dump。
由於auto_ptr只能管理Memory之類的Resource,所以我們必須要自行打造輪子。
可以學習C++11中的unique_ptr
帶入Destroy function
1 | template <typename T> |
雖然這樣子可以盡量避免掉呵叫錯誤Destory function的問題,不過如果硬要cast function prototype也是無法避免。
測試了一下C++11對這種錯誤也沒辦法
1 | unique_ptr<FILE, int(*)(FILE *)>(fopen("log.txt", "w"), free); // Compile error |
另外一個發法是透過Template跟template specialization來解決
1 | template <typename T> |
這樣雖然可以解決,不過美增加一種Resource,就會增加一大堆類似的程式碼,因此,C++中罕見的Template template parameter就可以在此發揮所長。
可以參考Writing a Smart Handle class using template template parameters
1 | template <typename T> |
不過就算把fclose換成free也不會有任何警告,這問題還真是難解。
在之前提過了,可以透過unique_ptr跟custom destructor來達成同樣的目的。
1 | unique_ptr<FILE, int (*)(FILE *)> obj(fopen("log.txt", "w"), fclose); |
C++14之後,新增了make_unique
這個函數,我們可以仿造這方式,寫出一個make_resource
的函數。
參考這一篇C++14 and SDL2: Managing Resources寫來的。
1 | template<typename Creator, typename Destructor, typename... Arguments> |
這段程式碼的auto跟decltype已經有個抵了,部過decay還看不懂。有時間在研究吧
以往在C++98寫的Code,䅰習慣用Raw Pointer來操作Object,在C++11/14之後,有了更安全的面貌。少了new/delete之後,接觸到Memory Leak的機會變少了。
1 | deque<Object *> objs; |
現在可以這麼寫
1 | deque<unique_ptr<Object>> objs; |
C++11有make_shared
部過沒有make_unique
,到C++14才加入,部過我們可以打造個一模一樣的版本。
1 | template<typename T, typename ...Args> |
以往的寫法大概就像這樣
1 | deque<Object*>::iterator it = std::find_if(objs.begin(), objs.end(), [](const Object *obj) -> bool { ... }); |
最常望記得就是那個delete,然後就造成Memory leak。
新的寫法就像這樣
1 | auto it = std::find_if(objs.begin(), objs.end(), [](const unique_ptr<Object> &obj) -> bool { ...}); |
被指向的Object resource會在某個時間點被歸還。
這邊可分成兩部份,單純瀏覽整個Container中的Elemeent,不對Container作任何動作。
或是當作資料結構,會改變Container本身的狀態。
先從第一種來說明,以往可能這麼作
1 | for (auto it = objs.begin(); it != objs.end(); ++it) |
用了unique_ptr之後,只能這麼做了
1 | for (auto it = objs.begin(); it != objs.end(); ++it) |
如果要直接操作Container,像輕空Buffer queue的情形時,以前的作法
1 | while (!objs.empty()) |
不過由於unique_ptr不像auto_ptr擁有copy semantics,因此上面的程式碼要改成
1 | while (!objs.empty()) |
可以看到,跟Raw Pointer操作相差無幾,不過利用RAII技術減少Memory leak的發生。
這種檔案格式最近才流行起來,7zup可以直接解壓縮。
在Linux底下可以這麼作
1 | $ xz *.tar.xz |
chrono原先是來自於boost,現在進入C++11 Standard了。
鑽簡單的範例就是用來作高精密度的Timer使用。原先在Windows有QueryPerformanceCounter
的函數,可以精密到nanoseconds,在Liunx/BSD很難找到類似的解法,不過C++11把這納入標準了,不必花太多功夫。
以下是一個範例
1 | #include <iostream> |
更多的使用方法可以參考