Merge branch 'master' into cxx17
This commit is contained in:
commit
0a7929b0a4
7 changed files with 120 additions and 73 deletions
26
.github/workflows/gh-pages.yml
vendored
Normal file
26
.github/workflows/gh-pages.yml
vendored
Normal 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
|
4
Doxyfile
4
Doxyfile
|
@ -771,7 +771,7 @@ WARN_LOGFILE =
|
||||||
# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
|
# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
|
||||||
# Note: If this tag is empty the current directory is searched.
|
# 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
|
# 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
|
# 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,
|
# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f, *.for, *.tcl,
|
||||||
# *.vhd, *.vhdl, *.ucf, *.qsf, *.as and *.js.
|
# *.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
|
# The RECURSIVE tag can be used to specify whether or not subdirectories should
|
||||||
# be searched for input files as well.
|
# be searched for input files as well.
|
||||||
|
|
|
@ -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)
|
[(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
|
# Compiling the UnitTests
|
||||||
|
|
||||||
Create a build directory.
|
Create a build directory.
|
||||||
|
|
9
doxygen/mainpage.dox
Normal file
9
doxygen/mainpage.dox
Normal 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"
|
||||||
|
*/
|
|
@ -773,11 +773,7 @@ namespace EC
|
||||||
}
|
}
|
||||||
}, &fnDataAr[i]);
|
}, &fnDataAr[i]);
|
||||||
}
|
}
|
||||||
threadPool->wakeThreads();
|
threadPool->easyWakeAndWait();
|
||||||
do {
|
|
||||||
std::this_thread::sleep_for(std::chrono::microseconds(200));
|
|
||||||
} while(!threadPool->isQueueEmpty()
|
|
||||||
|| !threadPool->isAllThreadsWaiting());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -894,11 +890,7 @@ namespace EC
|
||||||
}
|
}
|
||||||
}, &fnDataAr[i]);
|
}, &fnDataAr[i]);
|
||||||
}
|
}
|
||||||
threadPool->wakeThreads();
|
threadPool->easyWakeAndWait();
|
||||||
do {
|
|
||||||
std::this_thread::sleep_for(std::chrono::microseconds(200));
|
|
||||||
} while(!threadPool->isQueueEmpty()
|
|
||||||
|| !threadPool->isAllThreadsWaiting());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1039,12 +1031,7 @@ namespace EC
|
||||||
}
|
}
|
||||||
}, &fnDataAr[i]);
|
}, &fnDataAr[i]);
|
||||||
}
|
}
|
||||||
threadPool->wakeThreads();
|
threadPool->easyWakeAndWait();
|
||||||
do {
|
|
||||||
std::this_thread::sleep_for(
|
|
||||||
std::chrono::microseconds(200));
|
|
||||||
} while(!threadPool->isQueueEmpty()
|
|
||||||
|| !threadPool->isAllThreadsWaiting());
|
|
||||||
}
|
}
|
||||||
})));
|
})));
|
||||||
|
|
||||||
|
@ -1119,11 +1106,7 @@ namespace EC
|
||||||
}
|
}
|
||||||
}, &fnDataAr[i]);
|
}, &fnDataAr[i]);
|
||||||
}
|
}
|
||||||
threadPool->wakeThreads();
|
threadPool->easyWakeAndWait();
|
||||||
do {
|
|
||||||
std::this_thread::sleep_for(std::chrono::microseconds(200));
|
|
||||||
} while(!threadPool->isQueueEmpty()
|
|
||||||
|| !threadPool->isAllThreadsWaiting());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return matchingV;
|
return matchingV;
|
||||||
|
@ -1496,11 +1479,7 @@ namespace EC
|
||||||
}
|
}
|
||||||
}, &fnDataAr[i]);
|
}, &fnDataAr[i]);
|
||||||
}
|
}
|
||||||
threadPool->wakeThreads();
|
threadPool->easyWakeAndWait();
|
||||||
do {
|
|
||||||
std::this_thread::sleep_for(std::chrono::microseconds(200));
|
|
||||||
} while(!threadPool->isQueueEmpty()
|
|
||||||
|| !threadPool->isAllThreadsWaiting());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// call functions on matching entities
|
// call functions on matching entities
|
||||||
|
@ -1562,12 +1541,7 @@ namespace EC
|
||||||
}
|
}
|
||||||
}, &fnDataAr[i]);
|
}, &fnDataAr[i]);
|
||||||
}
|
}
|
||||||
threadPool->wakeThreads();
|
threadPool->easyWakeAndWait();
|
||||||
do {
|
|
||||||
std::this_thread::sleep_for(
|
|
||||||
std::chrono::microseconds(200));
|
|
||||||
} while(!threadPool->isQueueEmpty()
|
|
||||||
|| !threadPool->isAllThreadsWaiting());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -1705,11 +1679,7 @@ namespace EC
|
||||||
}
|
}
|
||||||
}, &fnDataAr[i]);
|
}, &fnDataAr[i]);
|
||||||
}
|
}
|
||||||
threadPool->wakeThreads();
|
threadPool->easyWakeAndWait();
|
||||||
do {
|
|
||||||
std::this_thread::sleep_for(std::chrono::microseconds(200));
|
|
||||||
} while(!threadPool->isQueueEmpty()
|
|
||||||
|| !threadPool->isAllThreadsWaiting());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// call functions on matching entities
|
// call functions on matching entities
|
||||||
|
@ -1776,12 +1746,7 @@ namespace EC
|
||||||
}
|
}
|
||||||
}, &fnDataAr[i]);
|
}, &fnDataAr[i]);
|
||||||
}
|
}
|
||||||
threadPool->wakeThreads();
|
threadPool->easyWakeAndWait();
|
||||||
do {
|
|
||||||
std::this_thread::sleep_for(
|
|
||||||
std::chrono::microseconds(200));
|
|
||||||
} while(!threadPool->isQueueEmpty()
|
|
||||||
|| !threadPool->isAllThreadsWaiting());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -1859,11 +1824,7 @@ namespace EC
|
||||||
}
|
}
|
||||||
}, &fnDataAr[i]);
|
}, &fnDataAr[i]);
|
||||||
}
|
}
|
||||||
threadPool->wakeThreads();
|
threadPool->easyWakeAndWait();
|
||||||
do {
|
|
||||||
std::this_thread::sleep_for(std::chrono::microseconds(200));
|
|
||||||
} while(!threadPool->isQueueEmpty()
|
|
||||||
|| !threadPool->isAllThreadsWaiting());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1952,11 +1913,7 @@ namespace EC
|
||||||
}
|
}
|
||||||
}, &fnDataAr[i]);
|
}, &fnDataAr[i]);
|
||||||
}
|
}
|
||||||
threadPool->wakeThreads();
|
threadPool->easyWakeAndWait();
|
||||||
do {
|
|
||||||
std::this_thread::sleep_for(std::chrono::microseconds(200));
|
|
||||||
} while(!threadPool->isQueueEmpty()
|
|
||||||
|| !threadPool->isAllThreadsWaiting());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -117,24 +117,7 @@ public:
|
||||||
cv.notify_one();
|
cv.notify_one();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// pull functions from queue and run them on main thread
|
sequentiallyRunTasks();
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -179,6 +162,26 @@ public:
|
||||||
return SIZE;
|
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:
|
private:
|
||||||
std::vector<std::thread> threads;
|
std::vector<std::thread> threads;
|
||||||
std::atomic_bool isAlive;
|
std::atomic_bool isAlive;
|
||||||
|
@ -189,6 +192,27 @@ private:
|
||||||
int waitCount;
|
int waitCount;
|
||||||
std::mutex waitCountMutex;
|
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
|
} // namespace EC
|
||||||
|
|
|
@ -77,3 +77,30 @@ TEST(ECThreadPool, QueryCount) {
|
||||||
ASSERT_EQ(3, threeP.getThreadCount());
|
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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue