《深入理解Android卷 I》- 第五章 - 理解常見類 - 讀書筆記

1 RefBase, sp, wp

在Android中,RefBase結(jié)合sp和wp旺入,實(shí)現(xiàn)了一套通過引用計(jì)數(shù)的方法來控制對(duì)象生命周期的機(jī)制而姐。

1.1 初識(shí)影子對(duì)象

refBase是實(shí)現(xiàn)引用計(jì)數(shù)的基類坑夯,提供引用計(jì)數(shù)的方法喂窟。簡單示例:

class A: public RefBase {
  //..
}
int main() {
  A* pA = new A;
  {
    //sp庐椒,wp對(duì)象是在{}中創(chuàng)建的椒舵,下面的代碼先創(chuàng)建sp,然后創(chuàng)建wp
    sp<A>spA(A);
    wp<A>wpA(spA);
    //大括號(hào)結(jié)束前约谈,先析構(gòu)wp,再析構(gòu)sp
  }
}

1.1.1 RefBase和它的影子

示例代碼中 class A繼承自RefBase,使用的是RefBase的構(gòu)造函數(shù)

system/core/libutils/RefBase.cpp

RefBase::RefBase()
    : mRefs(new weakref_impl(this)){
    }

mRefsRefBase的內(nèi)部類weakref_type的子類weakref_impl的實(shí)例笔宿,保存在RefBase中的一個(gè)字段。

class RefBase::weakref_impl : public RefBase::weakref_type {
public:
    std::atomic<int32_t>    mStrong;
    std::atomic<int32_t>    mWeak;
    RefBase* const          mBase;
    std::atomic<int32_t>    mFlags;
  
    weakref_impl(RefBase* base)
        : mStrong(INITIAL_STRONG_VALUE)
        , mWeak(0)
        , mBase(base)
        , mFlags(0)
        , mStrongRefs(NULL)
        , mWeakRefs(NULL)
        , mTrackEnabled(!!DEBUG_REFS_ENABLED_BY_DEFAULT)
        , mRetain(false)
    {
    }
}

通過上面代碼可知棱诱,在創(chuàng)建A對(duì)象的同時(shí)也創(chuàng)建了一個(gè)weakref_type對(duì)象泼橘,稱為影子。

影子中的兩個(gè)字段就關(guān)系對(duì)象的生死迈勋。

1.1.2 sp

system/core/include/utils/StrongPointer.h

繼續(xù)查看實(shí)例代碼中構(gòu)造一個(gè)sp引用sp<A> spA(A)

template<typename T>
sp<T>::sp(T* other)
        : m_ptr(other) {
    if (other)
        other->incStrong(this);
}

其中T必須繼承自RefBase,構(gòu)建sp引用后代碼就執(zhí)行了inctrong(this)炬灭,該方法是RefBase提供

system/core/libutils/RefBase.cpp

void RefBase::incStrong(const void* id) const {
  //mRefs是RefBase中的字段,在RefBase構(gòu)造函數(shù)執(zhí)行時(shí)賦值  
  weakref_impl* const refs = mRefs;
  //先增加弱引用計(jì)數(shù)
  refs->incWeak(id);
  //空實(shí)現(xiàn)粪躬,無視
  refs->addStrongRef(id);
  //原子操作担败,強(qiáng)引用增加1
  const int32_t c = refs->mStrong.fetch_add(1,std::memory_order_relaxed);
#if PRINT_REFS
  ALOGD("incStrong of %p from %p: cnt=%d\n", this, id, c);
#endif
  //判斷是否為初識(shí)值
  if (c != INITIAL_STRONG_VALUE)  {
      return;
  }
 //是第一引用就會(huì)執(zhí)行下面的代碼
  //設(shè)置初識(shí)值
  int32_t old = refs->mStrong.fetch_sub(INITIAL_STRONG_VALUE,
            std::memory_order_relaxed);
  // A decStrong() must still happen after us.
  ALOG_ASSERT(old > INITIAL_STRONG_VALUE, "0x%x too small", old);
  /*如果是第一次引用,則調(diào)用onFirstRef()
  這個(gè)函數(shù)很重要镰官,派生類可以重載這個(gè)函數(shù)提前,完成一些初始化工作。*/
  refs->mBase->onFirstRef();
}

incWeak(id)函數(shù)

void RefBase::weakref_type::incWeak(const void* id) {
    weakref_impl* const impl = static_cast<weakref_impl*>(this);
    //空實(shí)現(xiàn)泳唠,無視
    impl->addWeakRef(id);
    //原子操作狈网,弱引用增加1
    const int32_t c __unused = impl->mWeak.fetch_add(1,
            std::memory_order_relaxed);
}

sp構(gòu)造完成后RefBaseweakref_impl實(shí)例的強(qiáng)弱引用都增加了1.

wp構(gòu)造完成又是什么樣的?

system/core/include/utils/RefBase.h

template<typename T>
wp<T>::wp(T* other)
    : m_ptr(other) //m_ptr就是繼承RefBase的實(shí)際對(duì)象
{
    //調(diào)用pA的createWeak,并且保存返回值到成員變量m_refs中
    if (other) m_refs = other->createWeak(this);
}
RefBase::weakref_type* RefBase::createWeak(const void* id) const
{   
    //mRefs就是那個(gè)new出來的weakref_impl實(shí)例
    //增加弱引用加1
    mRefs->incWeak(id);
    return mRefs;
}

回到最初的示例代碼笨腥,在構(gòu)造完wp后拓哺,A對(duì)象的影子對(duì)象mRefs中的mWeak增加了2,mStrong只增加了1脖母。

wp中有兩個(gè)成員變量士鸥,一個(gè)保存實(shí)際對(duì)象,另一個(gè)保存影子對(duì)象谆级。sp只有一個(gè)成員變量用來保存實(shí)際對(duì)象烤礁,但這個(gè)實(shí)際對(duì)象內(nèi)部已包含了對(duì)應(yīng)的影子對(duì)象。

1.1.3 wp,sp析構(gòu)

還是最初的回到實(shí)例代碼里肥照,我們是在代碼塊中創(chuàng)建的sp<A> spAwp<A> wpA兩個(gè)對(duì)象脚仔,更具代碼的執(zhí)行,除了代碼塊舆绎,兩個(gè)對(duì)象的析構(gòu)函數(shù)就會(huì)被調(diào)用鲤脏。

system/core/include/utils/RefBase.h

wp<T>::~wp()
{   
    //調(diào)用影子對(duì)象的decWeak,由影子對(duì)象的基類實(shí)現(xiàn)
    if (m_ptr) m_refs->decWeak(this);
}

system/core/libutils/RefBase.cpp

void RefBase::weakref_type::decWeak(const void* id)
{
    weakref_impl* const impl = static_cast<weakref_impl*>(this);
    //空實(shí)現(xiàn),無視
    impl->removeWeakRef(id);
    //原子操作猎醇,計(jì)數(shù)減一
    const int32_t c = impl->mWeak.fetch_sub(1,std::memory_order_release);
   
    if (c != 1) return;
    atomic_thread_fence(std::memory_order_acquire);

    int32_t flags = impl->mFlags.load(std::memory_order_relaxed);
    //如果c為1窥突,則弱引用計(jì)數(shù)為0,這說明沒用弱引用指向?qū)嶋H對(duì)象姑食,需要考慮是否釋放內(nèi)存
    // OBJECT_LIFETIME_XXX和生命周期有關(guān)系
    if ((flags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_STRONG) {
        // This is the regular lifetime case. The object is destroyed
        // when the last strong reference goes away. Since weakref_impl
        // outlives the object, it is not destroyed in the dtor, and
        // we'll have to do it here.
        if (impl->mStrong.load(std::memory_order_relaxed)
                == INITIAL_STRONG_VALUE) {
            // Decrementing a weak count to zero when object never had a strong
            // reference.  We assume it acquired a weak reference early, e.g.
            // in the constructor, and will eventually be properly destroyed,
            // usually via incrementing and decrementing the strong count.
            // Thus we no longer do anything here.  We log this case, since it
            // seems to be extremely rare, and should not normally occur. We
            // used to deallocate mBase here, so this may now indicate a leak.
            ALOGW("RefBase: Object at %p lost last weak reference "
                    "before it had a strong reference", impl->mBase);
        } else {
            delete impl;
        }
    } else {
        // This is the OBJECT_LIFETIME_WEAK case. The last weak-reference
        // is gone, we can destroy the object.
        impl->mBase->onLastWeakRef(id);
        delete impl->mBase;
    }
}

繼續(xù)示例代碼波岛,wp析構(gòu)后茅坛,弱引用計(jì)數(shù)為1音半,但是強(qiáng)引用也是1,所以不能釋放對(duì)象贡蓖。

sp析構(gòu):

system/core/include/utils/StrongPointer.h

sp<T>::~sp() {
    if (m_ptr)
        //m_ptr就是實(shí)際對(duì)象曹鸠,集成自RefBase
        m_ptr->decStrong(this);
}

system/core/libutils/RefBase.cpp

void RefBase::decStrong(const void* id) const
{
    weakref_impl* const refs = mRefs;
    //無視
    refs->removeStrongRef(id);
    //減一
    const int32_t c = refs->mStrong.fetch_sub(1, std::memory_order_release);
#if PRINT_REFS
    ALOGD("decStrong of %p from %p: cnt=%d\n", this, id, c);
#endif
    LOG_ALWAYS_FATAL_IF(BAD_STRONG(c), "decStrong() called on %p too many times",
            refs);
    if (c == 1) {
        std::atomic_thread_fence(std::memory_order_acquire);
        //調(diào)用onLastStrongRef,表明強(qiáng)引用計(jì)數(shù)減為0斥铺,對(duì)象有可能被delete
        refs->mBase->onLastStrongRef(id);
        int32_t flags = refs->mFlags.load(std::memory_order_relaxed);
        if ((flags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_STRONG) {
            delete this;
            // The destructor does not delete refs in this case.
        }
    }
    // Note that even with only strong reference operations, the thread
    // deallocating this may not be the same as the thread deallocating refs.
    // That's OK: all accesses to this happen before its deletion here,
    // and all accesses to refs happen before its deletion in the final decWeak.
    // The destructor can safely access mRefs because either it's deleting
    // mRefs itself, or it's running entirely before the final mWeak decrement.
    //weaktype_impl對(duì)象調(diào)用減少弱引用
    refs->decWeak(id);

delete this回調(diào)用被引用的析構(gòu)函數(shù)彻桃,例如示例的A類,如果強(qiáng)引用沒有了,就把引用對(duì)象delete

RefBase::~RefBase()
{
    int32_t flags = mRefs->mFlags.load(std::memory_order_relaxed);
    // Life-time of this object is extended to WEAK, in
    // which case weakref_impl doesn't out-live the object and we
    // can free it now.
    if ((flags & OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_WEAK) {
        // It's possible that the weak count is not 0 if the object
        // re-acquired a weak reference in its destructor
        if (mRefs->mWeak.load(std::memory_order_relaxed) == 0) {
            delete mRefs;
        }
    } else if (mRefs->mStrong.load(std::memory_order_relaxed)
            == INITIAL_STRONG_VALUE) {
        // We never acquired a strong reference on this object.
        LOG_ALWAYS_FATAL_IF(mRefs->mWeak.load() != 0,
                "RefBase: Explicit destruction with non-zero weak "
                "reference count");
        // TODO: Always report if we get here. Currently MediaMetadataRetriever
        // C++ objects are inconsistently managed and sometimes get here.
        // There may be other cases, but we believe they should all be fixed.
        delete mRefs;
    }
    // For debugging purposes, clear mRefs.  Ineffective against outstanding wp's.
    const_cast<weakref_impl*&>(mRefs) = NULL;
}

sp執(zhí)行了減少強(qiáng)引用之后將執(zhí)行減少弱引用晾蜘,如果弱引用沒有了邻眷。就把weaktype_impl對(duì)象delete

void RefBase::weakref_type::decWeak(const void* id)
{
    weakref_impl* const impl = static_cast<weakref_impl*>(this);
    impl->removeWeakRef(id);
    const int32_t c = impl->mWeak.fetch_sub(1, std::memory_order_release);
    LOG_ALWAYS_FATAL_IF(BAD_WEAK(c), "decWeak called on %p too many times",
            this);
    if (c != 1) return;
    atomic_thread_fence(std::memory_order_acquire);

    int32_t flags = impl->mFlags.load(std::memory_order_relaxed);
    if ((flags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_STRONG) {
        // This is the regular lifetime case. The object is destroyed
        // when the last strong reference goes away. Since weakref_impl
        // outlives the object, it is not destroyed in the dtor, and
        // we'll have to do it here.
        if (impl->mStrong.load(std::memory_order_relaxed)
                == INITIAL_STRONG_VALUE) {
            // Decrementing a weak count to zero when object never had a strong
            // reference.  We assume it acquired a weak reference early, e.g.
            // in the constructor, and will eventually be properly destroyed,
            // usually via incrementing and decrementing the strong count.
            // Thus we no longer do anything here.  We log this case, since it
            // seems to be extremely rare, and should not normally occur. We
            // used to deallocate mBase here, so this may now indicate a leak.
            ALOGW("RefBase: Object at %p lost last weak reference "
                    "before it had a strong reference", impl->mBase);
        } else {
           //delete影子對(duì)象
            delete impl;
        }
    } else {
        // This is the OBJECT_LIFETIME_WEAK case. The last weak-reference
        // is gone, we can destroy the object.
        impl->mBase->onLastWeakRef(id);
        delete impl->mBase;
    }
}

1.1.4 總結(jié)

RefBase中有一個(gè)隱含的影子對(duì)象,這個(gè)對(duì)象就是實(shí)際包含被引用對(duì)象和強(qiáng)弱引用計(jì)數(shù)剔交;

sp構(gòu)造引用后肆饶,強(qiáng)弱引用計(jì)數(shù)各增加1,sp析構(gòu)后岖常,強(qiáng)弱引用計(jì)數(shù)各減1驯镊;

wp構(gòu)造引用后,弱引用增加1竭鞍,wp析構(gòu)后板惑,弱引用計(jì)數(shù)減1;

完全徹底地消滅RefBase對(duì)象偎快,包括讓實(shí)際對(duì)象和影子對(duì)象滅亡冯乘,這些都是由強(qiáng)弱引用計(jì)數(shù)控制的,另外還要考
慮flag的取值情況晒夹。當(dāng)flag為0時(shí)裆馒,可得出如下結(jié)論:

  • 強(qiáng)引用為0將導(dǎo)致實(shí)際對(duì)象被delete。
  • 弱引用為0將導(dǎo)致影子對(duì)象被delete惋戏。

1.2 由弱生強(qiáng)

代碼示例:

int main(){
    A *pA =new A();
    wp<A> wpA(A);
    sp<A> spA = wpA.promote();//通過promote函數(shù)领追,得到一個(gè)sp。
}

1.2.1 由弱生強(qiáng)的方法

由示例代碼可以看出响逢,依靠函數(shù)promote()可以得到一個(gè)sp的對(duì)象

template<typename T>
sp<T> wp<T>::promote() const
{
    sp<T> result;
    //該函數(shù)就是弱生強(qiáng)的關(guān)鍵
    if (m_ptr && m_refs->attemptIncStrong(&result)) {
        result.set_pointer(m_ptr);
    }
    return result;
}

成敗全靠attemptIncStrong()

system/core/libutils/RefBase.cpp


bool RefBase::weakref_type::attemptIncStrong(const void* id)
{
    incWeak(id); //增加弱
    
    weakref_impl* const impl = static_cast<weakref_impl*>(this);
    int32_t curCount = impl->mStrong.load(std::memory_order_relaxed);
    //該循環(huán)在多線程操作同一個(gè)對(duì)象時(shí)會(huì)多次循環(huán)绒窑,他的目的就是讓強(qiáng)引用加1
    while (curCount > 0 && curCount != INITIAL_STRONG_VALUE) {
        // we're in the easy/common case of promoting a weak-reference
        // from an existing strong reference.
        if (impl->mStrong.compare_exchange_weak(curCount, curCount+1,
                std::memory_order_relaxed)) {
            break;
        }
        // the strong count has changed on us, we need to re-assert our
        // situation. curCount was updated by compare_exchange_weak.
    }
    
    ....//太長了,也看不懂舔亭,也是為了保證能裝換強(qiáng)引用
      
    if (curCount == INITIAL_STRONG_VALUE) {
        impl->mStrong.fetch_sub(INITIAL_STRONG_VALUE,
                std::memory_order_relaxed);
    }

    return true;
}

1.2.2 結(jié)果

結(jié)果當(dāng)然就是強(qiáng)弱增加一個(gè)返回一個(gè)強(qiáng)引用對(duì)象些膨。

1.3 生命周期的管理

在構(gòu)造的sp,或wp的生命周期受flag的影響蟀俊。

system/core/include/utils/RefBase.h

//! Flags for extendObjectLifetime()
enum {
    OBJECT_LIFETIME_STRONG  = 0x0000,
    OBJECT_LIFETIME_WEAK    = 0x0001,
    OBJECT_LIFETIME_MASK    = 0x0001
};
  • 在flag為OBJECT_LIFETIME_WEAK時(shí),即便sp對(duì)象的強(qiáng)引用計(jì)數(shù)為0订雾,而弱引用不為0肢预,被引用對(duì)象不會(huì)被delete,進(jìn)而在減少弱引用函數(shù)中再去判斷,如果弱引用也為0了洼哎,就會(huì)delete掉被引用對(duì)象烫映。
  • 在flag為OBJECT_LIFETIME_STRONG強(qiáng)引用空之被引用對(duì)象的生命周期。弱引用控制影子對(duì)象的生命周期噩峦,強(qiáng)引用為0時(shí)锭沟,被引用對(duì)象delete。

1.3.1 輕量引用計(jì)數(shù)控制-LightRefBase

template <class T>
class LightRefBase
{
public:
    inline LightRefBase() : mCount(0) { }
    inline void incStrong(__attribute__((unused)) const void* id) const {
        mCount.fetch_add(1, std::memory_order_relaxed);
    }
    inline void decStrong(__attribute__((unused)) const void* id) const {
        if (mCount.fetch_sub(1, std::memory_order_release) == 1) {
            std::atomic_thread_fence(std::memory_order_acquire);
            delete static_cast<const T*>(this);
        }
    }
    //! DEBUGGING ONLY: Get current strong ref count.
    inline int32_t getStrongCount() const {
        return mCount.load(std::memory_order_relaxed);
    }

    typedef LightRefBase<T> basetype;
...
private:
    mutable std::atomic<int32_t> mCount;
};

這個(gè)類中僅有一個(gè)mCount用來引用計(jì)數(shù)识补,使用也非常簡單:

class A: public LightRefBase<A> //泛型得是A

2 Thread類以及常用同步類

Thread類是Android為線程操作而做的一個(gè)封裝族淮。代碼在Thread.cpp中,其中還封裝了一些與線程同步相關(guān)的類

2.1 常見同步類

Android提供了兩個(gè)封裝好的同步類凭涂,它們是Mutex和Condition祝辣。這是重量級(jí)的同步技術(shù),一般內(nèi)核會(huì)有對(duì)應(yīng)的
支持切油。另外蝙斜,OS還提供了簡單的原子操作,這些也算是同步技術(shù)的一種白翻。

2.1.1 互斥類-Mutex

Mutex的使用必須初始化乍炉,除此之外有兩個(gè)重要函數(shù)處理同步,lock(),unlock()滤馍,分別表示開始上鎖岛琼,釋放鎖。另外巢株,Mutex還提供了一個(gè)trylock()函數(shù)槐瑞,該函數(shù)只是嘗試去鎖住該區(qū)域,使用者需要根據(jù)trylock的返回值判
斷是否成功鎖住了該區(qū)域阁苞。

Mutex類的內(nèi)部還有一個(gè)AutoLock 幫助簡化同步困檩。

2.1.2 條件類-Condition

工作線程通過觸發(fā)信號(hào),喚起等待的進(jìn)程那槽。Condition的信號(hào)觸發(fā)需要在lock范圍中才可以

3 Looper和Handler

工作原理:

一個(gè)消息隊(duì)列悼沿,其他線程可以往這個(gè)隊(duì)列中添加消息。

有一個(gè)消息循環(huán)骚灸,不斷的去出消息糟趾,處理消息。![looper_handler-1]

looper_handler-1.png

在Android系統(tǒng)中:

Looper用于封裝消息循環(huán),內(nèi)部有一個(gè)消息隊(duì)列

Handler它是負(fù)責(zé)消息的入隊(duì)和消息的處理义郑。

Looper中的消息隊(duì)列里面存的是多個(gè)Message

每個(gè)Message中有一個(gè)Handler蝶柿,用于處理Message

上一篇 《第四章 - Zygote》讀書筆記

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市非驮,隨后出現(xiàn)的幾起案子交汤,更是在濱河造成了極大的恐慌,老刑警劉巖劫笙,帶你破解...
    沈念sama閱讀 206,482評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件芙扎,死亡現(xiàn)場離奇詭異,居然都是意外死亡邀摆,警方通過查閱死者的電腦和手機(jī)纵顾,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來栋盹,“玉大人,你說我怎么就攤上這事敷矫±瘢” “怎么了?”我有些...
    開封第一講書人閱讀 152,762評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵曹仗,是天一觀的道長榨汤。 經(jīng)常有香客問我,道長怎茫,這世上最難降的妖魔是什么收壕? 我笑而不...
    開封第一講書人閱讀 55,273評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮轨蛤,結(jié)果婚禮上蜜宪,老公的妹妹穿的比我還像新娘。我一直安慰自己祥山,他們只是感情好圃验,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,289評(píng)論 5 373
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著缝呕,像睡著了一般澳窑。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上供常,一...
    開封第一講書人閱讀 49,046評(píng)論 1 285
  • 那天摊聋,我揣著相機(jī)與錄音,去河邊找鬼栈暇。 笑死麻裁,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播悲立,決...
    沈念sama閱讀 38,351評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼鹿寨,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼!你這毒婦竟也來了薪夕?” 一聲冷哼從身側(cè)響起脚草,我...
    開封第一講書人閱讀 36,988評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎原献,沒想到半個(gè)月后馏慨,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,476評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡姑隅,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,948評(píng)論 2 324
  • 正文 我和宋清朗相戀三年写隶,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片讲仰。...
    茶點(diǎn)故事閱讀 38,064評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡慕趴,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出鄙陡,到底是詐尸還是另有隱情冕房,我是刑警寧澤,帶...
    沈念sama閱讀 33,712評(píng)論 4 323
  • 正文 年R本政府宣布趁矾,位于F島的核電站耙册,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏毫捣。R本人自食惡果不足惜详拙,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,261評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望蔓同。 院中可真熱鬧饶辙,春花似錦、人聲如沸牌柄。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,264評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽珊佣。三九已至蹋宦,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間咒锻,已是汗流浹背冷冗。 一陣腳步聲響...
    開封第一講書人閱讀 31,486評(píng)論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留惑艇,地道東北人蒿辙。 一個(gè)月前我還...
    沈念sama閱讀 45,511評(píng)論 2 354
  • 正文 我出身青樓拇泛,卻偏偏與公主長得像,于是被迫代替她去往敵國和親思灌。 傳聞我的和親對(duì)象是個(gè)殘疾皇子俺叭,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,802評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容