青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

OnTheWay2012
埋葬昨天的我,迎來(lái)重生的我!
posts - 15,  comments - 89,  trackbacks - 0
首先聲明:本文章是轉(zhuǎn)貼,為了防止自己忘記和別于查找。一切版權(quán)過(guò)作者所有。

0 前言

標(biāo)準(zhǔn)C++線程即將到來(lái)。CUJ預(yù)言它將衍生自Boost線程庫(kù),現(xiàn)在就由Bill帶領(lǐng)我們探索一下Boost線程庫(kù)。

就在幾年前,用多線程執(zhí)行程序還是一件非比尋常的事。然而今天互聯(lián)網(wǎng)應(yīng)用服務(wù)程序普遍使用多線程來(lái)提高與多客戶鏈接時(shí)的效率;為了達(dá)到最大的吞吐量,事務(wù)服務(wù)器在單獨(dú)的線程上運(yùn)行服務(wù)程序;GUI應(yīng)用程序?qū)⒛切┵M(fèi)時(shí),復(fù)雜的處理以線程的形式單獨(dú)運(yùn)行,以此來(lái)保證用戶界面能夠及時(shí)響應(yīng)用戶的操作。這樣使用多線程的例子還有很多。

但是C++標(biāo)準(zhǔn)并沒(méi)有涉及到多線程,這讓程序員們開始懷疑是否可能寫出多線程的C++程序。盡管不可能寫出符合標(biāo)準(zhǔn)的多線程程序,但是程序員們還是會(huì)使用支持多線程的操作系統(tǒng)提供的多線程庫(kù)來(lái)寫出多線程C++程序。但是這樣做至少有兩個(gè)問(wèn)題:這些庫(kù)大部分都是用C語(yǔ)言完成的,如果在C++程序中要使用這些庫(kù)就必須十分小心;還有,每一個(gè)操作系統(tǒng)都有自己的一套支持多線程的類庫(kù)。因此,這樣寫出來(lái)得代碼是沒(méi)有標(biāo)準(zhǔn)可循的,也不是到處都適用的(non-portable)。Boost線程庫(kù)就是為了解決所有這些問(wèn)題而設(shè)計(jì)的。

Boost是由C++標(biāo)準(zhǔn)委員會(huì)類庫(kù)工作組成員發(fā)起,致力于為C++開發(fā)新的類庫(kù)的組織?,F(xiàn)在它已經(jīng)有近2000名成員。許多庫(kù)都可以在Boost源碼的發(fā)布版本中找到。為了使這些類庫(kù)是線程安全的(thread-safe),Boost線程庫(kù)被創(chuàng)建了。

許多C++專家都投身于Boost線程庫(kù)的開發(fā)中。所有接口的設(shè)計(jì)都是從0開始的,并不是C線程API的簡(jiǎn)單封裝。許多C++特性(比如構(gòu)造函數(shù)和析構(gòu)函數(shù),函數(shù)對(duì)象(function object)和模板)都被使用在其中以使接口更加靈活?,F(xiàn)在的版本可以在POSIX,Win32和Macintosh Carbon平臺(tái)下工作。

1 創(chuàng)建線程

就像std::fstream類就代表一個(gè)文件一樣,boost::thread類就代表一個(gè)可執(zhí)行的線程。缺省構(gòu)造函數(shù)創(chuàng)建一個(gè)代表當(dāng)前執(zhí)行線程的實(shí)例。一個(gè)重載的構(gòu)造函數(shù)以一個(gè)不需任何參數(shù)的函數(shù)對(duì)象作為參數(shù),并且沒(méi)有返回值。這個(gè)構(gòu)造函數(shù)創(chuàng)建一個(gè)新的可執(zhí)行線程,它調(diào)用了那個(gè)函數(shù)對(duì)象。

起先,大家認(rèn)為傳統(tǒng)C創(chuàng)建線程的方法似乎比這樣的設(shè)計(jì)更有用,因?yàn)镃創(chuàng)建線程的時(shí)候會(huì)傳入一個(gè)void*指針,通過(guò)這種方法就可以傳入數(shù)據(jù)。然而,由于Boost線程庫(kù)是使用函數(shù)對(duì)象來(lái)代替函數(shù)指針,那么函數(shù)對(duì)象本身就可以攜帶線程所需的數(shù)據(jù)。這種方法更具靈活性,也是類型安全(type-safe)的。當(dāng)和Boost.Bind這樣的功能庫(kù)一起使用時(shí),這樣的方法就可以讓你傳遞任意數(shù)量的數(shù)據(jù)給新建的線程。

目前,由Boost線程庫(kù)創(chuàng)建的線程對(duì)象功能還不是很強(qiáng)大。事實(shí)上它只能做兩項(xiàng)操作。線程對(duì)象可以方便使用==和!=進(jìn)行比較來(lái)確定它們是否是代表同一個(gè)線程;你還可以調(diào)用boost::thread::join來(lái)等待線程執(zhí)行完畢。其他一些線程庫(kù)可以讓你對(duì)線程做一些其他操作(比如設(shè)置優(yōu)先級(jí),甚至是取消線程)。然而,由于要在普遍適用(portable)的接口中加入這些操作不是簡(jiǎn)單的事,目前仍在討論如何將這些操組加入到Boost線程庫(kù)中。

Listing1展示了boost::thread類的一個(gè)最簡(jiǎn)單的用法。 新建的線程只是簡(jiǎn)單的在std::out上打印“hello,world”,main函數(shù)在它執(zhí)行完畢之后結(jié)束。


例1:

#include <boost/thread/thread.hpp>
#include <iostream>
void hello()
{
std::cout <<
"Hello world, I'm a thread!"
<< std::endl;
}
int main(int argc, char* argv[])
{
boost::thread thrd(&hello);
thrd.join();
return 0;
}

2 互斥體

任何寫過(guò)多線程程序的人都知道避免不同線程同時(shí)訪問(wèn)共享區(qū)域的重要性。如果一個(gè)線程要改變共享區(qū)域中某個(gè)數(shù)據(jù),而與此同時(shí)另一線程正在讀這個(gè)數(shù)據(jù),那么結(jié)果將是未定義的。為了避免這種情況的發(fā)生就要使用一些特殊的原始類型和操作。其中最基本的就是互斥體(mutex,mutual exclusion的縮寫)。一個(gè)互斥體一次只允許一個(gè)線程訪問(wèn)共享區(qū)。當(dāng)一個(gè)線程想要訪問(wèn)共享區(qū)時(shí),首先要做的就是鎖?。╨ock)互斥體。如果其他的線程已經(jīng)鎖住了互斥體,那么就必須先等那個(gè)線程將互斥體解鎖,這樣就保證了同一時(shí)刻只有一個(gè)線程能訪問(wèn)共享區(qū)域。

互斥體的概念有不少變種。Boost線程庫(kù)支持兩大類互斥體,包括簡(jiǎn)單互斥體(simple mutex)和遞歸互斥體(recursive mutex)。如果同一個(gè)線程對(duì)互斥體上了兩次鎖,就會(huì)發(fā)生死鎖(deadlock),也就是說(shuō)所有的等待解鎖的線程將一直等下去。有了遞歸互斥體,單個(gè)線程就可以對(duì)互斥體多次上鎖,當(dāng)然也必須解鎖同樣次數(shù)來(lái)保證其他線程可以對(duì)這個(gè)互斥體上鎖。

在這兩大類互斥體中,對(duì)于線程如何上鎖還有多個(gè)變種。一個(gè)線程可以有三種方法來(lái)對(duì)一個(gè)互斥體加鎖:

  1. 一直等到?jīng)]有其他線程對(duì)互斥體加鎖。
  2. 如果有其他互斥體已經(jīng)對(duì)互斥體加鎖就立即返回。
  3. 一直等到?jīng)]有其他線程互斥體加鎖,直到超時(shí)。

似乎最佳的互斥體類型是遞歸互斥體,它可以使用所有三種上鎖形式。然而每一個(gè)變種都是有代價(jià)的。所以Boost線程庫(kù)允許你根據(jù)不同的需要使用最有效率的互斥體類型。Boost線程庫(kù)提供了6中互斥體類型,下面是按照效率進(jìn)行排序:

boost::mutex,
boost::try_mutex,
boost::timed_mutex,
boost::recursive_mutex,
boost::recursive_try_mutex,
boost::recursive_timed_mutex 
如果互斥體上鎖之后沒(méi)有解鎖就會(huì)發(fā)生死鎖。這是一個(gè)很普遍的錯(cuò)誤,Boost線程庫(kù)就是要將其變成不可能(至少時(shí)很困難)。直接對(duì)互斥體上鎖和解鎖對(duì)于Boost線程庫(kù)的用戶來(lái)說(shuō)是不可能的。mutex類通過(guò)teypdef定義在RAII中實(shí)現(xiàn)的類型來(lái)實(shí)現(xiàn)互斥體的上鎖和解鎖。這也就是大家知道的Scope Lock模式。為了構(gòu)造這些類型,要傳入一個(gè)互斥體的引用。構(gòu)造函數(shù)對(duì)互斥體加鎖,析構(gòu)函數(shù)對(duì)互斥體解鎖。C++保證了析構(gòu)函數(shù)一定會(huì)被調(diào)用,所以即使是有異常拋出,互斥體也總是會(huì)被正確的解鎖。

這種方法保證正確的使用互斥體。然而,有一點(diǎn)必須注意:盡管Scope Lock模式可以保證互斥體被解鎖,但是它并沒(méi)有保證在異常拋出之后貢獻(xiàn)資源仍是可用的。所以就像執(zhí)行單線程程序一樣,必須保證異常不會(huì)導(dǎo)致程序狀態(tài)異常。另外,這個(gè)已經(jīng)上鎖的對(duì)象不能傳遞給另一個(gè)線程,因?yàn)樗鼈兙S護(hù)的狀態(tài)并沒(méi)有禁止這樣做。

List2給出了一個(gè)使用boost::mutex的最簡(jiǎn)單的例子。例子中共創(chuàng)建了兩個(gè)新的線程,每個(gè)線程都有10次循環(huán),在std::cout上打印出線程id和當(dāng)前循環(huán)的次數(shù),而main函數(shù)等待這兩個(gè)線程執(zhí)行完才結(jié)束。std::cout就是共享資源,所以每一個(gè)線程都使用一個(gè)全局互斥體來(lái)保證同時(shí)只有一個(gè)線程能向它寫入。

許多讀者可能已經(jīng)注意到List2中傳遞數(shù)據(jù)給線程還必須的手工寫一個(gè)函數(shù)。盡管這個(gè)例子很簡(jiǎn)單,如果每一次都要寫這樣的代碼實(shí)在是讓人厭煩的事。別急,有一種簡(jiǎn)單的解決辦法。函數(shù)庫(kù)允許你通過(guò)將另一個(gè)函數(shù)綁定,并傳入調(diào)用時(shí)需要的數(shù)據(jù)來(lái)創(chuàng)建一個(gè)新的函數(shù)。 List3向你展示了如何使用Boost.Bind庫(kù)來(lái)簡(jiǎn)化List2中的代碼,這樣就不必手工寫這些函數(shù)對(duì)象了。

例2:

#include <boost/thread/thread.hpp>
#include <boost/thread/mutex.hpp>
#include <iostream>
boost::mutex io_mutex;
struct count
{
count(int id) : id(id) { }
void operator()()
{
for (int i = 0; i < 10; ++i)
{
boost::mutex::scoped_lock
lock(io_mutex);
std::cout << id << ": "
<< i << std::endl;
}
}
int id;
};
int main(int argc, char* argv[])
{
boost::thread thrd1(count(1));
boost::thread thrd2(count(2));
thrd1.join();
thrd2.join();
return 0;
}

例3: // 這個(gè)例子和例2一樣,除了使用Boost.Bind來(lái)簡(jiǎn)化創(chuàng)建線程攜帶數(shù)據(jù),避免使用函數(shù)對(duì)象

#include <boost/thread/thread.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/bind.hpp>
#include <iostream>
boost::mutex io_mutex;
void count(int id)
{
for (int i = 0; i < 10; ++i)
{
boost::mutex::scoped_lock
lock(io_mutex);
std::cout << id << ": " <<
i << std::endl;
}
}
int main(int argc, char* argv[])
{
boost::thread thrd1(
boost::bind(&count, 1));
boost::thread thrd2(
boost::bind(&count, 2));
thrd1.join();
thrd2.join();
return 0;
}

3 條件變量

有的時(shí)候僅僅依靠鎖住共享資源來(lái)使用它是不夠的。有時(shí)候共享資源只有某些狀態(tài)的時(shí)候才能夠使用。比方說(shuō),某個(gè)線程如果要從堆棧中讀取數(shù)據(jù),那么如果棧中沒(méi)有數(shù)據(jù)就必須等待數(shù)據(jù)被壓棧。這種情況下的同步使用互斥體是不夠的。另一種同步的方式--條件變量,就可以使用在這種情況下。

條件變量的使用總是和互斥體及共享資源聯(lián)系在一起的。線程首先鎖住互斥體,然后檢驗(yàn)共享資源的狀態(tài)是否處于可使用的狀態(tài)。如果不是,那么線程就要等待條件變量。要指向這樣的操作就必須在等待的時(shí)候?qū)⒒コ怏w解鎖,以便其他線程可以訪問(wèn)共享資源并改變其狀態(tài)。它還得保證從等到得線程返回時(shí)互斥體是被上鎖得。當(dāng)另一個(gè)線程改變了共享資源的狀態(tài)時(shí),它就要通知正在等待條件變量得線程,并將之返回等待的線程。

List4是一個(gè)使用了boost::condition的簡(jiǎn)單例子。有一個(gè)實(shí)現(xiàn)了有界緩存區(qū)的類和一個(gè)固定大小的先進(jìn)先出的容器。由于使用了互斥體boost::mutex,這個(gè)緩存區(qū)是線程安全的。put和get使用條件變量來(lái)保證線程等待完成操作所必須的狀態(tài)。有兩個(gè)線程被創(chuàng)建,一個(gè)在buffer中放入100個(gè)整數(shù),另一個(gè)將它們從buffer中取出。這個(gè)有界的緩存一次只能存放10個(gè)整數(shù),所以這兩個(gè)線程必須周期性的等待另一個(gè)線程。為了驗(yàn)證這一點(diǎn),put和get在std::cout中輸出診斷語(yǔ)句。最后,當(dāng)兩個(gè)線程結(jié)束后,main函數(shù)也就執(zhí)行完畢了。

#include <boost/thread/thread.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/condition.hpp>
#include <iostream>
const int BUF_SIZE = 10;
const int ITERS = 100;
boost::mutex io_mutex;
class buffer
{
public:
typedef boost::mutex::scoped_lock
scoped_lock;
buffer()
: p(0), c(0), full(0)
{
}
void put(int m)
{
scoped_lock lock(mutex);
if (full == BUF_SIZE)
{
{
boost::mutex::scoped_lock
lock(io_mutex);
std::cout <<
"Buffer is full. Waiting..."
<< std::endl;
}
while (full == BUF_SIZE)
cond.wait(lock);
}
buf[p] = m;
p = (p+1) % BUF_SIZE;
++full;
cond.notify_one();
}
int get()
{
scoped_lock lk(mutex);
if (full == 0)
{
{
boost::mutex::scoped_lock
lock(io_mutex);
std::cout <<
"Buffer is empty. Waiting..."
<< std::endl;
}
while (full == 0)
cond.wait(lk);
}
int i = buf[c];
c = (c+1) % BUF_SIZE;
--full;
cond.notify_one();
return i;
}
private:
boost::mutex mutex;
boost::condition cond;
unsigned int p, c, full;
int buf[BUF_SIZE];
};
buffer buf;
void writer()
{
for (int n = 0; n < ITERS; ++n)
{
{
boost::mutex::scoped_lock
lock(io_mutex);
std::cout << "sending: "
<< n << std::endl;
}
buf.put(n);
}
}
void reader()
{
for (int x = 0; x < ITERS; ++x)
{
int n = buf.get();
{
boost::mutex::scoped_lock
lock(io_mutex);
std::cout << "received: "
<< n << std::endl;
}
}
}
int main(int argc, char* argv[])
{
boost::thread thrd1(&reader);
boost::thread thrd2(&writer);
thrd1.join();
thrd2.join();
return 0;
}

4 線程局部存儲(chǔ)

大多數(shù)函數(shù)都不是可重入的。這也就是說(shuō)在某一個(gè)線程已經(jīng)調(diào)用了一個(gè)函數(shù)時(shí),如果你再調(diào)用同一個(gè)函數(shù),那么這樣是不安全的。一個(gè)不可重入的函數(shù)通過(guò)連續(xù)的調(diào)用來(lái)保存靜態(tài)變量或者是返回一個(gè)指向靜態(tài)數(shù)據(jù)的指針。 舉例來(lái)說(shuō),std::strtok就是不可重入的,因?yàn)樗褂渺o態(tài)變量來(lái)保存要被分割成符號(hào)的字符串。

有兩種方法可以讓不可重用的函數(shù)變成可重用的函數(shù)。第一種方法就是改變接口,用指針或引用代替原先使用靜態(tài)數(shù)據(jù)的地方。比方說(shuō),POSIX定義了strok_r,std::strtok中的一個(gè)可重入的變量,它用一個(gè)額外的char**參數(shù)來(lái)代替靜態(tài)數(shù)據(jù)。這種方法很簡(jiǎn)單,而且提供了可能的最佳效果。但是這樣必須改變公共接口,也就意味著必須改代碼。另一種方法不用改變公有接口,而是用本地存儲(chǔ)線程(thread local storage)來(lái)代替靜態(tài)數(shù)據(jù)(有時(shí)也被成為特殊線程存儲(chǔ),thread-specific storage)。

Boost線程庫(kù)提供了智能指針boost::thread_specific_ptr來(lái)訪問(wèn)本地存儲(chǔ)線程。每一個(gè)線程第一次使用這個(gè)智能指針的實(shí)例時(shí),它的初值是NULL,所以必須要先檢查這個(gè)它的只是否為空,并且為它賦值。Boost線程庫(kù)保證本地存儲(chǔ)線程中保存的數(shù)據(jù)會(huì)在線程結(jié)束后被清除。

List5是一個(gè)使用boost::thread_specific_ptr的簡(jiǎn)單例子。其中創(chuàng)建了兩個(gè)線程來(lái)初始化本地存儲(chǔ)線程,并有10次循環(huán),每一次都會(huì)增加智能指針指向的值,并將其輸出到std::cout上(由于std::cout是一個(gè)共享資源,所以通過(guò)互斥體進(jìn)行同步)。main線程等待這兩個(gè)線程結(jié)束后就退出。從這個(gè)例子輸出可以明白的看出每個(gè)線程都處理屬于自己的數(shù)據(jù)實(shí)例,盡管它們都是使用同一個(gè)boost::thread_specific_ptr。

例5:

#include <boost/thread/thread.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/tss.hpp>
#include <iostream>
boost::mutex io_mutex;
boost::thread_specific_ptr<int> ptr;
struct count
{
count(int id) : id(id) { }
void operator()()
{
if (ptr.get() == 0)
ptr.reset(new int(0));
for (int i = 0; i < 10; ++i)
{
(*ptr)++;
boost::mutex::scoped_lock
lock(io_mutex);
std::cout << id << ": "
<< *ptr << std::endl;
}
}
int id;
};
int main(int argc, char* argv[])
{
boost::thread thrd1(count(1));
boost::thread thrd2(count(2));
thrd1.join();
thrd2.join();
return 0;
}

5 僅運(yùn)行一次的例程

還有一個(gè)問(wèn)題沒(méi)有解決:如何使得初始化工作(比如說(shuō)構(gòu)造函數(shù))也是線程安全的。比方說(shuō),如果一個(gè)引用程序要產(chǎn)生唯一的全局的對(duì)象,由于實(shí)例化順序的問(wèn)題,某個(gè)函數(shù)會(huì)被調(diào)用來(lái)返回一個(gè)靜態(tài)的對(duì)象,它必須保證第一次被調(diào)用時(shí)就產(chǎn)生這個(gè)靜態(tài)的對(duì)象。這里的問(wèn)題就是如果多個(gè)線程同時(shí)調(diào)用了這個(gè)函數(shù),那么這個(gè)靜態(tài)對(duì)象的構(gòu)造函數(shù)就會(huì)被調(diào)用多次,這樣錯(cuò)誤產(chǎn)生了。

解決這個(gè)問(wèn)題的方法就是所謂的“一次實(shí)現(xiàn)”(once routine)。“一次實(shí)現(xiàn)”在一個(gè)應(yīng)用程序只能執(zhí)行一次。如果多個(gè)線程想同時(shí)執(zhí)行這個(gè)操作,那么真正執(zhí)行的只有一個(gè),而其他線程必須等這個(gè)操作結(jié)束。為了保證它只被執(zhí)行一次,這個(gè)routine由另一個(gè)函數(shù)間接的調(diào)用,而這個(gè)函數(shù)傳給它一個(gè)指針以及一個(gè)標(biāo)志著這個(gè)routine是否已經(jīng)被調(diào)用的特殊標(biāo)志。這個(gè)標(biāo)志是以靜態(tài)的方式初始化的,這也就保證了它在編譯期間就被初始化而不是運(yùn)行時(shí)。因此也就沒(méi)有多個(gè)線程同時(shí)將它初始化的問(wèn)題了。Boost線程庫(kù)提供了boost::call_once來(lái)支持“一次實(shí)現(xiàn)”,并且定義了一個(gè)標(biāo)志boost::once_flag及一個(gè)初始化這個(gè)標(biāo)志的宏BOOST_ONCE_INIT。

List6是一個(gè)使用了boost::call_once的例子。其中定義了一個(gè)靜態(tài)的全局整數(shù),初始值為0;還有一個(gè)由BOOST_ONCE_INIT初始化的靜態(tài)boost::once_flag實(shí)例。main函數(shù)創(chuàng)建了兩個(gè)線程,它們都想通過(guò)傳入一個(gè)函數(shù)調(diào)用boost::call_once來(lái)初始化這個(gè)全局的整數(shù),這個(gè)函數(shù)是將它加1。main函數(shù)等待著兩個(gè)線程結(jié)束,并將最后的結(jié)果輸出的到std::cout。由最后的結(jié)果可以看出這個(gè)操作確實(shí)只被執(zhí)行了一次,因?yàn)樗闹凳?。

#include <boost/thread/thread.hpp>
#include <boost/thread/once.hpp>
#include <iostream>
int i = 0;
boost::once_flag flag =
BOOST_ONCE_INIT;
void init()
{
++i;
}
void thread()
{
boost::call_once(&init, flag);
}
int main(int argc, char* argv[])
{
boost::thread thrd1(&thread);
boost::thread thrd2(&thread);
thrd1.join();
thrd2.join();
std::cout << i << std::endl;
return 0;
}

6 Boost線程庫(kù)的未來(lái)

Boost線程庫(kù)正在計(jì)劃加入一些新特性。其中包括boost::read_write_mutex,它可以讓多個(gè)線程同時(shí)從共享區(qū)中讀取數(shù)據(jù),但是一次只可能有一個(gè)線程向共享區(qū)寫入數(shù)據(jù);boost::thread_barrier,它使得一組線程處于等待狀態(tài),知道所有得線程都都進(jìn)入了屏障區(qū);boost::thread_pool,他允許執(zhí)行一些小的routine而不必每一都要?jiǎng)?chuàng)建或是銷毀一個(gè)線程。

Boost線程庫(kù)已經(jīng)作為標(biāo)準(zhǔn)中的類庫(kù)技術(shù)報(bào)告中的附件提交給C++標(biāo)準(zhǔn)委員會(huì),它的出現(xiàn)也為下一版C++標(biāo)準(zhǔn)吹響了第一聲號(hào)角。委員會(huì)成員對(duì)Boost線程庫(kù)的初稿給予了很高的評(píng)價(jià),當(dāng)然他們還會(huì)考慮其他的多線程庫(kù)。他們對(duì)在C++標(biāo)準(zhǔn)中加入對(duì)多線程的支持非常感興趣。從這一點(diǎn)上也可以看出,多線程在C++中的前途一片光明。

posted on 2010-06-18 22:23 OnTheWay 閱讀(297) 評(píng)論(0)  編輯 收藏 引用

只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。
網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問(wèn)   Chat2DB   管理



<2025年11月>
2627282930311
2345678
9101112131415
16171819202122
23242526272829
30123456

常用鏈接

留言簿(4)

隨筆分類

隨筆檔案

友情連接

搜索

  •  

最新評(píng)論

閱讀排行榜

評(píng)論排行榜

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            久久人人爽人人| 国产欧美日韩免费看aⅴ视频| 欧美午夜激情视频| 亚洲高清网站| 亚洲性线免费观看视频成熟| 久热精品视频在线观看| 一本色道久久综合亚洲精品小说 | 一本大道久久a久久综合婷婷| 久久国产精品久久久久久电车| 亚洲国产精品va在线观看黑人| 亚洲免费观看| 亚洲综合国产| 亚洲调教视频在线观看| 亚洲国产精品va在看黑人| 久久婷婷国产综合精品青草| 国产精品xxx在线观看www| 狠狠色香婷婷久久亚洲精品| 亚洲一二三区精品| 日韩视频在线一区| 欧美国产日本| 欲色影视综合吧| 久久久美女艺术照精彩视频福利播放| 一区二区三区欧美日韩| 欧美日韩视频一区二区三区| 日韩一区二区精品葵司在线| 亚洲激情成人在线| 欧美国产视频在线| 亚洲人成在线免费观看| 欧美高清hd18日本| 牛牛影视久久网| 日韩小视频在线观看| 亚洲国产电影| 欧美精品 国产精品| 亚洲视频在线一区观看| 在线综合亚洲| 国产一区二区三区av电影 | 国产一区二区三区电影在线观看| 欧美在线亚洲综合一区| 久久激情视频| 亚洲国产专区校园欧美| 亚洲精品女人| 欧美日韩p片| 亚洲欧美日韩视频一区| 欧美视频不卡| 欧美一级专区| 久久久久久久999精品视频| 亚洲精品社区| 亚洲免费在线观看| 国产一区导航| 91久久久亚洲精品| 国产精品视频第一区| 久久欧美中文字幕| 欧美日韩国产系列| 久久精品一级爱片| 欧美激情视频一区二区三区在线播放| 亚洲视频碰碰| 久久三级福利| 亚洲欧美日本日韩| 久久久av网站| 亚洲永久在线| 欧美大尺度在线| 久久国产欧美精品| 欧美日韩免费观看中文| 米奇777在线欧美播放| 欧美日韩国语| 免费在线观看日韩欧美| 国产精品午夜电影| 亚洲美女在线视频| 悠悠资源网久久精品| 香蕉久久夜色精品| 亚洲主播在线| 欧美精品一区二区三区一线天视频 | 久久三级福利| 欧美专区福利在线| 欧美天天视频| 99re热这里只有精品视频 | 亚洲无线视频| 欧美日韩国产影院| 亚洲福利在线看| 国产中文一区| 午夜在线观看欧美| 亚洲欧美视频在线观看视频| 欧美紧缚bdsm在线视频| 亚洲国产毛片完整版| 亚洲国产裸拍裸体视频在线观看乱了| 亚洲免费综合| 午夜精品在线观看| 欧美天堂亚洲电影院在线播放 | 欧美激情在线观看| 亚洲区中文字幕| 免费视频一区二区三区在线观看| 久久综合伊人| 亚洲国产精品一区二区第一页| 久久精品人人做人人综合| 久久中文字幕一区二区三区| 国内精品久久久久影院色| 一本色道久久综合狠狠躁的推荐| 一本色道久久综合亚洲91| 欧美黄色影院| 一区二区精品在线| 欧美一区网站| 狠狠色狠狠色综合系列| 久久亚洲精品网站| 亚洲国产婷婷综合在线精品 | 国产热re99久久6国产精品| 亚洲欧美视频在线观看| 久久久综合精品| 精品成人在线视频| 欧美成人精品| 亚洲一区二区在线播放| 葵司免费一区二区三区四区五区| 亚洲激情午夜| 美女主播视频一区| 狠狠色丁香婷婷综合影院| 麻豆久久婷婷| 亚洲一区欧美二区| 欧美91福利在线观看| 亚洲一级一区| 尤物99国产成人精品视频| 欧美日韩一区二区视频在线观看| 亚洲一区二区成人在线观看| 欧美jizz19性欧美| 亚洲专区欧美专区| 亚洲激情视频在线观看| 国产精品亚洲不卡a| 欧美第一黄网免费网站| 午夜久久久久| 亚洲看片免费| 欧美不卡激情三级在线观看| 在线亚洲免费视频| 在线日韩电影| 国产免费成人av| 欧美色播在线播放| 欧美xx69| 另类av导航| 久久激情视频| 欧美一区二区高清| 亚洲天堂久久| 91久久精品久久国产性色也91| 久久久www| 欧美一区二区三区在线观看视频| 日韩午夜电影av| 亚洲国产视频一区二区| 亚洲欧洲日韩在线| 欧美精品久久久久久久| 亚洲影音一区| 亚洲国产成人在线播放| 美乳少妇欧美精品| 久久精品视频在线观看| 午夜欧美大尺度福利影院在线看| 夜夜嗨av一区二区三区| 日韩视频在线一区| 亚洲国产欧美精品| 亚洲第一区色| 久久综合网络一区二区| 久久精品国产第一区二区三区最新章节 | 蜜桃av一区| 另类成人小视频在线| 久久久欧美一区二区| 久久婷婷亚洲| 牛夜精品久久久久久久99黑人| 免费观看日韩av| 欧美欧美午夜aⅴ在线观看| 免费欧美电影| 欧美视频在线观看视频极品| 国产精品成人一区| 国产精品有限公司| 国产综合第一页| 亚洲高清视频中文字幕| 亚洲美女毛片| 亚洲伊人第一页| 久久激五月天综合精品| 另类图片国产| 亚洲靠逼com| 午夜精品久久久久影视 | 99热在这里有精品免费| 亚洲一区二区视频在线观看| 久久精品91| 欧美区亚洲区| 国产视频一区二区在线观看| 亚洲高清资源综合久久精品| 99国产精品久久久久久久| 欧美一区精品| 亚洲国产日韩一区二区| 亚洲制服av| 欧美成人精品在线| 国产欧美精品在线观看| 亚洲精品国产精品乱码不99| 亚洲永久视频| 亚洲国产精品一区二区尤物区 | 免费亚洲一区二区| 一区二区三区四区在线| 欧美一区二区三区电影在线观看| 欧美国产专区| 韩国女主播一区| 一本在线高清不卡dvd| 欧美在线免费一级片| 欧美日韩日日骚| 在线电影国产精品| 欧美一区亚洲一区|