Merge branch 'master' into cxx17

This commit is contained in:
Stephen Seo 2021-09-09 15:54:30 +09:00
commit 0a7929b0a4
7 changed files with 120 additions and 73 deletions

26
.github/workflows/gh-pages.yml vendored Normal file
View file

@ -0,0 +1,26 @@
name: GitHub Pages Generated Doxygen Docs
on:
push:
branches:
- master
jobs:
build-deploy-doxygen-docs:
runs-on: ubuntu-latest
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 1
- name: Generate Doxygen Documentation
uses: mattnotmitt/doxygen-action@v1
- name: Deploy
uses: peaceiris/actions-gh-pages@v3
if: ${{ github.ref == 'refs/heads/master' }}
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./doxygen_html/html

View file

@ -771,7 +771,7 @@ WARN_LOGFILE =
# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
# Note: If this tag is empty the current directory is searched.
INPUT = ./src/EC/Meta ./src/EC
INPUT = ./src/EC/Meta ./src/EC ./doxygen/mainpage.dox ./README.md
# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
@ -796,7 +796,7 @@ INPUT_ENCODING = UTF-8
# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f, *.for, *.tcl,
# *.vhd, *.vhdl, *.ucf, *.qsf, *.as and *.js.
FILE_PATTERNS = *.hpp
FILE_PATTERNS = *.hpp *.md
# The RECURSIVE tag can be used to specify whether or not subdirectories should
# be searched for input files as well.

View file

@ -5,6 +5,10 @@ built and run using cmake (gtest is a dependency).
[(Note that gtest uses the BSD 3-Clause License.)](https://github.com/google/googletest/blob/master/LICENSE)
# Generated Doxygen Documentation
[Check this repository's gh-pages documentation on ECMS](https://stephen-seo.github.io/EntityComponentMetaSystem/)
# Compiling the UnitTests
Create a build directory.

9
doxygen/mainpage.dox Normal file
View file

@ -0,0 +1,9 @@
/*!
\mainpage EntityComponentMetaSystem Index Page
\ref md_README
<a href="annotated.html">Classes</a>
\ref EC::Manager "The Manager class that manages an Entity Component System"
*/

View file

@ -773,11 +773,7 @@ namespace EC
}
}, &fnDataAr[i]);
}
threadPool->wakeThreads();
do {
std::this_thread::sleep_for(std::chrono::microseconds(200));
} while(!threadPool->isQueueEmpty()
|| !threadPool->isAllThreadsWaiting());
threadPool->easyWakeAndWait();
}
}
@ -894,11 +890,7 @@ namespace EC
}
}, &fnDataAr[i]);
}
threadPool->wakeThreads();
do {
std::this_thread::sleep_for(std::chrono::microseconds(200));
} while(!threadPool->isQueueEmpty()
|| !threadPool->isAllThreadsWaiting());
threadPool->easyWakeAndWait();
}
}
@ -1039,12 +1031,7 @@ namespace EC
}
}, &fnDataAr[i]);
}
threadPool->wakeThreads();
do {
std::this_thread::sleep_for(
std::chrono::microseconds(200));
} while(!threadPool->isQueueEmpty()
|| !threadPool->isAllThreadsWaiting());
threadPool->easyWakeAndWait();
}
})));
@ -1119,11 +1106,7 @@ namespace EC
}
}, &fnDataAr[i]);
}
threadPool->wakeThreads();
do {
std::this_thread::sleep_for(std::chrono::microseconds(200));
} while(!threadPool->isQueueEmpty()
|| !threadPool->isAllThreadsWaiting());
threadPool->easyWakeAndWait();
}
return matchingV;
@ -1496,11 +1479,7 @@ namespace EC
}
}, &fnDataAr[i]);
}
threadPool->wakeThreads();
do {
std::this_thread::sleep_for(std::chrono::microseconds(200));
} while(!threadPool->isQueueEmpty()
|| !threadPool->isAllThreadsWaiting());
threadPool->easyWakeAndWait();
}
// call functions on matching entities
@ -1562,12 +1541,7 @@ namespace EC
}
}, &fnDataAr[i]);
}
threadPool->wakeThreads();
do {
std::this_thread::sleep_for(
std::chrono::microseconds(200));
} while(!threadPool->isQueueEmpty()
|| !threadPool->isAllThreadsWaiting());
threadPool->easyWakeAndWait();
}
}
);
@ -1705,11 +1679,7 @@ namespace EC
}
}, &fnDataAr[i]);
}
threadPool->wakeThreads();
do {
std::this_thread::sleep_for(std::chrono::microseconds(200));
} while(!threadPool->isQueueEmpty()
|| !threadPool->isAllThreadsWaiting());
threadPool->easyWakeAndWait();
}
// call functions on matching entities
@ -1776,12 +1746,7 @@ namespace EC
}
}, &fnDataAr[i]);
}
threadPool->wakeThreads();
do {
std::this_thread::sleep_for(
std::chrono::microseconds(200));
} while(!threadPool->isQueueEmpty()
|| !threadPool->isAllThreadsWaiting());
threadPool->easyWakeAndWait();
}
}
);
@ -1859,11 +1824,7 @@ namespace EC
}
}, &fnDataAr[i]);
}
threadPool->wakeThreads();
do {
std::this_thread::sleep_for(std::chrono::microseconds(200));
} while(!threadPool->isQueueEmpty()
|| !threadPool->isAllThreadsWaiting());
threadPool->easyWakeAndWait();
}
}
@ -1952,11 +1913,7 @@ namespace EC
}
}, &fnDataAr[i]);
}
threadPool->wakeThreads();
do {
std::this_thread::sleep_for(std::chrono::microseconds(200));
} while(!threadPool->isQueueEmpty()
|| !threadPool->isAllThreadsWaiting());
threadPool->easyWakeAndWait();
}
}
};

View file

@ -117,24 +117,7 @@ public:
cv.notify_one();
}
} else {
// pull functions from queue and run them on main thread
Internal::TPTupleType fnTuple;
bool hasFn;
do {
{
std::lock_guard<std::mutex> lock(queueMutex);
if(!fnQueue.empty()) {
hasFn = true;
fnTuple = fnQueue.front();
fnQueue.pop();
} else {
hasFn = false;
}
}
if(hasFn) {
std::get<0>(fnTuple)(std::get<1>(fnTuple));
}
} while(hasFn);
sequentiallyRunTasks();
}
}
@ -179,6 +162,26 @@ public:
return SIZE;
}
/*!
\brief Wakes all threads and blocks until all queued tasks are finished.
If SIZE is less than 2, then this function call will block until all the
queued functions have been executed on the calling thread.
If SIZE is 2 or greater, then this function will block until all the
queued functions have been executed by the threads in the thread pool.
*/
void easyWakeAndWait() {
if(SIZE >= 2) {
wakeThreads();
do {
std::this_thread::sleep_for(std::chrono::microseconds(150));
} while(!isQueueEmpty() || !isAllThreadsWaiting());
} else {
sequentiallyRunTasks();
}
}
private:
std::vector<std::thread> threads;
std::atomic_bool isAlive;
@ -189,6 +192,27 @@ private:
int waitCount;
std::mutex waitCountMutex;
void sequentiallyRunTasks() {
// pull functions from queue and run them on current thread
Internal::TPTupleType fnTuple;
bool hasFn;
do {
{
std::lock_guard<std::mutex> lock(queueMutex);
if(!fnQueue.empty()) {
hasFn = true;
fnTuple = fnQueue.front();
fnQueue.pop();
} else {
hasFn = false;
}
}
if(hasFn) {
std::get<0>(fnTuple)(std::get<1>(fnTuple));
}
} while(hasFn);
}
};
} // namespace EC

View file

@ -77,3 +77,30 @@ TEST(ECThreadPool, QueryCount) {
ASSERT_EQ(3, threeP.getThreadCount());
}
}
TEST(ECThreadPool, easyWakeAndWait) {
std::atomic_int data;
data.store(0);
{
OneThreadPool oneP;
for(unsigned int i = 0; i < 20; ++i) {
oneP.queueFn([] (void *ud) {
auto *atomicInt = static_cast<std::atomic_int*>(ud);
atomicInt->fetch_add(1);
}, &data);
}
oneP.easyWakeAndWait();
EXPECT_EQ(20, data.load());
}
{
ThreeThreadPool threeP;
for(unsigned int i = 0; i < 20; ++i) {
threeP.queueFn([] (void *ud) {
auto *atomicInt = static_cast<std::atomic_int*>(ud);
atomicInt->fetch_add(1);
}, &data);
}
threeP.easyWakeAndWait();
EXPECT_EQ(40, data.load());
}
}