152 lines
4.2 KiB
C++
152 lines
4.2 KiB
C++
/*
|
|
* Copyright (C) 2017 The Android Open Source Project
|
|
*
|
|
* Licensed 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 "thread/ThreadBase.h"
|
|
#include "utils/TimeUtils.h"
|
|
|
|
#include <chrono>
|
|
#include "unistd.h"
|
|
|
|
using namespace android;
|
|
using namespace android::uirenderer;
|
|
|
|
static ThreadBase& thread() {
|
|
class TestThread : public ThreadBase, public virtual RefBase {};
|
|
static sp<TestThread> thread = []() -> auto {
|
|
sp<TestThread> ret{new TestThread};
|
|
ret->start("TestThread");
|
|
return ret;
|
|
}
|
|
();
|
|
return *thread;
|
|
}
|
|
|
|
static WorkQueue& queue() {
|
|
return thread().queue();
|
|
}
|
|
|
|
TEST(ThreadBase, post) {
|
|
std::atomic_bool ran(false);
|
|
queue().post([&ran]() { ran = true; });
|
|
for (int i = 0; !ran && i < 1000; i++) {
|
|
usleep(1);
|
|
}
|
|
ASSERT_TRUE(ran) << "Failed to flip atomic after 1 second";
|
|
}
|
|
|
|
TEST(ThreadBase, postDelay) {
|
|
using clock = WorkQueue::clock;
|
|
|
|
std::promise<nsecs_t> ranAtPromise;
|
|
auto queuedAt = clock::now();
|
|
queue().postDelayed(100_us, [&]() { ranAtPromise.set_value(clock::now()); });
|
|
auto ranAt = ranAtPromise.get_future().get();
|
|
auto ranAfter = ranAt - queuedAt;
|
|
ASSERT_TRUE(ranAfter > 90_us) << "Ran after " << ns2us(ranAfter) << "us <= 90us";
|
|
}
|
|
|
|
TEST(ThreadBase, runSync) {
|
|
pid_t thisTid = gettid();
|
|
pid_t otherTid = thisTid;
|
|
|
|
auto result = queue().runSync([&otherTid]() -> auto {
|
|
otherTid = gettid();
|
|
return 42;
|
|
});
|
|
|
|
ASSERT_EQ(42, result);
|
|
ASSERT_NE(thisTid, otherTid);
|
|
}
|
|
|
|
TEST(ThreadBase, async) {
|
|
pid_t thisTid = gettid();
|
|
pid_t thisPid = getpid();
|
|
|
|
auto otherTid = queue().async([]() -> auto { return gettid(); });
|
|
auto otherPid = queue().async([]() -> auto { return getpid(); });
|
|
auto result = queue().async([]() -> auto { return 42; });
|
|
|
|
ASSERT_NE(thisTid, otherTid.get());
|
|
ASSERT_EQ(thisPid, otherPid.get());
|
|
ASSERT_EQ(42, result.get());
|
|
}
|
|
|
|
TEST(ThreadBase, lifecyclePerf) {
|
|
struct EventCount {
|
|
std::atomic_int construct{0};
|
|
std::atomic_int destruct{0};
|
|
std::atomic_int copy{0};
|
|
std::atomic_int move{0};
|
|
};
|
|
|
|
struct Counter {
|
|
explicit Counter(EventCount* count) : mCount(count) { mCount->construct++; }
|
|
|
|
Counter(const Counter& other) : mCount(other.mCount) {
|
|
if (mCount) mCount->copy++;
|
|
}
|
|
|
|
Counter(Counter&& other) : mCount(other.mCount) {
|
|
other.mCount = nullptr;
|
|
if (mCount) mCount->move++;
|
|
}
|
|
|
|
Counter& operator=(const Counter& other) {
|
|
mCount = other.mCount;
|
|
if (mCount) mCount->copy++;
|
|
return *this;
|
|
}
|
|
|
|
Counter& operator=(Counter&& other) {
|
|
mCount = other.mCount;
|
|
other.mCount = nullptr;
|
|
if (mCount) mCount->move++;
|
|
return *this;
|
|
}
|
|
|
|
~Counter() {
|
|
if (mCount) mCount->destruct++;
|
|
}
|
|
|
|
EventCount* mCount;
|
|
};
|
|
|
|
EventCount count;
|
|
{
|
|
Counter counter{&count};
|
|
queue().runSync([c = std::move(counter)](){});
|
|
}
|
|
ASSERT_EQ(1, count.construct.load());
|
|
ASSERT_EQ(1, count.destruct.load());
|
|
ASSERT_EQ(0, count.copy.load());
|
|
ASSERT_LE(1, count.move.load());
|
|
}
|
|
|
|
int lifecycleTestHelper(const sp<VirtualLightRefBase>& test) {
|
|
return queue().runSync([t = test]()->int { return t->getStrongCount(); });
|
|
}
|
|
|
|
TEST(ThreadBase, lifecycle) {
|
|
sp<VirtualLightRefBase> dummyObject{new VirtualLightRefBase};
|
|
ASSERT_EQ(1, dummyObject->getStrongCount());
|
|
ASSERT_EQ(2, queue().runSync([dummyObject]() -> int { return dummyObject->getStrongCount(); }));
|
|
ASSERT_EQ(1, dummyObject->getStrongCount());
|
|
ASSERT_EQ(2, lifecycleTestHelper(dummyObject));
|
|
ASSERT_EQ(1, dummyObject->getStrongCount());
|
|
}
|