1f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck/*
2f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck * Copyright (C) 2017 The Android Open Source Project
3f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck *
4f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck * Licensed under the Apache License, Version 2.0 (the "License");
5f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck * you may not use this file except in compliance with the License.
6f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck * You may obtain a copy of the License at
7f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck *
8f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck *      http://www.apache.org/licenses/LICENSE-2.0
9f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck *
10f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck * Unless required by applicable law or agreed to in writing, software
11f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck * distributed under the License is distributed on an "AS IS" BASIS,
12f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck * See the License for the specific language governing permissions and
14f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck * limitations under the License.
15f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck */
16f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck
17f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck#include <gtest/gtest.h>
18f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck
19f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck#include "thread/ThreadBase.h"
20f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck#include "utils/TimeUtils.h"
21f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck
22f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck#include <chrono>
23f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck#include "unistd.h"
24f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck
25f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reckusing namespace android;
26f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reckusing namespace android::uirenderer;
27f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck
28f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reckstatic ThreadBase& thread() {
29f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck    class TestThread : public ThreadBase, public virtual RefBase {};
30f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck    static sp<TestThread> thread = []() -> auto {
31f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck        sp<TestThread> ret{new TestThread};
32f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck        ret->start("TestThread");
33f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck        return ret;
341bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    }
351bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    ();
36f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck    return *thread;
37f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck}
38f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck
39f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reckstatic WorkQueue& queue() {
40f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck    return thread().queue();
41f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck}
42f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck
43f8441e65526cd1721f1ad77dad21b1a1e2743d76John ReckTEST(ThreadBase, post) {
44f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck    std::atomic_bool ran(false);
451bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    queue().post([&ran]() { ran = true; });
46f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck    for (int i = 0; !ran && i < 1000; i++) {
47f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck        usleep(1);
48f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck    }
49f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck    ASSERT_TRUE(ran) << "Failed to flip atomic after 1 second";
50f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck}
51f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck
52f8441e65526cd1721f1ad77dad21b1a1e2743d76John ReckTEST(ThreadBase, postDelay) {
53f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck    using clock = WorkQueue::clock;
54f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck
55f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck    std::promise<nsecs_t> ranAtPromise;
56f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck    auto queuedAt = clock::now();
571bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    queue().postDelayed(100_us, [&]() { ranAtPromise.set_value(clock::now()); });
58f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck    auto ranAt = ranAtPromise.get_future().get();
59f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck    auto ranAfter = ranAt - queuedAt;
60f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck    ASSERT_TRUE(ranAfter > 90_us) << "Ran after " << ns2us(ranAfter) << "us <= 90us";
61f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck}
62f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck
63f8441e65526cd1721f1ad77dad21b1a1e2743d76John ReckTEST(ThreadBase, runSync) {
64f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck    pid_t thisTid = gettid();
65f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck    pid_t otherTid = thisTid;
66f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck
67f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck    auto result = queue().runSync([&otherTid]() -> auto {
68f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck        otherTid = gettid();
69f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck        return 42;
70f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck    });
71f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck
72f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck    ASSERT_EQ(42, result);
73f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck    ASSERT_NE(thisTid, otherTid);
74f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck}
75f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck
76f8441e65526cd1721f1ad77dad21b1a1e2743d76John ReckTEST(ThreadBase, async) {
77f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck    pid_t thisTid = gettid();
78f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck    pid_t thisPid = getpid();
79f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck
801bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    auto otherTid = queue().async([]() -> auto { return gettid(); });
811bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    auto otherPid = queue().async([]() -> auto { return getpid(); });
821bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    auto result = queue().async([]() -> auto { return 42; });
83f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck
84f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck    ASSERT_NE(thisTid, otherTid.get());
85f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck    ASSERT_EQ(thisPid, otherPid.get());
86f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck    ASSERT_EQ(42, result.get());
87f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck}
88f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck
89f8441e65526cd1721f1ad77dad21b1a1e2743d76John ReckTEST(ThreadBase, lifecyclePerf) {
90f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck    struct EventCount {
91f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck        std::atomic_int construct{0};
92f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck        std::atomic_int destruct{0};
93f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck        std::atomic_int copy{0};
94f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck        std::atomic_int move{0};
95f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck    };
96f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck
97f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck    struct Counter {
981bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        Counter(EventCount* count) : mCount(count) { mCount->construct++; }
99f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck
100f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck        Counter(const Counter& other) : mCount(other.mCount) {
101f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck            if (mCount) mCount->copy++;
102f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck        }
103f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck
104f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck        Counter(Counter&& other) : mCount(other.mCount) {
105f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck            other.mCount = nullptr;
106f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck            if (mCount) mCount->move++;
107f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck        }
108f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck
109f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck        Counter& operator=(const Counter& other) {
110f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck            mCount = other.mCount;
111f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck            if (mCount) mCount->copy++;
112f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck            return *this;
113f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck        }
114f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck
115f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck        Counter& operator=(Counter&& other) {
116f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck            mCount = other.mCount;
117f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck            other.mCount = nullptr;
118f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck            if (mCount) mCount->move++;
119f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck            return *this;
120f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck        }
121f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck
122f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck        ~Counter() {
123f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck            if (mCount) mCount->destruct++;
124f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck        }
125f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck
126f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck        EventCount* mCount;
127f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck    };
128f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck
129f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck    EventCount count;
130f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck    {
131f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck        Counter counter{&count};
132f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck        queue().runSync([c = std::move(counter)](){});
133f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck    }
134f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck    ASSERT_EQ(1, count.construct.load());
135f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck    ASSERT_EQ(1, count.destruct.load());
136f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck    ASSERT_EQ(0, count.copy.load());
137f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck    ASSERT_LE(1, count.move.load());
138f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck}
139f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck
140f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reckint lifecycleTestHelper(const sp<VirtualLightRefBase>& test) {
1411bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    return queue().runSync([t = test]()->int { return t->getStrongCount(); });
142f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck}
143f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck
144f8441e65526cd1721f1ad77dad21b1a1e2743d76John ReckTEST(ThreadBase, lifecycle) {
145f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck    sp<VirtualLightRefBase> dummyObject{new VirtualLightRefBase};
146f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck    ASSERT_EQ(1, dummyObject->getStrongCount());
1471bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    ASSERT_EQ(2, queue().runSync([dummyObject]() -> int { return dummyObject->getStrongCount(); }));
148f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck    ASSERT_EQ(1, dummyObject->getStrongCount());
149f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck    ASSERT_EQ(2, lifecycleTestHelper(dummyObject));
150f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck    ASSERT_EQ(1, dummyObject->getStrongCount());
151f8441e65526cd1721f1ad77dad21b1a1e2743d76John Reck}