muduo網路庫學習之Timestamp類、AtomicIntegerT 類封裝中的知識點
阿新 • • 發佈:2019-02-15
一、Timestamp類封裝
class Timestamp : public muduo::copyable,public boost::less_than_comparable<Timestamp> 類圖如下:
3、成員 microSecondsSinceEpoch_ 是現在這個時刻距離1970-01-01 00:00:00 (UTC 時間) 的微秒數 4、BOOST_STATIC_ASSERT 編譯時斷言 assert 執行時斷言 5、使用PRld64 int64_t 用來表示64位整數,在32位系統中是long long int,在64位系統中是long int,所以列印int64_t的格式化方法是:Timestamp 要求實現<, =,可自動實現>,<=,>=
printf(“%ld”, value); // 64bit OS
printf("%lld", value); // 32bit OS
跨平臺的做法:
#define __STDC_FORMAT_MACROS
#include <inttypes.h>
#undef __STDC_FORMAT_MACROS
printf("%" PRId64 "\n", value); 二、AtomicIntegerT 類封裝
class AtomicIntegerT : boost::noncopyable 類圖如下:
1、為什麼需要原子性操作?
x++; (x是共享變數)
從記憶體中讀x的值到暫存器中,對暫存器加1,再把新值寫回x所處的記憶體地址
(1)、假設是多核(multiprocessors)的情況,x 的初始值為5:
因為每個核都有自己獨立的暫存器,兩個執行緒同時訪問可能出現只加了一次的情況。
(2)、假設是單核的情況:
例如有兩個執行緒,它們按照如下順序執行(注意讀x和寫回x是原子操作,兩個執行緒不能同時執行(偽併發),是分時實現):
time Thread 1 Thread 2
load eax, x
load eax, x
add eax, 1
add eax, 1
store x, eax
store x, eax
我們會發現最終x的值會是1而不是2,Thread 1的結果被覆蓋掉了,因為Thread2在進行++之前以為x還是0,而不是1(每個執行緒都儲存自己的上下文包括暫存器的值,重新排程回Thread2時eax被載入為原來儲存的0)。
這種情況下我們就需要對x++這樣的操作加鎖(例如Pthread中的mutex)以保證同步,或者使用一些提供了atomic operations的庫,linux下的如atomic.h,下面會介紹部分函式。
2、gcc 原子性操作 // 原子自增操作type __sync_fetch_and_add (type *ptr, type value) type tmp = *ptr; *ptr += value; return tmp;
// 原子比較和設定操作
type __sync_val_compare_and_swap (type *ptr, type oldval, type newval) if (*ptr == oldval) {
*ptr = newval return oldval;} else return *ptr;
bool __sync_bool_compare_and_swap (type *ptr, type oldval, type newval) if (*ptr == oldval) {
*ptr = newval; return true;} else return false;
// 原子賦值操作
type __sync_lock_test_and_set (type *ptr, type value) type tmp = *ptr; *ptr = value; return tmp;
使用這些原子性操作,編譯的時候需要加-march=cpu-type 或者 -march = native 3、volatile 關鍵字 volatile的作用: 作為指令關鍵字,確保本條指令不會因編譯器的優化而省略,且要求每次直接讀值。簡單地說就是防止編譯器對程式碼進行優化。當要求使用volatile 宣告的變數的值的時候,系統總是重新從它所在的記憶體讀取資料,而不是使用儲存在暫存器中的備份。即使它前面的指令剛剛從該處讀取過資料,而且讀取的資料立刻被儲存。 補充:gcc/g++ 一些編譯選項 -Wall // 大部分警告
-Wextra // 一些額外的警告
-Werror // 當出現警告時轉為錯誤,停止編譯。(對應 -Wno-error)
-Wconversion // 一些可能改變值的隱式轉換,給出警告。
-Wno-unused-parameter // 函式中出現未使用的引數,不給出警告。
-Wold-style-cast // C風格的轉換,給出警告
-Woverloaded-virtual // 如果函式的宣告隱藏住了基類的虛擬函式,就給出警告。
-Wpointer-arith // 對函式指標或者void *型別的指標進行算術操作時給出警告
-Wshadow // 當一個區域性變數遮蓋住了另一個區域性變數,或者全域性變數時,給出警告。
-Wwrite-strings // 規定字串常量的型別是const char[length],因此,把這樣的地址複製給 non-const char *指標將產生警告. 這些警告能夠幫助你在編譯期間發現企圖寫入字串常量 的程式碼 -march=native // 指定cpu體系結構為本地平臺 注:本文對原子操作與鎖、volatile等討論比較基礎,更詳細的探討請參考這篇文章。 參考: muduo manual.pdf 《linux 多執行緒伺服器程式設計:使用muduo c++網路庫》