chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,136 @@
|
||||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include "bthread/bthread.h"
|
||||
#include "bthread/singleton_on_bthread_once.h"
|
||||
#include "bthread/task_control.h"
|
||||
|
||||
namespace bthread {
|
||||
extern TaskControl* g_task_control;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
bthread_once_t g_bthread_once_control;
|
||||
bool g_bthread_once_started = false;
|
||||
butil::atomic<int> g_bthread_once_count(0);
|
||||
|
||||
void init_routine() {
|
||||
bthread_usleep(2000 * 1000);
|
||||
g_bthread_once_count.fetch_add(1, butil::memory_order_relaxed);
|
||||
}
|
||||
|
||||
void bthread_once_task() {
|
||||
bthread_once(&g_bthread_once_control, init_routine);
|
||||
// `init_routine' only be called once.
|
||||
ASSERT_EQ(1, g_bthread_once_count.load(butil::memory_order_relaxed));
|
||||
}
|
||||
|
||||
void* first_bthread_once_task(void*) {
|
||||
g_bthread_once_started = true;
|
||||
bthread_once_task();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void* other_bthread_once_task(void*) {
|
||||
bthread_once_task();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
TEST(BthreadOnceTest, once) {
|
||||
bthread_t bid;
|
||||
ASSERT_EQ(0, bthread_start_background(
|
||||
&bid, NULL, first_bthread_once_task, NULL));
|
||||
while (!g_bthread_once_started) {
|
||||
bthread_usleep(1000);
|
||||
}
|
||||
ASSERT_NE(nullptr, bthread::g_task_control);
|
||||
int concurrency = bthread::g_task_control->concurrency();
|
||||
LOG(INFO) << "concurrency: " << concurrency;
|
||||
ASSERT_GT(concurrency, 0);
|
||||
std::vector<bthread_t> bids(concurrency * 100);
|
||||
for (auto& id : bids) {
|
||||
ASSERT_EQ(0, bthread_start_background(
|
||||
&id, NULL, other_bthread_once_task, NULL));
|
||||
}
|
||||
bthread_once_task();
|
||||
|
||||
for (auto& id : bids) {
|
||||
bthread_join(id, NULL);
|
||||
}
|
||||
bthread_join(bid, NULL);
|
||||
}
|
||||
|
||||
bool g_bthread_started = false;
|
||||
butil::atomic<int> g_bthread_singleton_count(0);
|
||||
|
||||
class BthreadSingleton {
|
||||
public:
|
||||
BthreadSingleton() {
|
||||
bthread_usleep(2000 * 1000);
|
||||
g_bthread_singleton_count.fetch_add(1, butil::memory_order_relaxed);
|
||||
}
|
||||
};
|
||||
|
||||
void get_bthread_singleton() {
|
||||
auto instance = bthread::get_leaky_singleton<BthreadSingleton>();
|
||||
ASSERT_NE(nullptr, instance);
|
||||
// Only one BthreadSingleton instance has been created.
|
||||
ASSERT_EQ(1, g_bthread_singleton_count.load(butil::memory_order_relaxed));
|
||||
}
|
||||
|
||||
void* first_get_bthread_singleton(void*) {
|
||||
g_bthread_started = true;
|
||||
get_bthread_singleton();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void* get_bthread_singleton(void*) {
|
||||
get_bthread_singleton();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Singleton will definitely not cause deadlock,
|
||||
// even if constructor of T will hang the bthread.
|
||||
TEST(BthreadOnceTest, singleton) {
|
||||
bthread_t bid;
|
||||
ASSERT_EQ(0, bthread_start_background(
|
||||
&bid, NULL, first_get_bthread_singleton, NULL));
|
||||
while (!g_bthread_started) {
|
||||
bthread_usleep(1000);
|
||||
}
|
||||
ASSERT_NE(nullptr, bthread::g_task_control);
|
||||
int concurrency = bthread::g_task_control->concurrency();
|
||||
LOG(INFO) << "concurrency: " << concurrency;
|
||||
ASSERT_GT(concurrency, 0);
|
||||
std::vector<bthread_t> bids(concurrency * 100);
|
||||
for (auto& id : bids) {
|
||||
ASSERT_EQ(0, bthread_start_background(
|
||||
&id, NULL, get_bthread_singleton, NULL));
|
||||
}
|
||||
get_bthread_singleton();
|
||||
|
||||
for (auto& id : bids) {
|
||||
bthread_join(id, NULL);
|
||||
}
|
||||
bthread_join(bid, NULL);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user