日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Discuz模板内涵TV段子_wap手机版源码

發布時間:2024/3/24 编程问答 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Discuz模板内涵TV段子_wap手机版源码 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

模板特色:
1、首頁簡潔高大上布局,純DIY制作,支持點擊加載更多;
2、論壇首頁內容聚合;
3、個人菜單置頂美化優化;
4、導讀美化;
5、排行榜美化;
6、任務、道具、勛章、等美化;
7、版塊主題列表頁美化;
8、帖子內容美化;
9、資訊列表美化;
10、資訊內容頁美化;
11、內置精美瀑布流;
12、登錄注冊美化;

文件:590m.com/f/25127180-499031531-d4fef6(訪問密碼:551685)

以下內容無關:

-------------------------------------------分割線---------------------------------------------

傳統同步方案的缺點
一般是將需要同步的數據和鎖一一配對,即 —— associate mutexes with data, not code :

class RequestHandler {

std::mutex requestMutex_;
RequestQueue requestQueue_;

processRequest(const Request& request);
};

void RequestHandler::processRequest(const Request& request) {
std::lock_guardstd::mutex lg(requestMutex_);
requestQueue_.push_back(request);
}
然而,操作這些數據成員,開發人員必須注意,正確的獲取鎖、獲取正確的鎖。

一些常見的錯誤包括:

操作數據之前沒有獲取鎖。
獲取了不配對的鎖,這個鎖不是用來鎖這個數據的。
獲取了讀鎖,但是試圖去修改數據。
獲取了寫鎖,但是對數據只有 const access.
一般在使用時,需要提醒開發人員:“別忘了 xxxx”,那一般都會出錯,比如 new 的對象別忘了 delete : )

folly/Synchronized.h 簡單使用
上面的代碼可以用 folly/Synchronized.h 重寫為:

class RequestHandler {
folly::Synchronized requestQueue_;

processRequest(const Request& request);
};

void RequestHandler::processRequest(const Request& request) {
requestQueue_.wlock()->push_back(request);
}
為什么 folly/Synchronized.h 更加有效呢?

與傳統使用方式不同,這里鎖和數據是結合成了一個對象 —— requestQueue_。傳統方案中,需要尋找鎖和數據的配對關系。
幾乎不可能在不獲取鎖的情況下,去操作數據,還是因為它們被封裝成了一個對象。傳統方案加不加鎖全靠自覺。
在 push_back 后,鎖立即被釋放。
如果在臨界區有多個操作,那么可以使用如下方法:

{
auto lockedQueue = requestQueue_.wlock();
lockedQueue->push_back(request1);
lockedQueue->push_back(request2);
}
wlock 返回一個 LockedPtr 對象,這個對象可以被理解為指向數據成員的指針。只有這個對象存在,那么鎖就會被鎖住,所以最好為這個對象顯示定義一個 scope.

更好的方式,是使用 lambdas :

void RequestHandler::processRequest(const Request& request) {
requestQueue_.withWLock([&](auto& queue “&”) {
// withWLock() automatically holds the lock for the
// duration of this lambda function
queue.push_back(request);
});
}
使用 withWLock 配合 lambdas 強制定義了一個 scope,更清晰。

Synchronized的模板參數
Synchronized 有兩個模板參數,數據類型和鎖類型:

template <class T, class Mutex = SharedMutex>
如果不指定第二個模板參數,默認是 folly::SharedMutex。只要被 folly::LockTraits 支持的都可以使用,比如 std::mutex、std::recursive_mutex、std::timed_mutex,。std::recursive_timed_mutex、folly::SharedMutex、folly::RWSpinLock、folly::SpinLock.

根據鎖類型的不同,Synchronized 會提供不同的 API:

共享鎖和升級鎖:如果存在 lock_shared()成員函數,Synchronized 會提供 wlock(),rlock(),ulock()三個方法來獲取不同的鎖類型。其中,rlock()只提供對數據成員 const access.
排他鎖:lock()
withLock()/withRLock()/withWLock() —— 更易用的加鎖方式
withLock()在上面提到過了,可以用來替代 lock()。在持有鎖的期間,執行一個 lambda 或者 function. withRLock()/withWLock()同理可以替代 rlock()/wlock().

我們再詳細說一下這種方式的好處。下面的函數將 vector 里的所有元素都 double:

auto locked = vec.lock();
for (int& n : *locked) {
n *= 2;
}
使用 lock()/wlock()/rlock()的一個重要注意事項:一個指向數據的指針或者引用,它的生命周期一定不要比 LockedPtr 對象長(lock()/wlock()/rlock()的返回值類型)。 如果我們將上面的例子這樣寫就會出問題:

// No. NO. NO!
for (int& n : *vec.wlock()) {
n *= 2;
}
vec.wlock()返回的 LockPtr 對象在 range iterators 建立后就銷毀了(詳細解釋見 Range-based for loop Temporary range expression 小節),range iterators 指向了 vector data,但此時鎖已經被釋放。想想如果要 debug 這種問題,會用多少時間 😃

這時 withLock()/withRLock()/withWLock()的好處就體現出來了,鎖會在 for loop 期間一直持有:

vec.withLock([](auto& data “”) {
for (int& n : data) {
n *= 2;
}
});
withLock 定義為(withRLock/withWLock 類似):

/**

  • Invoke a function while holding the lock.
  • A reference to the datum will be passed into the function as its only
  • argument.
  • This can be used with a lambda argument for easily defining small critical
  • sections in the code. For example:
  • auto value = obj.withLock([](auto& data “”) {
  • data.doStuff();
  • return data.getValue();
  • });
    */
    template
    auto withLock(Function&& function) {
    return function(*lock());
    }

template
auto withLock(Function&& function) const {
return function(*lock());
}
升級鎖
ulock()和 withULockPtr()
Synchronized 還支持升級鎖。升級鎖與共享鎖可以共存,但是與排它鎖互斥。

/**

  • An enum to describe the “level” of a mutex. The supported levels are
  • Unique - a normal mutex that supports only exclusive locking
  • Shared - a shared mutex which has shared locking and unlocking functions;
  • Upgrade - a mutex that has all the methods of the two above along with
  • support for upgradable locking

*/
enum class MutexLevel { UNIQUE, SHARED, UPGRADE };
升級鎖解決的問題是:先對數據進行讀操作,然后根據一定的條件會進行寫操作。

升級鎖可以通過 uclock()或者 withULockPtr()獲得:

{
// only const access allowed to the underlying object when an upgrade lock
// is acquired
auto ulock = vec.ulock();
auto newSize = ulock->size();
}

auto newSize = vec.withULockPtr([](auto ulock “”) {
// only const access allowed to the underlying object when an upgrade lock
// is acquired
return ulock->size();
});
通過下面的函數可以進行升級或者降級:

moveFromUpgradeToWrite()
moveFromWriteToUpgrade()
moveFromWriteToRead() // withWLockPtr()獲得的 wlock 可以調用此函數降級為 rlock
moveFromUpgradeToRead()
調用這些函數的 LockedPtr 會被設置為 invalid null state,并返回另一個鎖住特定鎖的 LockedPtr。這些操作都是原子性的,中間不會出現 unlocked 狀態。

比如現在有一個 cache,數據結構為 unordered_map,需求是先檢查對應的 key 是否在 unordered_map 中,如果在則返回對應的 value,不在則初始化 value 為 0:

folly::Synchronized<std::unordered_map<int64_t, int64_t>> cache;

int64_t res = cache.withULockPtr([key,value](auto ulock “key,value”) {
int64_t cache_value;
auto iter = ulock->find(key);
if (iter != ulock->end()) {
cache_value = iter->second;
} else {
cache_value = 0;

// ulock is now nullauto wlock = ulock.moveFromUpgradeToWrite();(*wlock)[key] = cache_value; }return cache_value;

});
Timed Locking
如果初始化 Synchronized 的鎖類型支持時間,lock()/wlock()/rlock()可以傳入一個類型為 std::chrono::duration 的參數:

void fun(Synchronized<vector>& vec) {
{
auto locked = vec.lock(10ms);
if (!locked) {
throw std::runtime_error(“failed to acquire lock”);
}
locked->push_back(“hello”);
locked->push_back(“world”);
}
LOG(INFO) << “successfully added greeting”;
}
Synchronized 與 std::condition_variable
如果 Synchronized 的鎖類型是 std::mutex,那么可以和 std::condition_variable 配合使用。

Synchronized<vector, std::mutex> vec;
std::condition_variable emptySignal;

// Assuming some other thread will put data on vec and signal
// emptySignal, we can then wait on it as follows:
auto locked = vec.lock();
emptySignal.wait(locked.getUniqueLock(),
[&] { return !locked->empty(); });
getUniqueLock()返回一個 std::unique_lockstd::mutex的引用。但是不推薦這么使用,因為這繞過了 Synchronized 的 API,可以直接操作對應的鎖:

/**

  • Get a reference to the std::unique_lock.
  • This is provided so that callers can use Synchronized<T, std::mutex>
  • with a std::condition_variable.
  • While this API could be used to bypass the normal Synchronized APIs and
  • manually interact with the underlying unique_lock, this is strongly
  • discouraged.
    */
    std::unique_lockstd::mutex& getUniqueLock() { return lock_; }
    acquireLocked() —— 同時鎖多個數據
    假如需要將一個 vector 的數據拷貝到另一個 vector,wlock()可能會實現需求:

void fun(Synchronized<vector>& a, Synchronized<vector>& b) {
auto lockedA = a.wlock();
auto lockedB = b.wlock();
… use lockedA and lockedB …
}
但是如果一個線程調用 fun(x,y),另一個線程調用 func(y,x),就很有可能出現死鎖。經典的解決方式是,所有的線程以同樣的順序獲取鎖。許多庫的實現是通過比較鎖地址的大小來決定加鎖順序:

void fun(Synchronized<vector>& a, Synchronized<vector>& b) {
auto ret = folly::acquireLocked(a, b);
auto& lockedA = std::get<0>(ret);
auto& lockedB = std::get<1>(ret);
… use lockedA and lockedB …
}

// 實現:通過比較鎖地址的大小
/**

  • Acquire locks for multiple Synchronized objects, in a deadlock-safe
  • manner.
  • The locks are acquired in order from lowest address to highest address.
  • (Note that this is not necessarily the same algorithm used by std::lock().)
  • For parameters that are const and support shared locks, a read lock is
  • acquired. Otherwise an exclusive lock is acquired.
  • use lock() with folly::wlock(), folly::rlock() and folly::ulock() for
  • arbitrary locking without causing a deadlock (as much as possible), with the
  • same effects as std::lock()
    /
    template <class Sync1, class Sync2>
    std::tuple<detail::LockedPtrType, detail::LockedPtrType>
    acquireLocked(Sync1& l1, Sync2& l2) {
    if (static_cast<const void>(&l1) < static_cast<const void*>(&l2)) {
    auto p1 = l1.contextualLock();
    auto p2 = l2.contextualLock();
    return std::make_tuple(std::move(p1), std::move(p2));
    } else {
    auto p2 = l2.contextualLock();
    auto p1 = l1.contextualLock();
    return std::make_tuple(std::move(p1), std::move(p2));
    }
    }
    C++17 引入了 structured binding syntax,可以使代碼更簡單:

void fun(Synchronized<vector>& a, Synchronized<vector>& b) {
auto [lockedA, lockedB] = folly::acquireLocked(a, b);
… use lockedA and lockedB …
}
acquireLockedPair()返回 std::pair,在不支持 C++17 的編譯器情況下,使用也很方便。

使用一把鎖,鎖多個數據
比如一個 bidirectional map,需要同時操作。一般有兩個方案:

Struct
class Server {
struct BiMap {
map<int, string> direct;
map<string, int> inverse;
};
Synchronized bimap_;

};


bimap_.withLock([](auto& locked “”) {
locked.direct[0] = “zero”;
locked.inverse[“zero”] = 0;
});
std::tuple
class Server {
Synchronized<tuple<map<int, string>, map<string, int>>> bimap_;

};


bimap_.withLock([](auto& locked “”) {
get<0>(locked)[0] = “zero”;
get<1>(locked)[“zero”] = 0;
});
Benchmark
SynchronizedBenchmark.cpp

下篇文章寫一下 Synchronized 的基本實現 :)

總結

以上是生活随笔為你收集整理的Discuz模板内涵TV段子_wap手机版源码的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 91视频一区二区三区 | 色无五月 | 男男做性免费视频网 | 日韩无码精品一区二区三区 | 久久国产精品无码一区二区 | 亚洲视频一二三区 | 欧美大片www| 日本少妇一区二区三区 | 国产成人欧美一区二区三区91 | 热re99久久精品国产99热 | 在线爱情大片免费观看大全 | 色综合天天综合 | 中文字幕日韩无 | 中文字幕女同女同女同 | 免费av网址在线 | 91官网在线观看 | 婷婷色图 | 日韩精品一区二区三区在线观看 | 久久国产精品亚洲 | 人人爽人人爽人人 | 官场艳妇疯狂性关系 | 91九色蝌蚪 | 骚虎av在线 | 久久婷婷一区 | 欧美黑人一级爽快片淫片高清 | 五月视频| 国产成人精品一区二区在线小狼 | 久久久91 | 中文毛片 | 伊人日韩| 欧美人与性动交α欧美片 | 日韩免费av片 | 一本大道东京热无码 | 亚洲av永久中文无码精品综合 | 黄色大片免费看 | 91免费视频观看 | 中文字幕欧美另类精品亚洲 | 一区二区三区免费毛片 | 国产精品香蕉在线 | 亚洲精品久久久久久无码色欲四季 | 免费看成人av | 人人看人人艹 | 国产精品久久久久久久免费观看 | 久久免费播放视频 | 啪啪激情网 | 插骚| 综合久久精品 | 欧美绿帽合集xxxxx | 日日噜噜夜夜狠狠久久丁香五月 | 欧美在线色图 | 国产wwww | 色综合av | 西西4444www大胆无码 | 99视频一区二区 | 久热久操 | 在线精品一区二区三区 | 三级黄色在线 | 国产xxx在线观看 | 国精产品乱码一区一区三区四区 | 午夜精品久久99蜜桃的功能介绍 | 88av网| 欧美透逼视频 | 欧美日韩一区电影 | 女优视频在线观看 | 国产资源久久 | 欧美日韩久久 | 国产在线伊人 | 成人精品福利 | 久久久成人精品一区二区三区 | 人妻在卧室被老板疯狂进入 | 丰满人妻在公车被猛烈进入电影 | 欧美日韩一区二区中文字幕 | 76少妇精品导航 | 一级免费在线 | 一级特黄bbbbb免费观看 | 仙踪林久久久久久久999 | 打白嫩屁屁网站视频短裙 | 亚洲专区视频 | 免费国产黄色网址 | 91成人天堂久久成人 | 国产精品美女久久久久 | 国产三区在线视频 | 美女脱得一干二净 | 老司机深夜影院 | 99热在线国产 | 懂色av懂色av粉嫩av分享吧 | 日本激情视频一区二区三区 | aaa国产精品 | 国产精欧美一区二区三区白种人 | 国产九九九九九 | 国产精品久久久久久精 | www.国产色 | 精品一区二区三区精华液 | 五月婷婷在线视频 | 影音先锋在线中文字幕 | 狠狠老司机 | 欧美美女一区 | 日韩av免费| 亚洲午夜精品久久久久久浪潮 |