Compare commits
15 Commits
35140ee002
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 93547beb38 | |||
| 5794eac20a | |||
| edb7189013 | |||
| dc16a0c903 | |||
| 96c22e1184 | |||
| 4537e40832 | |||
| 6efe77a395 | |||
| 6cfc4524f0 | |||
| fe3b30bd49 | |||
|
a1be5be5a1
|
|||
|
99c99c39c2
|
|||
| ba63e72bfa | |||
| 79fa549201 | |||
| ba57aa0144 | |||
| ccbf86f781 |
@@ -97,8 +97,10 @@ public:
|
||||
{
|
||||
int code = lua_pcall (L, nargs, nresults, msgh);
|
||||
|
||||
if (code != LUABRIDGE_LUA_OK)
|
||||
Throw (LuaException (L, code));
|
||||
if (code != LUABRIDGE_LUA_OK) {
|
||||
// Throw (LuaException (L, code));
|
||||
assert(true);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -128,7 +130,8 @@ protected:
|
||||
private:
|
||||
static int throwAtPanic (lua_State* L)
|
||||
{
|
||||
throw LuaException (L, -1);
|
||||
// throw LuaException (L, -1);
|
||||
return -1;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -101,7 +101,8 @@ protected:
|
||||
{
|
||||
if (m_stackSize == 0)
|
||||
{
|
||||
throw std::logic_error ("Unable to continue registration");
|
||||
std::cerr << ("Unable to continue registration");
|
||||
assert(true);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -1054,7 +1055,8 @@ public:
|
||||
{
|
||||
if (m_stackSize == 1)
|
||||
{
|
||||
throw std::logic_error ("endNamespace () called on global namespace");
|
||||
std::cerr << ("endNamespace () called on global namespace");
|
||||
assert(true);
|
||||
}
|
||||
|
||||
assert (m_stackSize > 1);
|
||||
@@ -1150,7 +1152,8 @@ public:
|
||||
{
|
||||
if (m_stackSize == 1)
|
||||
{
|
||||
throw std::logic_error ("addProperty () called on global namespace");
|
||||
std::cerr << ("addProperty () called on global namespace");
|
||||
assert(true);
|
||||
}
|
||||
|
||||
assert (lua_istable (L, -1)); // Stack: namespace table (ns)
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
|
||||
#include <cassert>
|
||||
#include <stdexcept>
|
||||
#include <iostream>
|
||||
|
||||
|
||||
namespace luabridge {
|
||||
@@ -320,7 +321,8 @@ public:
|
||||
lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getClassKey ());
|
||||
if (!lua_istable (L, -1))
|
||||
{
|
||||
throw std::logic_error ("The class is not registered in LuaBridge");
|
||||
std::cerr << ("The class is not registered in LuaBridge");
|
||||
assert(true);
|
||||
}
|
||||
lua_setmetatable (L, -2);
|
||||
return ud;
|
||||
@@ -375,7 +377,8 @@ private:
|
||||
lua_rawgetp (L, LUA_REGISTRYINDEX, key);
|
||||
if (!lua_istable (L, -1))
|
||||
{
|
||||
throw std::logic_error ("The class is not registered in LuaBridge");
|
||||
std::cerr << ("The class is not registered in LuaBridge");
|
||||
assert(true);
|
||||
}
|
||||
lua_setmetatable (L, -2);
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ endif()
|
||||
project(PIP)
|
||||
set(PIP_MAJOR 5)
|
||||
set(PIP_MINOR 6)
|
||||
set(PIP_REVISION 0)
|
||||
set(PIP_REVISION 1)
|
||||
set(PIP_SUFFIX )
|
||||
set(PIP_COMPANY SHS)
|
||||
set(PIP_DOMAIN org.SHS)
|
||||
@@ -67,11 +67,13 @@ set(PIP_DLL_DIR "${CMAKE_CURRENT_BINARY_DIR}" CACHE STRING "")
|
||||
option(ICU "ICU support for convert codepages" ${_ICU_DEFAULT})
|
||||
option(STD_IOSTREAM "Building with std iostream operators support" OFF)
|
||||
option(INTROSPECTION "Build with introspection" OFF)
|
||||
option(TESTS "Build tests and perform their before install step" OFF)
|
||||
option(TESTS "Build tests" OFF)
|
||||
option(TESTS_RUN "Run tests before install step" OFF)
|
||||
option(COVERAGE "Build project with coverage info" OFF)
|
||||
option(PIP_FFTW_F "Support fftw module for float" ON)
|
||||
option(PIP_FFTW_L "Support fftw module for long double" ON)
|
||||
option(PIP_FFTW_Q "Support fftw module for quad double" OFF)
|
||||
option(PIP_MANUAL_TEST "Build dev test (main.cpp)" OFF)
|
||||
set(PIP_UTILS 1)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED TRUE)
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
@@ -360,10 +362,13 @@ endif()
|
||||
if(WIN32)
|
||||
add_definitions(-DPSAPI_VERSION=1)
|
||||
if(${C_COMPILER} STREQUAL "cl.exe")
|
||||
set(CMAKE_CXX_FLAGS "/O2 /Ob2 /Ot /W0")
|
||||
set(CMAKE_CXX_FLAGS "/O2 /Ob2 /Ot /W0 /EH-")
|
||||
endif()
|
||||
else()
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC")
|
||||
if (NOT DEFINED ANDROID_PLATFORM)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-exceptions")
|
||||
endif()
|
||||
if(DEFINED ENV{QNX_HOST} OR PIP_FREERTOS)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ftemplate-depth-32")
|
||||
endif()
|
||||
@@ -592,12 +597,14 @@ if (NOT CROSSTOOLS)
|
||||
#target_link_libraries(pip_plugin pip)
|
||||
|
||||
if (NOT DEFINED ANDROID_PLATFORM)
|
||||
if(microhttpd_FOUND AND curl_FOUND)
|
||||
add_executable(pip_test "main.cpp")
|
||||
target_link_libraries(pip_test pip pip_io_utils pip_client_server pip_http_server pip_http_client)
|
||||
if(sodium_FOUND)
|
||||
add_executable(pip_cloud_test "main_picloud_test.cpp")
|
||||
target_link_libraries(pip_cloud_test pip_cloud)
|
||||
if (PIP_MANUAL_TEST)
|
||||
if(microhttpd_FOUND AND curl_FOUND)
|
||||
add_executable(pip_test "main.cpp")
|
||||
target_link_libraries(pip_test pip pip_io_utils pip_client_server pip_http_server pip_http_client)
|
||||
if(sodium_FOUND)
|
||||
add_executable(pip_cloud_test "main_picloud_test.cpp")
|
||||
target_link_libraries(pip_cloud_test pip_cloud)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
@@ -823,6 +830,9 @@ if (PIP_TESTS_LIST)
|
||||
foreach(_test ${PIP_TESTS_LIST})
|
||||
message(" * ${_test}")
|
||||
endforeach()
|
||||
if (TESTS_RUN)
|
||||
message("TESTS_RUN ON -> Run tests before install step")
|
||||
endif()
|
||||
else()
|
||||
message(" Tests: skip (tests off)")
|
||||
endif()
|
||||
|
||||
@@ -247,7 +247,7 @@ PIHTTPClient * PIHTTPClient::onFinish(std::function<void()> f) {
|
||||
|
||||
|
||||
PIHTTPClient * PIHTTPClient::onFinish(std::function<void(const PIHTTP::MessageConst &)> f) {
|
||||
on_finish = f;
|
||||
on_finish = std::move(f);
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -258,7 +258,7 @@ PIHTTPClient * PIHTTPClient::onError(std::function<void()> f) {
|
||||
|
||||
|
||||
PIHTTPClient * PIHTTPClient::onError(std::function<void(const PIHTTP::MessageConst &)> f) {
|
||||
on_error = f;
|
||||
on_error = std::move(f);
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -269,7 +269,7 @@ PIHTTPClient * PIHTTPClient::onAbort(std::function<void()> f) {
|
||||
|
||||
|
||||
PIHTTPClient * PIHTTPClient::onAbort(std::function<void(const PIHTTP::MessageConst &)> f) {
|
||||
on_abort = f;
|
||||
on_abort = std::move(f);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ bool PIHTTPServer::registerPath(const PIString & path, PIHTTP::Method method, Re
|
||||
Endpoint ep;
|
||||
if (!ep.create(path)) return false;
|
||||
ep.method = method;
|
||||
ep.function = functor;
|
||||
ep.function = std::move(functor);
|
||||
endpoints[ep.priority] << ep;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -103,7 +103,7 @@ public:
|
||||
|
||||
//! \~english Sets the factory used to create accepted client objects.
|
||||
//! \~russian Устанавливает фабрику, создающую объекты принятых клиентов.
|
||||
void setClientFactory(std::function<ServerClient *()> f) { client_factory = f; }
|
||||
void setClientFactory(std::function<ServerClient *()> f) { client_factory = std::move(f); }
|
||||
|
||||
private:
|
||||
void newClient(ServerClient * c);
|
||||
|
||||
@@ -204,7 +204,7 @@ public:
|
||||
|
||||
//! \~english Sets the callback receiving both key event and user data.
|
||||
//! \~russian Устанавливает обратный вызов, получающий событие клавиши и пользовательские данные.
|
||||
void setSlot(KBFunc slot) { ret_func = slot; }
|
||||
void setSlot(KBFunc slot) { ret_func = std::move(slot); }
|
||||
|
||||
//! \~english Sets the callback that only receives the key event and ignores user data.
|
||||
//! \~russian Устанавливает обратный вызов, получающий только событие клавиши и игнорирующий пользовательские данные.
|
||||
|
||||
@@ -184,7 +184,7 @@ public:
|
||||
//! \endcode
|
||||
inline PIDeque(size_t piv_size, std::function<T(size_t i)> f) {
|
||||
PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T))
|
||||
expand(piv_size, f);
|
||||
expand(piv_size, std::move(f));
|
||||
}
|
||||
|
||||
//! \~english Move constructor.
|
||||
@@ -729,7 +729,7 @@ public:
|
||||
//! заданному в передаваемой функции `test`, или `def` если такого элемента нет.
|
||||
//! \~\sa \a indexWhere()
|
||||
inline const T & atWhere(std::function<bool(const T & e)> test, ssize_t start = 0, const T & def = T()) const {
|
||||
const ssize_t i = indexWhere(test, start);
|
||||
const ssize_t i = indexWhere(std::move(test), start);
|
||||
if (i < 0)
|
||||
return def;
|
||||
else
|
||||
@@ -743,7 +743,7 @@ public:
|
||||
//! заданному в передаваемой функции `test`, или `def` если такого элемента нет.
|
||||
//! \~\sa \a lastIndexWhere()
|
||||
inline const T & lastAtWhere(std::function<bool(const T & e)> test, ssize_t start = -1, const T & def = T()) const {
|
||||
const ssize_t i = lastIndexWhere(test, start);
|
||||
const ssize_t i = lastIndexWhere(std::move(test), start);
|
||||
if (i < 0)
|
||||
return def;
|
||||
else
|
||||
@@ -1265,7 +1265,7 @@ public:
|
||||
deleteT(pid_data + pid_start + new_size, pid_size - new_size);
|
||||
pid_size = new_size;
|
||||
} else if (new_size > pid_size) {
|
||||
expand(new_size, f);
|
||||
expand(new_size, std::move(f));
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
@@ -1328,15 +1328,15 @@ public:
|
||||
if (index < pid_size - 1) {
|
||||
const size_t os = pid_size - index - 1;
|
||||
memmove(reinterpret_cast<void *>(pid_data + pid_start + index + 1),
|
||||
reinterpret_cast<const void *>(pid_data + pid_start + index),
|
||||
os * sizeof(T));
|
||||
reinterpret_cast<const void *>(pid_data + pid_start + index),
|
||||
os * sizeof(T));
|
||||
}
|
||||
} else {
|
||||
alloc_backward(pid_size + 1, -1);
|
||||
if (index > 0) {
|
||||
memmove(reinterpret_cast<void *>(pid_data + pid_start),
|
||||
reinterpret_cast<const void *>(pid_data + pid_start + 1),
|
||||
index * sizeof(T));
|
||||
reinterpret_cast<const void *>(pid_data + pid_start + 1),
|
||||
index * sizeof(T));
|
||||
}
|
||||
}
|
||||
elementNew(pid_data + pid_start + index, e);
|
||||
@@ -1358,15 +1358,15 @@ public:
|
||||
if (index < pid_size - 1) {
|
||||
const size_t os = pid_size - index - 1;
|
||||
memmove(reinterpret_cast<void *>(pid_data + pid_start + index + 1),
|
||||
reinterpret_cast<const void *>(pid_data + pid_start + index),
|
||||
os * sizeof(T));
|
||||
reinterpret_cast<const void *>(pid_data + pid_start + index),
|
||||
os * sizeof(T));
|
||||
}
|
||||
} else {
|
||||
alloc_backward(pid_size + 1, -1);
|
||||
if (index > 0) {
|
||||
memmove(reinterpret_cast<void *>(pid_data + pid_start),
|
||||
reinterpret_cast<const void *>(pid_data + pid_start + 1),
|
||||
index * sizeof(T));
|
||||
reinterpret_cast<const void *>(pid_data + pid_start + 1),
|
||||
index * sizeof(T));
|
||||
}
|
||||
}
|
||||
elementNew(pid_data + pid_start + index, std::move(e));
|
||||
@@ -1393,15 +1393,15 @@ public:
|
||||
alloc_forward(pid_size + v.pid_size);
|
||||
if (os > 0) {
|
||||
memmove(reinterpret_cast<void *>(pid_data + pid_start + index + v.pid_size),
|
||||
reinterpret_cast<const void *>(pid_data + pid_start + index),
|
||||
os * sizeof(T));
|
||||
reinterpret_cast<const void *>(pid_data + pid_start + index),
|
||||
os * sizeof(T));
|
||||
}
|
||||
} else {
|
||||
alloc_backward(pid_size + v.pid_size, -v.pid_size);
|
||||
if (index > 0) {
|
||||
memmove(reinterpret_cast<void *>(pid_data + pid_start),
|
||||
reinterpret_cast<const void *>(pid_data + pid_start + v.pid_size),
|
||||
index * sizeof(T));
|
||||
reinterpret_cast<const void *>(pid_data + pid_start + v.pid_size),
|
||||
index * sizeof(T));
|
||||
}
|
||||
}
|
||||
newT(pid_data + pid_start + index, v.pid_data + v.pid_start, v.pid_size);
|
||||
@@ -1426,15 +1426,15 @@ public:
|
||||
alloc_forward(pid_size + init_list.size());
|
||||
if (os > 0) {
|
||||
memmove(reinterpret_cast<void *>(pid_data + pid_start + index + init_list.size()),
|
||||
reinterpret_cast<const void *>(pid_data + pid_start + index),
|
||||
reinterpret_cast<const void *>(pid_data + pid_start + index),
|
||||
os * sizeof(T));
|
||||
}
|
||||
} else {
|
||||
alloc_backward(pid_size + init_list.size(), -init_list.size());
|
||||
if (index > 0) {
|
||||
memmove(reinterpret_cast<void *>(pid_data + pid_start),
|
||||
reinterpret_cast<const void *>(pid_data + pid_start + init_list.size()),
|
||||
index * sizeof(T));
|
||||
reinterpret_cast<const void *>(pid_data + pid_start + init_list.size()),
|
||||
index * sizeof(T));
|
||||
}
|
||||
}
|
||||
newT(pid_data + pid_start + index, init_list.begin(), init_list.size());
|
||||
@@ -1462,13 +1462,13 @@ public:
|
||||
deleteT(pid_data + pid_start + index, count);
|
||||
if (os <= index) {
|
||||
memmove(reinterpret_cast<void *>(pid_data + pid_start + index),
|
||||
reinterpret_cast<const void *>(pid_data + pid_start + index + count),
|
||||
os * sizeof(T));
|
||||
reinterpret_cast<const void *>(pid_data + pid_start + index + count),
|
||||
os * sizeof(T));
|
||||
} else {
|
||||
if (index > 0) {
|
||||
memmove(reinterpret_cast<void *>(pid_data + pid_start + count),
|
||||
reinterpret_cast<const void *>(pid_data + pid_start),
|
||||
index * sizeof(T));
|
||||
reinterpret_cast<const void *>(pid_data + pid_start),
|
||||
index * sizeof(T));
|
||||
}
|
||||
pid_start += count;
|
||||
}
|
||||
@@ -1540,7 +1540,7 @@ public:
|
||||
//! \endcode
|
||||
//! \~\sa \a sort()
|
||||
inline PIDeque<T> & sort(std::function<bool(const T & a, const T & b)> comp) {
|
||||
std::stable_sort(begin(), end(), comp);
|
||||
std::stable_sort(begin(), end(), std::move(comp));
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -1654,7 +1654,13 @@ public:
|
||||
//! \endcode
|
||||
//! \~\sa \a remove(), \a removeOne(), \a removeWhere()
|
||||
inline PIDeque<T> & removeWhere(std::function<bool(const T & e)> test) {
|
||||
ssize_t j = indexWhere(test);
|
||||
ssize_t j = -1;
|
||||
for (size_t i = pid_start; i < pid_start + pid_size; ++i) {
|
||||
if (test(pid_data[i])) {
|
||||
j = ssize_t(i) - pid_start;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (j != -1) {
|
||||
for (size_t i = j + 1; i < pid_size; ++i) {
|
||||
if (!test(pid_data[i + pid_start])) {
|
||||
@@ -2545,21 +2551,21 @@ public:
|
||||
if (index + count > pid_size) count = pid_size - index;
|
||||
ret.alloc_forward(count);
|
||||
memcpy(reinterpret_cast<void *>(ret.pid_data + ret.pid_start),
|
||||
reinterpret_cast<const void *>(pid_data + pid_start + index),
|
||||
count * sizeof(T));
|
||||
reinterpret_cast<const void *>(pid_data + pid_start + index),
|
||||
count * sizeof(T));
|
||||
|
||||
const size_t os = pid_size - index - count;
|
||||
if (os <= index) {
|
||||
if (os > 0) {
|
||||
memmove(reinterpret_cast<void *>(pid_data + pid_start + index),
|
||||
reinterpret_cast<const void *>(pid_data + pid_start + index + count),
|
||||
os * sizeof(T));
|
||||
reinterpret_cast<const void *>(pid_data + pid_start + index + count),
|
||||
os * sizeof(T));
|
||||
}
|
||||
} else {
|
||||
if (index > 0) {
|
||||
memmove(reinterpret_cast<void *>(pid_data + pid_start + count),
|
||||
reinterpret_cast<const void *>(pid_data + pid_start),
|
||||
index * sizeof(T));
|
||||
reinterpret_cast<const void *>(pid_data + pid_start),
|
||||
index * sizeof(T));
|
||||
}
|
||||
pid_start += count;
|
||||
}
|
||||
@@ -2646,8 +2652,8 @@ private:
|
||||
size_t ns = (pid_rsize - pid_size) / 2;
|
||||
if (pid_start != ns) {
|
||||
memmove(reinterpret_cast<void *>(pid_data + ns),
|
||||
reinterpret_cast<const void *>(pid_data + pid_start),
|
||||
pid_size * sizeof(T));
|
||||
reinterpret_cast<const void *>(pid_data + pid_start),
|
||||
pid_size * sizeof(T));
|
||||
pid_start = ns;
|
||||
}
|
||||
}
|
||||
@@ -2656,8 +2662,8 @@ private:
|
||||
const size_t ns = (pid_rsize - pid_size) / 2;
|
||||
if (pid_start != ns) {
|
||||
memmove(reinterpret_cast<void *>(pid_data + ns),
|
||||
reinterpret_cast<const void *>(pid_data + pid_start),
|
||||
pid_size * sizeof(T));
|
||||
reinterpret_cast<const void *>(pid_data + pid_start),
|
||||
pid_size * sizeof(T));
|
||||
pid_start = ns;
|
||||
}
|
||||
}
|
||||
@@ -2694,8 +2700,8 @@ private:
|
||||
PIINTROSPECTION_CONTAINER_ALLOC(T, (as - pid_rsize))
|
||||
if (pid_rsize > 0 && pid_data) {
|
||||
memcpy(reinterpret_cast<void *>(tmp_data + new_start),
|
||||
reinterpret_cast<const void *>(pid_data + pid_start),
|
||||
pid_size * sizeof(T));
|
||||
reinterpret_cast<const void *>(pid_data + pid_start),
|
||||
pid_size * sizeof(T));
|
||||
dealloc();
|
||||
}
|
||||
pid_data = tmp_data;
|
||||
|
||||
@@ -184,7 +184,7 @@ public:
|
||||
//! \endcode
|
||||
inline PIVector(size_t size, std::function<T(size_t i)> f) {
|
||||
PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T))
|
||||
expand(size, f);
|
||||
expand(size, std::move(f));
|
||||
}
|
||||
|
||||
//! \~english Move constructor.
|
||||
@@ -725,7 +725,7 @@ public:
|
||||
//! заданному в передаваемой функции `test`, или `def` если такого элемента нет.
|
||||
//! \~\sa \a indexWhere()
|
||||
inline const T & atWhere(std::function<bool(const T & e)> test, ssize_t start = 0, const T & def = T()) const {
|
||||
const ssize_t i = indexWhere(test, start);
|
||||
const ssize_t i = indexWhere(std::move(test), start);
|
||||
if (i < 0)
|
||||
return def;
|
||||
else
|
||||
@@ -739,7 +739,7 @@ public:
|
||||
//! заданному в передаваемой функции `test`, или `def` если такого элемента нет.
|
||||
//! \~\sa \a lastIndexWhere()
|
||||
inline const T & lastAtWhere(std::function<bool(const T & e)> test, ssize_t start = -1, const T & def = T()) const {
|
||||
const ssize_t i = lastIndexWhere(test, start);
|
||||
const ssize_t i = lastIndexWhere(std::move(test), start);
|
||||
if (i < 0)
|
||||
return def;
|
||||
else
|
||||
@@ -1267,7 +1267,7 @@ public:
|
||||
deleteT(piv_data + new_size, piv_size - new_size);
|
||||
piv_size = new_size;
|
||||
} else if (new_size > piv_size) {
|
||||
expand(new_size, f);
|
||||
expand(new_size, std::move(f));
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
@@ -1486,7 +1486,7 @@ public:
|
||||
//! \endcode
|
||||
//! \~\sa \a sort()
|
||||
inline PIVector<T> & sort(std::function<bool(const T & a, const T & b)> comp) {
|
||||
std::stable_sort(begin(), end(), comp);
|
||||
std::stable_sort(begin(), end(), std::move(comp));
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -1599,7 +1599,13 @@ public:
|
||||
//! \endcode
|
||||
//! \~\sa \a remove(), \a removeOne(), \a removeWhere()
|
||||
inline PIVector<T> & removeWhere(std::function<bool(const T & e)> test) {
|
||||
ssize_t j = indexWhere(test);
|
||||
ssize_t j = -1;
|
||||
for (size_t i = 0; i < piv_size; ++i) {
|
||||
if (test(piv_data[i])) {
|
||||
j = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (j != -1) {
|
||||
for (size_t i = j + 1; i < piv_size; ++i) {
|
||||
if (!test(piv_data[i])) {
|
||||
|
||||
@@ -1070,7 +1070,7 @@ public:
|
||||
//! \~english Counts elements in the flat vector that pass the `test`.
|
||||
//! \~russian Подсчитывает элементы в плоском векторе, проходящие `test`.
|
||||
//! \~\sa PIVector::entries(std::function)
|
||||
inline int entries(std::function<bool(const T & e)> test) const { return mat.entries(test); }
|
||||
inline int entries(std::function<bool(const T & e)> test) const { return mat.entries(std::move(test)); }
|
||||
|
||||
|
||||
//! \~english Returns the first index (row, col) of `e` in the 2D array.
|
||||
@@ -1086,7 +1086,7 @@ public:
|
||||
//! \~russian Возвращает первый индекс (строка, столбец) в двумерном массиве, проходящий `test`.
|
||||
//! \~\sa PIVector::indexWhere()
|
||||
inline Index indexWhere(std::function<bool(const T & e)> test, ssize_t start = 0) const {
|
||||
ssize_t flat = mat.indexWhere(test, start);
|
||||
ssize_t flat = mat.indexWhere(std::move(test), start);
|
||||
if (flat < 0 || cols_ == 0) return Index{-1, -1};
|
||||
return Index{flat / static_cast<ssize_t>(cols_), flat % static_cast<ssize_t>(cols_)};
|
||||
}
|
||||
@@ -1104,7 +1104,7 @@ public:
|
||||
//! \~russian Возвращает последний индекс (строка, столбец) в двумерном массиве, проходящий `test`.
|
||||
//! \~\sa PIVector::lastIndexWhere()
|
||||
inline Index lastIndexWhere(std::function<bool(const T & e)> test, ssize_t start = -1) const {
|
||||
ssize_t flat = mat.lastIndexWhere(test, start);
|
||||
ssize_t flat = mat.lastIndexWhere(std::move(test), start);
|
||||
if (flat < 0 || cols_ == 0) return Index{-1, -1};
|
||||
return Index{flat / static_cast<ssize_t>(cols_), flat % static_cast<ssize_t>(cols_)};
|
||||
}
|
||||
@@ -1113,12 +1113,12 @@ public:
|
||||
//! \~english Tests if any element in the flat vector passes the `test`.
|
||||
//! \~russian Проверяет, проходит ли какой-либо элемент в плоском векторе `test`.
|
||||
//! \~\sa PIVector::any()
|
||||
inline bool any(std::function<bool(const T & e)> test) const { return mat.any(test); }
|
||||
inline bool any(std::function<bool(const T & e)> test) const { return mat.any(std::move(test)); }
|
||||
|
||||
//! \~english Tests if all elements in the flat vector pass the `test`.
|
||||
//! \~russian Проверяет, проходят ли все элементы в плоском векторе `test`.
|
||||
//! \~\sa PIVector::every()
|
||||
inline bool every(std::function<bool(const T & e)> test) const { return mat.every(test); }
|
||||
inline bool every(std::function<bool(const T & e)> test) const { return mat.every(std::move(test)); }
|
||||
|
||||
//! \~english Fills the entire 2D array with copies of `e`.
|
||||
//! \~russian Заполняет весь двумерный массив копиями `e`.
|
||||
@@ -1132,7 +1132,7 @@ public:
|
||||
//! \~russian Заполняет весь двумерный массив, используя функцию-генератор `f` на основе плоского индекса.
|
||||
//! \~\sa PIVector::fill(std::function)
|
||||
inline PIVector2D<T> & fill(std::function<T(size_t i)> f) {
|
||||
mat.fill(f);
|
||||
mat.fill(std::move(f));
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -1228,7 +1228,7 @@ public:
|
||||
//! \~\sa PIVector::map()
|
||||
template<typename ST>
|
||||
inline PIVector2D<ST> map(std::function<ST(const T & e)> f) const {
|
||||
return PIVector2D<ST>(rows_, cols_, mat.template map<ST>(f));
|
||||
return PIVector2D<ST>(rows_, cols_, mat.template map<ST>(std::move(f)));
|
||||
}
|
||||
|
||||
//! \~english Applies a function (with row and col indices) to each element and returns a new 2D array.
|
||||
@@ -1250,23 +1250,26 @@ public:
|
||||
//! \~russian Применяет функцию к каждой строке (с возможностью изменения).
|
||||
//! \~\sa forEachRow() const, PIVector::forEach()
|
||||
inline PIVector2D<T> & forEachRow(std::function<void(Row)> f) {
|
||||
for (size_t r = 0; r < rows_; ++r)
|
||||
for (size_t r = 0; r < rows_; ++r) {
|
||||
f(row(r));
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
//! \~english Applies a function to each row (read-only).
|
||||
//! \~russian Применяет функцию к каждой строке (только чтение).
|
||||
inline void forEachRow(std::function<void(RowConst)> f) const {
|
||||
for (size_t r = 0; r < rows_; ++r)
|
||||
for (size_t r = 0; r < rows_; ++r) {
|
||||
f(row(r));
|
||||
}
|
||||
}
|
||||
|
||||
//! \~english Applies a function to each column (modifiable).
|
||||
//! \~russian Применяет функцию к каждому столбцу (с возможностью изменения).
|
||||
inline PIVector2D<T> & forEachColumn(std::function<void(Col)> f) {
|
||||
for (size_t c = 0; c < cols_; ++c)
|
||||
for (size_t c = 0; c < cols_; ++c) {
|
||||
f(col(c));
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -1274,8 +1277,9 @@ public:
|
||||
//! \~russian Применяет функцию к каждому столбцу (только чтение).
|
||||
//! \param f Function taking a \a ColConst.
|
||||
inline void forEachColumn(std::function<void(ColConst)> f) const {
|
||||
for (size_t c = 0; c < cols_; ++c)
|
||||
for (size_t c = 0; c < cols_; ++c) {
|
||||
f(col(c));
|
||||
}
|
||||
}
|
||||
|
||||
//! \~english Accumulates a value across all elements.
|
||||
@@ -1283,7 +1287,7 @@ public:
|
||||
//! \~\sa PIVector::reduce()
|
||||
template<typename ST>
|
||||
inline ST reduce(std::function<ST(const T & e, const ST & acc)> f, const ST & initial = ST()) const {
|
||||
return mat.template reduce<ST>(f, initial);
|
||||
return mat.template reduce<ST>(std::move(f), initial);
|
||||
}
|
||||
|
||||
//! \~english Accumulates a value across all elements with indices.
|
||||
|
||||
@@ -726,11 +726,12 @@ inline bool piDeleteSafety(T *& pointer) {
|
||||
//! \~english In this example "Error!" will be printed on every \b false function return.
|
||||
//! \~russian В данном примере будет выведен "Error!" при каждом \b false возврате из функции.
|
||||
class PIP_EXPORT PIScopeExitCall {
|
||||
NO_COPY_CLASS(PIScopeExitCall)
|
||||
public:
|
||||
//! \~\brief
|
||||
//! \~english Constructor that takes a function to execute
|
||||
//! \~russian Конструктор, который принимает функцию для выполнения
|
||||
explicit PIScopeExitCall(std::function<void()> f): func(f) {}
|
||||
explicit PIScopeExitCall(std::function<void()> f): func(std::move(f)) {}
|
||||
|
||||
//! \~\brief
|
||||
//! \~english Destructor that executes the function if it exists
|
||||
@@ -758,8 +759,6 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
NO_COPY_CLASS(PIScopeExitCall)
|
||||
|
||||
std::function<void()> func;
|
||||
};
|
||||
|
||||
@@ -768,14 +767,14 @@ private:
|
||||
//! \~english Inherit from this class to make your class non-trivially copyable.
|
||||
//! \~russian Наследуйтесь от этого класса чтобы сделать свой класс нетривиально копируемым.
|
||||
struct PIP_EXPORT PINonTriviallyCopyable {
|
||||
PINonTriviallyCopyable() noexcept = default;
|
||||
PINonTriviallyCopyable(const PINonTriviallyCopyable &) noexcept = default;
|
||||
PINonTriviallyCopyable(PINonTriviallyCopyable &&) noexcept;
|
||||
PINonTriviallyCopyable & operator=(const PINonTriviallyCopyable &) noexcept = default;
|
||||
PINonTriviallyCopyable & operator=(PINonTriviallyCopyable &&) noexcept = default;
|
||||
PINonTriviallyCopyable() = default;
|
||||
PINonTriviallyCopyable(const PINonTriviallyCopyable &) = default;
|
||||
PINonTriviallyCopyable(PINonTriviallyCopyable &&) ;
|
||||
PINonTriviallyCopyable & operator=(const PINonTriviallyCopyable &) = default;
|
||||
PINonTriviallyCopyable & operator=(PINonTriviallyCopyable &&) = default;
|
||||
~PINonTriviallyCopyable() = default;
|
||||
};
|
||||
inline PINonTriviallyCopyable::PINonTriviallyCopyable(PINonTriviallyCopyable &&) noexcept = default;
|
||||
inline PINonTriviallyCopyable::PINonTriviallyCopyable(PINonTriviallyCopyable &&) = default;
|
||||
|
||||
|
||||
//! \~\brief
|
||||
|
||||
@@ -113,11 +113,11 @@ public:
|
||||
|
||||
//! \~english Sets the callback that receives parsed requests and returns replies.
|
||||
//! \~russian Устанавливает callback, который получает разобранные запросы и возвращает ответы.
|
||||
void setRequestCallback(std::function<PIHTTP::MessageMutable(const PIHTTP::MessageConst &)> c) { callback = c; }
|
||||
void setRequestCallback(std::function<PIHTTP::MessageMutable(const PIHTTP::MessageConst &)> c) { callback = std::move(c); }
|
||||
|
||||
//! \~english Sets the credential validator used when HTTP Basic authentication is enabled.
|
||||
//! \~russian Устанавливает валидатор учетных данных, используемый при включенной HTTP Basic-аутентификации.
|
||||
void setBasicAuthCallback(std::function<bool(const PIString &, const PIString &)> c) { callback_auth = c; }
|
||||
void setBasicAuthCallback(std::function<bool(const PIString &, const PIString &)> c) { callback_auth = std::move(c); }
|
||||
|
||||
private:
|
||||
static void addFixedHeaders(PIHTTP::MessageMutable & msg);
|
||||
|
||||
@@ -419,7 +419,7 @@ public:
|
||||
//! \~\param f
|
||||
//! \~english The callback function returning the next file path, or nullptr to use the internal generator.
|
||||
//! \~russian Функция обратного вызова, возвращающая путь к следующему файлу, или nullptr для использования внутреннего генератора.
|
||||
void setFuncGetNewFilePath(std::function<PIString()> f) { f_new_path = f; }
|
||||
void setFuncGetNewFilePath(std::function<PIString()> f) { f_new_path = std::move(f); }
|
||||
|
||||
//! \~english Writes one record with explicit ID and payload.
|
||||
//! \~russian Записывает одну запись с явным идентификатором и данными.
|
||||
|
||||
@@ -177,7 +177,7 @@ void PIIODevice::setReopenTimeout(PISystemTime timeout) {
|
||||
//! после каждого успешного потокового чтения. Метод должен быть
|
||||
//! в формате "bool func(void * data, uchar * readed, int size)"
|
||||
void PIIODevice::setThreadedReadSlot(ReadRetFunc func) {
|
||||
func_read = func;
|
||||
func_read = std::move(func);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -103,15 +103,15 @@ public:
|
||||
|
||||
//! \~english Sets custom header validation callback.
|
||||
//! \~russian Устанавливает пользовательский callback проверки заголовка.
|
||||
void setHeaderCheckSlot(PacketExtractorHeaderFunc f) { func_header = f; }
|
||||
void setHeaderCheckSlot(PacketExtractorHeaderFunc f) { func_header = std::move(f); }
|
||||
|
||||
//! \~english Sets custom payload validation callback.
|
||||
//! \~russian Устанавливает пользовательский callback проверки полезной нагрузки.
|
||||
void setPayloadCheckSlot(PacketExtractorPayloadFunc f) { func_payload = f; }
|
||||
void setPayloadCheckSlot(PacketExtractorPayloadFunc f) { func_payload = std::move(f); }
|
||||
|
||||
//! \~english Sets custom footer validation callback.
|
||||
//! \~russian Устанавливает пользовательский callback проверки окончания пакета.
|
||||
void setFooterCheckSlot(PacketExtractorFooterFunc f) { func_footer = f; }
|
||||
void setFooterCheckSlot(PacketExtractorFooterFunc f) { func_footer = std::move(f); }
|
||||
|
||||
|
||||
//! \~english Switches packet extraction to mode "mode".
|
||||
|
||||
@@ -62,7 +62,7 @@ public:
|
||||
//! \~russian Связывает ключ "key" с callback-функцией "func" без аргументов полезной нагрузки.
|
||||
void assign(Key key, std::function<void()> func) {
|
||||
auto lf = [func](PIByteArray) { func(); };
|
||||
functions[key] << lf;
|
||||
functions[key] << std::move(lf);
|
||||
}
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ public:
|
||||
func(v);
|
||||
}
|
||||
};
|
||||
functions[key] << lf;
|
||||
functions[key] << std::move(lf);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -175,7 +175,7 @@ struct PIP_EXPORT Function {
|
||||
identifier = name;
|
||||
arguments = args;
|
||||
type = bfCustom;
|
||||
handler = h;
|
||||
handler = std::move(h);
|
||||
}
|
||||
|
||||
PIString identifier;
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
//! \~russian Математический вектор
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Math vector
|
||||
Math vector
|
||||
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
@@ -805,11 +805,12 @@ public:
|
||||
|
||||
//! \~english Applies \a f to every coordinate without modifying the vector.
|
||||
//! \~russian Применяет \a f к каждой координате без изменения вектора.
|
||||
void forEach(std::function<void(const Type &)> f) const { c.forEach(f); }
|
||||
void forEach(std::function<void(const Type &)> f) const { c.forEach(std::move(f)); }
|
||||
|
||||
//! \~english Applies \a f to every coordinate and returns this vector.
|
||||
//! \~russian Применяет \a f к каждой координате и возвращает этот вектор.
|
||||
_CVector & forEach(std::function<void(Type &)> f) {
|
||||
c.forEach(f);
|
||||
c.forEach(std::move(f));
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ public:
|
||||
|
||||
//! \~english Sets a callback invoked when the machine finishes.
|
||||
//! \~russian Задает callback-функцию, вызываемую при завершении машины.
|
||||
void setOnFinish(std::function<void()> f) { on_finish = f; }
|
||||
void setOnFinish(std::function<void()> f) { on_finish = std::move(f); }
|
||||
|
||||
|
||||
//! \~english Posts an event to active states and triggers the first matching transition.
|
||||
|
||||
@@ -51,7 +51,7 @@ public:
|
||||
template<typename Ret, typename... Args>
|
||||
FunctionBase * makeFunction(std::function<Ret(Args...)> func) {
|
||||
auto * ret = new Function<Args...>();
|
||||
ret->func = func;
|
||||
ret->func = std::move(func);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
//! \~russian Объявляет состояния, используемые в PIStateMachine
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
State machine node
|
||||
Ivan Pelipenko peri4ko@yandex.ru
|
||||
State machine node
|
||||
Ivan Pelipenko peri4ko@yandex.ru
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
@@ -196,10 +196,10 @@ class PIP_EXPORT PIStateLambda: public PIStateBase {
|
||||
public:
|
||||
//! \~english Creates a state backed by enter and exit callbacks.
|
||||
//! \~russian Создает состояние с callback-функциями входа и выхода.
|
||||
PIStateLambda(std::function<void()> on_enter, std::function<void()> on_exit = nullptr, const PIString & n = {}): PIStateBase(n) {
|
||||
enter = on_enter;
|
||||
exit = on_exit;
|
||||
}
|
||||
PIStateLambda(std::function<void()> on_enter, std::function<void()> on_exit = nullptr, const PIString & n = {})
|
||||
: PIStateBase(n)
|
||||
, enter(std::move(on_enter))
|
||||
, exit(std::move(on_exit)) {}
|
||||
|
||||
|
||||
//! \~english Executes the enter callback.
|
||||
@@ -228,9 +228,8 @@ class PIP_EXPORT PIStateFinal: public PIStateBase {
|
||||
public:
|
||||
//! \~english Creates a final state with an optional callback executed on entry.
|
||||
//! \~russian Создает финальное состояние с необязательной callback-функцией, выполняемой при входе.
|
||||
PIStateFinal(std::function<void()> on_finish = nullptr, const PIString & n = {}): PIStateBase(n) {
|
||||
PIStateFinal(std::function<void()> on_finish = nullptr, const PIString & n = {}): PIStateBase(n), enter(std::move(on_finish)) {
|
||||
is_final = true;
|
||||
enter = on_finish;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ PITransitionBase::~PITransitionBase() {
|
||||
|
||||
|
||||
PITransitionBase * PITransitionBase::addAction(std::function<void()> a) {
|
||||
action = a;
|
||||
action = std::move(a);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@@ -68,7 +68,7 @@ public:
|
||||
|
||||
//! \~english Installs callback that receives grabbed signals.
|
||||
//! \~russian Устанавливает обратный вызов, получающий перехваченные сигналы.
|
||||
static void setSlot(SignalEvent slot) { ret_func = slot; }
|
||||
static void setSlot(SignalEvent slot) { ret_func = std::move(slot); }
|
||||
|
||||
//! \~english Redirects selected signals to the slot set by \a setSlot().
|
||||
//! \~russian Перенаправляет выбранные сигналы в обработчик, заданный через \a setSlot().
|
||||
|
||||
@@ -86,11 +86,9 @@ void PIConditionVariable::wait(PIMutex & lk) {
|
||||
}
|
||||
|
||||
|
||||
void PIConditionVariable::wait(PIMutex & lk, const std::function<bool()> & condition) {
|
||||
bool isCondition;
|
||||
void PIConditionVariable::wait(PIMutex & lk, std::function<bool()> condition) {
|
||||
while (true) {
|
||||
isCondition = condition();
|
||||
if (isCondition) break;
|
||||
if (condition()) break;
|
||||
#if defined(WINDOWS)
|
||||
SleepConditionVariableCS(&PRIVATE->nativeHandle, (PCRITICAL_SECTION)lk.handle(), INFINITE);
|
||||
#elif defined(FREERTOS)
|
||||
@@ -122,8 +120,7 @@ bool PIConditionVariable::waitFor(PIMutex & lk, PISystemTime timeout) {
|
||||
}
|
||||
|
||||
|
||||
bool PIConditionVariable::waitFor(PIMutex & lk, PISystemTime timeout, const std::function<bool()> & condition) {
|
||||
bool isCondition;
|
||||
bool PIConditionVariable::waitFor(PIMutex & lk, PISystemTime timeout, std::function<bool()> condition) {
|
||||
#if defined(WINDOWS) || defined(FREERTOS)
|
||||
PITimeMeasurer measurer;
|
||||
#else
|
||||
@@ -135,8 +132,7 @@ bool PIConditionVariable::waitFor(PIMutex & lk, PISystemTime timeout, const std:
|
||||
xEventGroupClearBits(PRIVATE->nativeHandle, 1);
|
||||
#endif
|
||||
while (true) {
|
||||
isCondition = condition();
|
||||
if (isCondition) break;
|
||||
if (condition()) break;
|
||||
bool isTimeout;
|
||||
#if defined(WINDOWS)
|
||||
isTimeout = SleepConditionVariableCS(&PRIVATE->nativeHandle,
|
||||
|
||||
@@ -106,7 +106,7 @@ public:
|
||||
//! \param condition вызываемый объект или функция, не принимающая аргументов и возвращающая значение, которое может быть оценено как
|
||||
//! bool. Вызывается повторно, пока не примет значение true
|
||||
//!
|
||||
virtual void wait(PIMutex & lk, const std::function<bool()> & condition);
|
||||
virtual void wait(PIMutex & lk, std::function<bool ()> condition);
|
||||
|
||||
|
||||
//! \~english Waits for at most \a timeout and returns \c true if awakened before it expires.
|
||||
@@ -167,7 +167,7 @@ public:
|
||||
//! bool. Вызывается повторно, пока не примет значение true
|
||||
//! \return false если достигнут таймаут, или true если условие пробуждения истинно
|
||||
//!
|
||||
virtual bool waitFor(PIMutex & lk, PISystemTime timeout, const std::function<bool()> & condition);
|
||||
virtual bool waitFor(PIMutex & lk, PISystemTime timeout, std::function<bool()> condition);
|
||||
|
||||
private:
|
||||
PRIVATE_DECLARATION(PIP_EXPORT)
|
||||
|
||||
@@ -540,7 +540,7 @@ PRIVATE_DEFINITION_END(PIThread)
|
||||
PIThread::PIThread(void * data, ThreadFunc func, bool startNow, PISystemTime loop_delay): PIObject() {
|
||||
PIINTROSPECTION_THREAD_NEW(this);
|
||||
data_ = data;
|
||||
ret_func = func;
|
||||
ret_func = std::move(func);
|
||||
terminating = running_ = lockRun = false;
|
||||
priority_ = piNormal;
|
||||
delay_ = loop_delay;
|
||||
@@ -609,13 +609,13 @@ bool PIThread::start(PISystemTime loop_delay) {
|
||||
|
||||
|
||||
bool PIThread::start(ThreadFunc func) {
|
||||
ret_func = func;
|
||||
ret_func = std::move(func);
|
||||
return start();
|
||||
}
|
||||
|
||||
|
||||
bool PIThread::start(ThreadFunc func, PISystemTime loop_delay) {
|
||||
ret_func = func;
|
||||
ret_func = std::move(func);
|
||||
delay_ = loop_delay;
|
||||
return start();
|
||||
}
|
||||
@@ -641,7 +641,7 @@ bool PIThread::startOnce() {
|
||||
|
||||
|
||||
bool PIThread::startOnce(ThreadFunc func) {
|
||||
ret_func = func;
|
||||
ret_func = std::move(func);
|
||||
return startOnce();
|
||||
}
|
||||
|
||||
@@ -738,12 +738,12 @@ bool PIThread::_startThread(void * func) {
|
||||
#ifdef FREERTOS
|
||||
|
||||
auto name_ba = createThreadName();
|
||||
if (xTaskCreate((__THREAD_FUNC_RET__ (*)(void *))func,
|
||||
(const char *)name_ba.data(), // A name just for humans
|
||||
128, // This stack size can be checked & adjusted by reading the Stack Highwater
|
||||
this,
|
||||
priority_,
|
||||
&PRIVATE->thread) == pdPASS) {
|
||||
if (xTaskCreate((__THREAD_FUNC_RET__(*)(void *))func,
|
||||
(const char *)name_ba.data(), // A name just for humans
|
||||
128, // This stack size can be checked & adjusted by reading the Stack Highwater
|
||||
this,
|
||||
priority_,
|
||||
&PRIVATE->thread) == pdPASS) {
|
||||
tid_ = (llong)PRIVATE->thread;
|
||||
return true;
|
||||
}
|
||||
@@ -752,7 +752,7 @@ bool PIThread::_startThread(void * func) {
|
||||
|
||||
if (PRIVATE->thread) CloseHandle(PRIVATE->thread);
|
||||
# ifdef CC_GCC
|
||||
PRIVATE->thread = (void *)_beginthreadex(0, 0, (__THREAD_FUNC_RET__ (*)(void *))func, this, CREATE_SUSPENDED, 0);
|
||||
PRIVATE->thread = (void *)_beginthreadex(0, 0, (__THREAD_FUNC_RET__(*)(void *))func, this, CREATE_SUSPENDED, 0);
|
||||
# else
|
||||
PRIVATE->thread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)func, this, CREATE_SUSPENDED, 0);
|
||||
# endif
|
||||
@@ -766,7 +766,7 @@ bool PIThread::_startThread(void * func) {
|
||||
pthread_attr_t attr;
|
||||
pthread_attr_init(&attr);
|
||||
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
|
||||
int ret = pthread_create(&PRIVATE->thread, &attr, (__THREAD_FUNC_RET__ (*)(void *))func, this);
|
||||
int ret = pthread_create(&PRIVATE->thread, &attr, (__THREAD_FUNC_RET__(*)(void *))func, this);
|
||||
pthread_attr_destroy(&attr);
|
||||
// PICout(PICoutManipulators::DefaultControls) << "pthread_create" << PRIVATE->thread;
|
||||
// piCout << "started" << PRIVATE->thread;
|
||||
@@ -884,8 +884,8 @@ void PIThread::_runThread() {
|
||||
PIINTROSPECTION_THREAD_RUN(this);
|
||||
// PICout(PICoutManipulators::DefaultControls) << "thread" << this << "lock" << "...";
|
||||
if (lockRun) thread_mutex.lock();
|
||||
// PICout(PICoutManipulators::DefaultControls) << "thread" << this << "lock" << "ok";
|
||||
// PICout(PICoutManipulators::DefaultControls) << "thread" << this << "run" << "...";
|
||||
// PICout(PICoutManipulators::DefaultControls) << "thread" << this << "lock" << "ok";
|
||||
// PICout(PICoutManipulators::DefaultControls) << "thread" << this << "run" << "...";
|
||||
#ifdef PIP_INTROSPECTION
|
||||
PITimeMeasurer _tm;
|
||||
#endif
|
||||
@@ -1042,7 +1042,7 @@ void PIThread::runOnce(PIObject * object, const char * handler, const PIString &
|
||||
void PIThread::runOnce(std::function<void()> func, const PIString & name) {
|
||||
PIThread * t = new PIThread();
|
||||
t->setName(name);
|
||||
t->setSlot(func);
|
||||
t->setSlot(std::move(func));
|
||||
#ifndef MICRO_PIP
|
||||
__PIThreadCollection::instance()->startedAuto(t);
|
||||
CONNECT0(void, t, stopped, __PIThreadCollection::instance(), stoppedAuto);
|
||||
|
||||
@@ -68,8 +68,8 @@ PIThreadPoolExecutor::~PIThreadPoolExecutor() {
|
||||
}
|
||||
|
||||
|
||||
void PIThreadPoolExecutor::execute(const std::function<void()> & runnable) {
|
||||
if (!isShutdown_) taskQueue.offer(runnable);
|
||||
void PIThreadPoolExecutor::execute(std::function<void()> runnable) {
|
||||
if (!isShutdown_) taskQueue.offer(std::move(runnable));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@ public:
|
||||
//! \~russian
|
||||
//! Это вызов по принципу best-effort без ожидания результата и без сообщения о том, была ли задача принята.
|
||||
//! \После запроса на завершение новые задачи игнорируются.
|
||||
void execute(const std::function<void()> & runnable);
|
||||
void execute(std::function<void()> runnable);
|
||||
|
||||
//! \~english Requests immediate shutdown and stops worker threads without waiting for queued tasks to finish.
|
||||
//! \~russian Запрашивает немедленное завершение и останавливает рабочие потоки без ожидания завершения задач в очереди.
|
||||
|
||||
@@ -136,7 +136,7 @@ PIThreadPoolLoop::~PIThreadPoolLoop() {
|
||||
|
||||
|
||||
void PIThreadPoolLoop::setFunction(std::function<void(int)> f) {
|
||||
func = f;
|
||||
func = std::move(f);
|
||||
}
|
||||
|
||||
|
||||
@@ -163,6 +163,6 @@ void PIThreadPoolLoop::exec(int index_start, int index_count) {
|
||||
|
||||
|
||||
void PIThreadPoolLoop::exec(int index_start, int index_count, std::function<void(int)> f) {
|
||||
setFunction(f);
|
||||
setFunction(std::move(f));
|
||||
exec(index_start, index_count);
|
||||
}
|
||||
|
||||
@@ -122,13 +122,13 @@ PITimer::PITimer(): PIObject() {
|
||||
|
||||
PITimer::PITimer(std::function<void(int)> func) {
|
||||
initFirst();
|
||||
ret_func = func;
|
||||
ret_func_delim = std::move(func);
|
||||
}
|
||||
|
||||
|
||||
PITimer::PITimer(std::function<void()> func) {
|
||||
initFirst();
|
||||
ret_func = [func](int) { func(); };
|
||||
ret_func = std::move(func);
|
||||
}
|
||||
|
||||
|
||||
@@ -224,7 +224,8 @@ void PITimer::adjustTimes() {
|
||||
void PITimer::execTick() {
|
||||
if (!isRunning()) return;
|
||||
if (lockRun) lock();
|
||||
if (ret_func) ret_func(1);
|
||||
if (ret_func) ret_func();
|
||||
if (ret_func_delim) ret_func_delim(1);
|
||||
tick(1);
|
||||
tickEvent(1);
|
||||
if (callEvents) maybeCallQueuedEvents();
|
||||
@@ -233,8 +234,8 @@ void PITimer::execTick() {
|
||||
i.tick = 0;
|
||||
if (i.func)
|
||||
i.func(i.delim);
|
||||
else if (ret_func)
|
||||
ret_func(i.delim);
|
||||
else if (ret_func_delim)
|
||||
ret_func_delim(i.delim);
|
||||
tick(i.delim);
|
||||
tickEvent(i.delim);
|
||||
}
|
||||
@@ -262,7 +263,7 @@ bool PITimer::start(PISystemTime interval) {
|
||||
bool PITimer::start(PISystemTime interval, std::function<void()> func) {
|
||||
if (isRunning()) stopAndWait();
|
||||
setInterval(interval);
|
||||
setSlot(func);
|
||||
setSlot(std::move(func));
|
||||
return start();
|
||||
}
|
||||
|
||||
@@ -274,7 +275,7 @@ void PITimer::stopAndWait(PISystemTime timeout) {
|
||||
|
||||
|
||||
void PITimer::addDelimiter(int delim, std::function<void(int)> func) {
|
||||
delims << Delimiter(func, delim);
|
||||
delims << Delimiter(std::move(func), delim);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -127,12 +127,16 @@ public:
|
||||
//! \~english Sets a tick callback that ignores the delimiter value.
|
||||
//! \~russian Устанавливает обратный вызов тика, игнорирующий значение делителя.
|
||||
void setSlot(std::function<void()> func) {
|
||||
ret_func = [func](int) { func(); };
|
||||
ret_func_delim = nullptr;
|
||||
ret_func = std::move(func);
|
||||
}
|
||||
|
||||
//! \~english Sets a tick callback that receives the current delimiter value.
|
||||
//! \~russian Устанавливает обратный вызов тика, принимающий текущее значение делителя.
|
||||
void setSlot(std::function<void(int)> func) { ret_func = func; }
|
||||
void setSlot(std::function<void(int)> func) {
|
||||
ret_func = nullptr;
|
||||
ret_func_delim = std::move(func);
|
||||
}
|
||||
|
||||
//! \~english Enables locking of the internal mutex around tick processing.
|
||||
//! \~russian Включает блокировку внутреннего мьютекса вокруг обработки тиков.
|
||||
@@ -141,7 +145,8 @@ public:
|
||||
EVENT_HANDLER0(void, unlock) { mutex_.unlock(); }
|
||||
|
||||
//! \~english Returns whether the timer drains queued delivery for itself as performer on each main tick. By default \b true.
|
||||
//! \~russian Возвращает, должен ли таймер обрабатывать отложенную доставку для себя как исполнителя на каждом основном тике. По умолчанию \b true.
|
||||
//! \~russian Возвращает, должен ли таймер обрабатывать отложенную доставку для себя как исполнителя на каждом основном тике. По
|
||||
//! умолчанию \b true.
|
||||
bool isCallQueuedEvents() const { return callEvents; }
|
||||
|
||||
//! \~english Enables or disables queued-delivery draining through \a maybeCallQueuedEvents() on each main tick.
|
||||
@@ -221,7 +226,7 @@ public:
|
||||
protected:
|
||||
struct PIP_EXPORT Delimiter {
|
||||
Delimiter(std::function<void(int)> func_ = nullptr, int delim_ = 1) {
|
||||
func = func_;
|
||||
func = std::move(func_);
|
||||
delim = delim_;
|
||||
}
|
||||
std::function<void(int)> func;
|
||||
@@ -245,7 +250,8 @@ protected:
|
||||
PIMutex mutex_;
|
||||
PISystemTime m_interval, m_interval_x5;
|
||||
PISystemTime m_time_next;
|
||||
std::function<void(int)> ret_func = nullptr;
|
||||
std::function<void()> ret_func = nullptr;
|
||||
std::function<void(int)> ret_func_delim = nullptr;
|
||||
PIVector<Delimiter> delims;
|
||||
PIConditionVariable event;
|
||||
};
|
||||
|
||||
@@ -198,7 +198,7 @@ public:
|
||||
//! Метод возвращает **false** при любом условии для пустого массива.
|
||||
//! \~\details
|
||||
//! \~\sa \a every(), \a contains(), \a entries(), \a forEach()
|
||||
inline bool any(std::function<bool(uchar e)> test) const { return d.any(test); }
|
||||
inline bool any(std::function<bool(uchar e)> test) const { return d.any(std::move(test)); }
|
||||
|
||||
//! \~english Tests whether all elements in the array passes the test
|
||||
//! implemented by the provided function `test`.
|
||||
@@ -213,7 +213,7 @@ public:
|
||||
//! Метод возвращает **true** при любом условии для пустого массива.
|
||||
//! \~\details
|
||||
//! \~\sa \a any(), \a contains(), \a entries(), \a forEach()
|
||||
inline bool every(std::function<bool(uchar e)> test) const { return d.every(test); }
|
||||
inline bool every(std::function<bool(uchar e)> test) const { return d.every(std::move(test)); }
|
||||
|
||||
//! \~english Full access to element by `index`.
|
||||
//! \~russian Полный доступ к элементу по индексу `index`.
|
||||
@@ -340,7 +340,7 @@ public:
|
||||
//! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от начала к концу.
|
||||
//! Значение по умолчанию равно 0, что означает, что просматривается весь массив.
|
||||
//! \~\sa \a every(), \a any(), \a contains(), \a indexWhere()
|
||||
inline int entries(std::function<bool(uchar e)> test, ssize_t start = 0) const { return d.entries(test, start); }
|
||||
inline int entries(std::function<bool(uchar e)> test, ssize_t start = 0) const { return d.entries(std::move(test), start); }
|
||||
|
||||
bool startsWith(const PIByteArray & o) const;
|
||||
|
||||
@@ -405,7 +405,9 @@ public:
|
||||
//! piCout << v.indexWhere([](const uchar & s){return s > 10;}); // -1
|
||||
//! \endcode
|
||||
//! \~\sa \a indexOf(), \a lastIndexOf(), \a lastIndexWhere(), \a contains()
|
||||
inline ssize_t indexWhere(std::function<bool(const uchar & e)> test, ssize_t start = 0) const { return d.indexWhere(test, start); }
|
||||
inline ssize_t indexWhere(std::function<bool(const uchar & e)> test, ssize_t start = 0) const {
|
||||
return d.indexWhere(std::move(test), start);
|
||||
}
|
||||
|
||||
//! \~english Returns the last index at which a given element `e`
|
||||
//! can be found in the array, or `-1` if it is not present.
|
||||
@@ -469,7 +471,7 @@ public:
|
||||
//! и означает, что просматривается весь массив.
|
||||
//! \~\sa \a indexOf(), \a lastIndexOf(), \a indexWhere(), \a contains()
|
||||
inline ssize_t lastIndexWhere(std::function<bool(const uchar & e)> test, ssize_t start = -1) const {
|
||||
return d.lastIndexWhere(test, start);
|
||||
return d.lastIndexWhere(std::move(test), start);
|
||||
}
|
||||
|
||||
//! \~english Pointer to array
|
||||
@@ -525,7 +527,7 @@ public:
|
||||
//! \~\details
|
||||
//! \~\sa \a resize()
|
||||
inline PIByteArray & fill(std::function<uchar(size_t i)> f) {
|
||||
d.fill(f);
|
||||
d.fill(std::move(f));
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -570,7 +572,7 @@ public:
|
||||
//! лишние элементы удаляются с конца массива.
|
||||
//! \~\sa \a size(), \a clear()
|
||||
inline PIByteArray & resize(size_t new_size, std::function<uchar(size_t i)> f) {
|
||||
d.resize(new_size, f);
|
||||
d.resize(new_size, std::move(f));
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -738,7 +740,7 @@ public:
|
||||
//! \~\details
|
||||
//! \~\sa \a remove(), \a removeOne(), \a removeWhere()
|
||||
inline PIByteArray & removeWhere(std::function<bool(uchar e)> test) {
|
||||
d.removeWhere(test);
|
||||
d.removeWhere(std::move(test));
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -950,7 +952,7 @@ public:
|
||||
//! piCout << v2; // {3, 5, 7}
|
||||
//! \endcode
|
||||
//! \~\sa \a map(), \a any(), \a every()
|
||||
inline PIByteArray filter(std::function<bool(const uchar & e)> test) const { return PIByteArray(d.filter(test)); }
|
||||
inline PIByteArray filter(std::function<bool(const uchar & e)> test) const { return PIByteArray(d.filter(std::move(test))); }
|
||||
|
||||
//! \~english Execute function `void f(const uchar & e)` for every element in array.
|
||||
//! \~russian Выполняет функцию `void f(const uchar & e)` для каждого элемента массива.
|
||||
@@ -966,7 +968,7 @@ public:
|
||||
//! piCout << s; // 15
|
||||
//! \endcode
|
||||
//! \~\sa \a filter(), \a map(), \a reduce(), \a any(), \a every()
|
||||
inline void forEach(std::function<void(const uchar & e)> f) const { d.forEach(f); }
|
||||
inline void forEach(std::function<void(const uchar & e)> f) const { d.forEach(std::move(f)); }
|
||||
|
||||
//! \~english Execute function `void f(uchar & e)` for every element in array.
|
||||
//! \~russian Выполняет функцию `void f(uchar & e)` для каждого элемента массива.
|
||||
@@ -982,7 +984,7 @@ public:
|
||||
//! \endcode
|
||||
//! \~\sa \a filter(), \a map(), \a reduce(), \a any(), \a every()
|
||||
inline PIByteArray & forEach(std::function<void(uchar & e)> f) {
|
||||
d.forEach(f);
|
||||
d.forEach(std::move(f));
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -1005,7 +1007,7 @@ public:
|
||||
//! \~\sa \a forEach(), \a reduce()
|
||||
template<typename ST>
|
||||
inline PIDeque<ST> map(std::function<ST(const uchar & e)> f) const {
|
||||
return d.map<ST>(f);
|
||||
return d.map<ST>(std::move(f));
|
||||
}
|
||||
|
||||
//! \~english Applies the function `ST f(const uchar & e, const ST & acc)`
|
||||
@@ -1051,7 +1053,7 @@ public:
|
||||
//! \~\sa \a forEach(), \a map()
|
||||
template<typename ST>
|
||||
inline ST reduce(std::function<ST(const uchar & e, const ST & acc)> f, const ST & initial = ST()) const {
|
||||
return d.reduce<ST>(f, initial);
|
||||
return d.reduce<ST>(std::move(f), initial);
|
||||
}
|
||||
|
||||
//! \~english Convert data to Base 64 and return this byte array
|
||||
|
||||
@@ -262,7 +262,7 @@ PIValueTree & PIValueTree::remove(const PIString & name) {
|
||||
|
||||
|
||||
void PIValueTree::forEachRecursive(std::function<void(const PIValueTree &, const PIString &)> func) {
|
||||
forEachRecursiveInternal(func);
|
||||
forEachRecursiveInternal(std::move(func));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ FetchContent_Declare(
|
||||
)
|
||||
# For Windows: Prevent overriding the parent project's compiler/linker settings
|
||||
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
|
||||
set(BUILD_GMOCK OFF CACHE BOOL "Build Google Mock" FORCE)
|
||||
FetchContent_MakeAvailable(googletest)
|
||||
|
||||
enable_testing()
|
||||
@@ -24,13 +25,14 @@ macro(pip_test NAME)
|
||||
file(GLOB _HDRS "${NAME}/*.h")
|
||||
set(_target pip_${NAME}_test)
|
||||
add_executable(${_target} ${_CPPS} ${_HDRS})
|
||||
target_link_libraries(${_target} pip ${ARGN} gtest_main)
|
||||
gtest_discover_tests(${_target})
|
||||
target_link_libraries(${_target} pip ${ARGN} gtest_main)
|
||||
if (TESTS_RUN)
|
||||
gtest_discover_tests(${_target})
|
||||
endif()
|
||||
list(APPEND PIP_TESTS_LIST "${NAME}")
|
||||
set(PIP_TESTS_LIST ${PIP_TESTS_LIST} PARENT_SCOPE)
|
||||
endmacro()
|
||||
|
||||
#pip_test(concurrent)
|
||||
pip_test(math)
|
||||
pip_test(core)
|
||||
pip_test(piobject)
|
||||
|
||||
@@ -33,7 +33,7 @@ TEST(ClientServer, OneClient) {
|
||||
auto const loop_timeout = 1000_ms;
|
||||
auto s = createServer<false, true>();
|
||||
piMinSleep();
|
||||
auto c = createAndConnectClient<TestClient<false, false>>();
|
||||
auto c = createAndConnectClient<TestClient<false, false>>();
|
||||
|
||||
waitLoop([s]() { return s->clientsCount() > 0; }, loop_timeout);
|
||||
EXPECT_EQ(1, s->clientsCount());
|
||||
@@ -103,7 +103,7 @@ int getClientsPings(const PIVector<ClientSendThread *> & clients) {
|
||||
|
||||
|
||||
TEST(ClientServer, ManyClients) {
|
||||
auto const loop_timeout = 100_ms;
|
||||
auto const loop_timeout = 1_s;
|
||||
constexpr int clients_count = 20;
|
||||
PIVector<ClientSendThread *> clients;
|
||||
auto s = createServer<false, false, 100_KiB>();
|
||||
@@ -139,8 +139,9 @@ TEST(ClientServer, ManyClients) {
|
||||
for (const auto c: clients) {
|
||||
c->startSend();
|
||||
}
|
||||
loop_timeout.sleep();
|
||||
waitLoop([&clients]() { return getClientsPings(clients) > clients_count * 2; }, loop_timeout);
|
||||
EXPECT_TRUE(getClientsPings(clients) > clients_count * 2);
|
||||
waitLoop([s]() { return getServerPongs(s) > clients_count * 2; }, loop_timeout);
|
||||
EXPECT_TRUE(getServerPongs(s) > clients_count * 2);
|
||||
piDeleteAllAndClear(clients);
|
||||
waitLoop([s]() { return s->clientsCount() == 0; }, loop_timeout);
|
||||
@@ -149,7 +150,7 @@ TEST(ClientServer, ManyClients) {
|
||||
}
|
||||
|
||||
TEST(ClientServer, DynamicClients) {
|
||||
auto const loop_timeout = 10_ms;
|
||||
auto const loop_timeout = 3_s;
|
||||
constexpr int clients_count = 20;
|
||||
PIVector<ClientSendThread *> clients;
|
||||
PIMutex clients_mutex;
|
||||
@@ -199,15 +200,14 @@ TEST(ClientServer, DynamicClients) {
|
||||
},
|
||||
130_Hz);
|
||||
|
||||
(loop_timeout * clients_count).sleep();
|
||||
|
||||
waitLoop([s]() { return s->clientsCount() >= 10; }, loop_timeout);
|
||||
EXPECT_GE(s->clientsCount(), 10);
|
||||
|
||||
deleteThread.stopAndWait();
|
||||
spawnThread.stopAndWait();
|
||||
|
||||
piDeleteAllAndClear(clients);
|
||||
waitLoop([s]() { return s->clientsCount() == 0; }, loop_timeout * clients_count);
|
||||
waitLoop([s]() { return s->clientsCount() == 0; }, loop_timeout);
|
||||
EXPECT_EQ(0, s->clientsCount());
|
||||
|
||||
delete s;
|
||||
|
||||
@@ -1,262 +0,0 @@
|
||||
#include "piblockingqueue.h"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
class MockConditionVar: public PIConditionVariable {
|
||||
public:
|
||||
bool isWaitCalled = false;
|
||||
bool isWaitForCalled = false;
|
||||
bool isTrueCondition = false;
|
||||
int timeout = -1;
|
||||
|
||||
void wait(PIMutex & lk) override { isWaitCalled = true; }
|
||||
|
||||
void wait(PIMutex & lk, const std::function<bool()> & condition) override {
|
||||
isWaitCalled = true;
|
||||
isTrueCondition = condition();
|
||||
}
|
||||
|
||||
bool waitFor(PIMutex & lk, int timeoutMs) override {
|
||||
isWaitForCalled = true;
|
||||
timeout = timeoutMs;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool waitFor(PIMutex & lk, int timeoutMs, const std::function<bool()> & condition) override {
|
||||
isWaitForCalled = true;
|
||||
isTrueCondition = condition();
|
||||
timeout = timeoutMs;
|
||||
return isTrueCondition;
|
||||
}
|
||||
};
|
||||
|
||||
TEST(BlockingDequeueUnitTest, put_is_block_when_capacity_reach) {
|
||||
size_t capacity = 0;
|
||||
auto conditionVarAdd = new MockConditionVar();
|
||||
auto conditionVarRem = new MockConditionVar();
|
||||
PIBlockingQueue<int> dequeue(capacity, conditionVarAdd, conditionVarRem);
|
||||
dequeue.put(11);
|
||||
ASSERT_TRUE(conditionVarRem->isWaitCalled);
|
||||
ASSERT_FALSE(conditionVarRem->isTrueCondition);
|
||||
}
|
||||
|
||||
TEST(BlockingDequeueUnitTest, offer_timedout_is_false_when_capacity_reach) {
|
||||
size_t capacity = 0;
|
||||
int timeout = 11;
|
||||
auto conditionVarAdd = new MockConditionVar();
|
||||
auto conditionVarRem = new MockConditionVar();
|
||||
PIBlockingQueue<int> dequeue(capacity, conditionVarAdd, conditionVarRem);
|
||||
ASSERT_FALSE(dequeue.offer(11, timeout));
|
||||
}
|
||||
|
||||
TEST(BlockingDequeueUnitTest, offer_timedout_is_block_when_capacity_reach) {
|
||||
size_t capacity = 0;
|
||||
int timeout = 11;
|
||||
auto conditionVarAdd = new MockConditionVar();
|
||||
auto conditionVarRem = new MockConditionVar();
|
||||
PIBlockingQueue<int> dequeue(capacity, conditionVarAdd, conditionVarRem);
|
||||
dequeue.offer(11, timeout);
|
||||
EXPECT_TRUE(conditionVarRem->isWaitForCalled);
|
||||
EXPECT_EQ(timeout, conditionVarRem->timeout);
|
||||
ASSERT_FALSE(conditionVarRem->isTrueCondition);
|
||||
}
|
||||
|
||||
TEST(BlockingDequeueUnitTest, offer_is_true_before_capacity_reach) {
|
||||
size_t capacity = 1;
|
||||
PIBlockingQueue<int> dequeue(capacity);
|
||||
ASSERT_TRUE(dequeue.offer(10));
|
||||
}
|
||||
|
||||
TEST(BlockingDequeueUnitTest, offer_is_false_when_capacity_reach) {
|
||||
size_t capacity = 1;
|
||||
PIBlockingQueue<int> dequeue(capacity);
|
||||
dequeue.offer(11);
|
||||
ASSERT_FALSE(dequeue.offer(10));
|
||||
}
|
||||
|
||||
// TODO change take_is_block_when_empty to prevent segfault
|
||||
TEST(DISABLED_BlockingDequeueUnitTest, take_is_block_when_empty) {
|
||||
size_t capacity = 1;
|
||||
auto conditionVar = new MockConditionVar();
|
||||
PIBlockingQueue<int> dequeue(capacity, conditionVar);
|
||||
// May cause segfault because take front of empty queue
|
||||
dequeue.take();
|
||||
EXPECT_TRUE(conditionVar->isWaitCalled);
|
||||
ASSERT_FALSE(conditionVar->isTrueCondition);
|
||||
}
|
||||
|
||||
TEST(BlockingDequeueUnitTest, take_is_not_block_when_not_empty) {
|
||||
size_t capacity = 1;
|
||||
auto conditionVar = new MockConditionVar();
|
||||
PIBlockingQueue<int> dequeue(capacity, conditionVar);
|
||||
dequeue.offer(111);
|
||||
dequeue.take();
|
||||
|
||||
EXPECT_TRUE(conditionVar->isWaitCalled);
|
||||
ASSERT_TRUE(conditionVar->isTrueCondition);
|
||||
}
|
||||
|
||||
TEST(BlockingDequeueUnitTest, take_is_value_eq_to_offer_value) {
|
||||
size_t capacity = 1;
|
||||
auto conditionVar = new MockConditionVar();
|
||||
PIBlockingQueue<int> dequeue(capacity, conditionVar);
|
||||
|
||||
dequeue.offer(111);
|
||||
ASSERT_EQ(dequeue.take(), 111);
|
||||
}
|
||||
|
||||
TEST(BlockingDequeueUnitTest, take_is_last) {
|
||||
size_t capacity = 10;
|
||||
auto conditionVar = new MockConditionVar();
|
||||
PIBlockingQueue<int> dequeue(capacity, conditionVar);
|
||||
EXPECT_TRUE(dequeue.offer(111));
|
||||
EXPECT_TRUE(dequeue.offer(222));
|
||||
ASSERT_EQ(dequeue.take(), 111);
|
||||
ASSERT_EQ(dequeue.take(), 222);
|
||||
}
|
||||
|
||||
TEST(BlockingDequeueUnitTest, poll_is_not_block_when_empty) {
|
||||
size_t capacity = 1;
|
||||
bool isOk;
|
||||
auto conditionVar = new MockConditionVar();
|
||||
PIBlockingQueue<int> dequeue(capacity, conditionVar);
|
||||
dequeue.poll(0, 111, &isOk);
|
||||
EXPECT_FALSE(conditionVar->isWaitForCalled);
|
||||
}
|
||||
|
||||
TEST(BlockingDequeueUnitTest, poll_is_default_value_when_empty) {
|
||||
size_t capacity = 1;
|
||||
bool isOk;
|
||||
auto conditionVar = new MockConditionVar();
|
||||
PIBlockingQueue<int> dequeue(capacity, conditionVar);
|
||||
ASSERT_EQ(dequeue.poll(0, 111, &isOk), 111);
|
||||
}
|
||||
|
||||
TEST(BlockingDequeueUnitTest, poll_is_offer_value_when_not_empty) {
|
||||
size_t capacity = 1;
|
||||
bool isOk;
|
||||
auto conditionVar = new MockConditionVar();
|
||||
PIBlockingQueue<int> dequeue(capacity, conditionVar);
|
||||
dequeue.offer(111);
|
||||
ASSERT_EQ(dequeue.poll(0, -1, &isOk), 111);
|
||||
}
|
||||
|
||||
TEST(BlockingDequeueUnitTest, poll_timeouted_is_block_when_empty) {
|
||||
size_t capacity = 1;
|
||||
int timeout = 11;
|
||||
auto conditionVar = new MockConditionVar();
|
||||
PIBlockingQueue<int> dequeue(capacity, conditionVar);
|
||||
dequeue.poll(timeout, 111);
|
||||
EXPECT_TRUE(conditionVar->isWaitForCalled);
|
||||
EXPECT_EQ(timeout, conditionVar->timeout);
|
||||
ASSERT_FALSE(conditionVar->isTrueCondition);
|
||||
}
|
||||
|
||||
TEST(BlockingDequeueUnitTest, poll_timeouted_is_default_value_when_empty) {
|
||||
size_t capacity = 1;
|
||||
int timeout = 11;
|
||||
auto conditionVar = new MockConditionVar();
|
||||
PIBlockingQueue<int> dequeue(capacity, conditionVar);
|
||||
ASSERT_EQ(dequeue.poll(timeout, 111), 111);
|
||||
}
|
||||
|
||||
TEST(BlockingDequeueUnitTest, poll_timeouted_is_not_block_when_not_empty) {
|
||||
size_t capacity = 1;
|
||||
int timeout = 11;
|
||||
auto conditionVar = new MockConditionVar();
|
||||
PIBlockingQueue<int> dequeue(capacity, conditionVar);
|
||||
dequeue.offer(111);
|
||||
dequeue.poll(timeout, -1);
|
||||
|
||||
EXPECT_TRUE(conditionVar->isWaitForCalled);
|
||||
ASSERT_TRUE(conditionVar->isTrueCondition);
|
||||
}
|
||||
|
||||
TEST(BlockingDequeueUnitTest, poll_timeouted_is_offer_value_when_not_empty) {
|
||||
size_t capacity = 1;
|
||||
int timeout = 11;
|
||||
auto conditionVar = new MockConditionVar();
|
||||
PIBlockingQueue<int> dequeue(capacity, conditionVar);
|
||||
dequeue.offer(111);
|
||||
ASSERT_EQ(dequeue.poll(timeout, -1), 111);
|
||||
}
|
||||
|
||||
TEST(BlockingDequeueUnitTest, poll_timeouted_is_last) {
|
||||
size_t capacity = 10;
|
||||
auto conditionVar = new MockConditionVar();
|
||||
PIBlockingQueue<int> dequeue(capacity, conditionVar);
|
||||
dequeue.offer(111);
|
||||
dequeue.offer(222);
|
||||
ASSERT_EQ(dequeue.poll(10, -1), 111);
|
||||
ASSERT_EQ(dequeue.poll(10, -1), 222);
|
||||
}
|
||||
|
||||
TEST(BlockingDequeueUnitTest, capacity_is_eq_constructor_capacity) {
|
||||
size_t capacity = 10;
|
||||
PIBlockingQueue<int> dequeue(capacity);
|
||||
ASSERT_EQ(dequeue.capacity(), capacity);
|
||||
}
|
||||
|
||||
TEST(BlockingDequeueUnitTest, remainingCapacity_is_dif_of_capacity_and_size) {
|
||||
size_t capacity = 2;
|
||||
PIBlockingQueue<int> dequeue(capacity);
|
||||
ASSERT_EQ(dequeue.remainingCapacity(), capacity);
|
||||
dequeue.offer(111);
|
||||
ASSERT_EQ(dequeue.remainingCapacity(), capacity - 1);
|
||||
}
|
||||
|
||||
TEST(BlockingDequeueUnitTest, remainingCapacity_is_zero_when_capacity_reach) {
|
||||
size_t capacity = 1;
|
||||
PIBlockingQueue<int> dequeue(capacity);
|
||||
dequeue.offer(111);
|
||||
dequeue.offer(111);
|
||||
ASSERT_EQ(dequeue.remainingCapacity(), 0);
|
||||
}
|
||||
|
||||
TEST(BlockingDequeueUnitTest, size_is_eq_to_num_of_elements) {
|
||||
size_t capacity = 1;
|
||||
PIBlockingQueue<int> dequeue(capacity);
|
||||
ASSERT_EQ(dequeue.size(), 0);
|
||||
dequeue.offer(111);
|
||||
ASSERT_EQ(dequeue.size(), 1);
|
||||
}
|
||||
|
||||
TEST(BlockingDequeueUnitTest, size_is_eq_to_capacity_when_capacity_reach) {
|
||||
size_t capacity = 1;
|
||||
PIBlockingQueue<int> dequeue(capacity);
|
||||
dequeue.offer(111);
|
||||
dequeue.offer(111);
|
||||
ASSERT_EQ(dequeue.size(), capacity);
|
||||
}
|
||||
|
||||
TEST(BlockingDequeueUnitTest, drainTo_is_elements_moved) {
|
||||
size_t capacity = 10;
|
||||
PIDeque<int> refDeque;
|
||||
for (size_t i = 0; i < capacity / 2; ++i)
|
||||
refDeque.push_back(i * 10);
|
||||
PIBlockingQueue<int> blockingDequeue(refDeque);
|
||||
PIDeque<int> deque;
|
||||
blockingDequeue.drainTo(deque);
|
||||
ASSERT_EQ(blockingDequeue.size(), 0);
|
||||
ASSERT_TRUE(deque == refDeque);
|
||||
}
|
||||
|
||||
TEST(BlockingDequeueUnitTest, drainTo_is_ret_eq_to_size_when_all_moved) {
|
||||
size_t capacity = 10;
|
||||
PIDeque<int> refDeque;
|
||||
for (size_t i = 0; i < capacity / 2; ++i)
|
||||
refDeque.push_back(i * 10);
|
||||
PIBlockingQueue<int> blockingDequeue(refDeque);
|
||||
PIDeque<int> deque;
|
||||
ASSERT_EQ(blockingDequeue.drainTo(deque), refDeque.size());
|
||||
}
|
||||
|
||||
TEST(BlockingDequeueUnitTest, drainTo_is_ret_eq_to_maxCount) {
|
||||
size_t capacity = 10;
|
||||
PIDeque<int> refDeque;
|
||||
for (size_t i = 0; i < capacity / 2; ++i)
|
||||
refDeque.push_back(i * 10);
|
||||
PIBlockingQueue<int> blockingDequeue(refDeque);
|
||||
PIDeque<int> deque;
|
||||
ASSERT_EQ(blockingDequeue.drainTo(deque, refDeque.size() - 1), refDeque.size() - 1);
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
#include "piconditionvar.h"
|
||||
#include "pithread.h"
|
||||
#include "testutil.h"
|
||||
|
||||
#include "gmock/gmock.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
class ConditionLock
|
||||
: public ::testing::Test
|
||||
, public TestUtil {
|
||||
public:
|
||||
PIMutex * m = new PIMutex();
|
||||
bool isProtect;
|
||||
bool isReleased;
|
||||
};
|
||||
|
||||
|
||||
TEST_F(ConditionLock, DISABLED_lock_is_protect) {
|
||||
m->lock();
|
||||
isProtect = true;
|
||||
createThread([&]() {
|
||||
m->lock();
|
||||
isProtect = false;
|
||||
});
|
||||
EXPECT_FALSE(thread->waitForFinish(WAIT_THREAD_TIME_MS));
|
||||
ASSERT_TRUE(isProtect);
|
||||
}
|
||||
|
||||
TEST_F(ConditionLock, DISABLED_unlock_is_release) {
|
||||
m->lock();
|
||||
isReleased = false;
|
||||
m->unlock();
|
||||
|
||||
createThread([&]() {
|
||||
m->lock();
|
||||
isReleased = true;
|
||||
m->unlock();
|
||||
});
|
||||
ASSERT_TRUE(isReleased);
|
||||
}
|
||||
|
||||
TEST_F(ConditionLock, tryLock_is_false_when_locked) {
|
||||
createThread([&]() {
|
||||
m->lock();
|
||||
piMSleep(WAIT_THREAD_TIME_MS);
|
||||
});
|
||||
ASSERT_FALSE(m->tryLock());
|
||||
}
|
||||
|
||||
TEST_F(ConditionLock, tryLock_is_true_when_unlocked) {
|
||||
ASSERT_TRUE(m->tryLock());
|
||||
}
|
||||
|
||||
TEST_F(ConditionLock, tryLock_is_recursive_lock_enable) {
|
||||
m->lock();
|
||||
ASSERT_TRUE(m->tryLock());
|
||||
}
|
||||
@@ -1,209 +0,0 @@
|
||||
#include "piconditionvar.h"
|
||||
#include "pithread.h"
|
||||
#include "testutil.h"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
class ConditionVariable
|
||||
: public ::testing::Test
|
||||
, public TestUtil {
|
||||
public:
|
||||
~ConditionVariable() { delete variable; }
|
||||
PIMutex m;
|
||||
PIConditionVariable * variable;
|
||||
|
||||
protected:
|
||||
void SetUp() override {
|
||||
variable = new PIConditionVariable();
|
||||
adapterFunctionDefault = [&]() {
|
||||
m.lock();
|
||||
variable->wait(m);
|
||||
m.unlock();
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(ConditionVariable, wait_is_block) {
|
||||
createThread();
|
||||
ASSERT_FALSE(thread->waitForFinish(WAIT_THREAD_TIME_MS));
|
||||
}
|
||||
|
||||
TEST_F(ConditionVariable, wait_is_block_when_notifyOne_before_wait) {
|
||||
variable->notifyOne();
|
||||
createThread();
|
||||
ASSERT_FALSE(thread->waitForFinish(WAIT_THREAD_TIME_MS));
|
||||
}
|
||||
|
||||
TEST_F(ConditionVariable, wait_is_block_when_notifyAll_before_wait) {
|
||||
variable->notifyAll();
|
||||
createThread();
|
||||
ASSERT_FALSE(thread->waitForFinish(WAIT_THREAD_TIME_MS));
|
||||
}
|
||||
|
||||
TEST_F(ConditionVariable, wait_is_unblock_when_notifyOne_after_wait) {
|
||||
createThread();
|
||||
variable->notifyOne();
|
||||
ASSERT_TRUE(thread->waitForFinish(WAIT_THREAD_TIME_MS));
|
||||
}
|
||||
|
||||
TEST_F(ConditionVariable, wait_is_unblock_when_notifyAll_after_wait) {
|
||||
PIVector<PIThread *> threads;
|
||||
|
||||
for (int i = 0; i < THREAD_COUNT; ++i) {
|
||||
threads.push_back(new PIThread([=]() { adapterFunctionDefault(); }));
|
||||
}
|
||||
|
||||
piForeach(PIThread * thread, threads)
|
||||
thread->startOnce();
|
||||
piMSleep(WAIT_THREAD_TIME_MS * THREAD_COUNT);
|
||||
variable->notifyAll();
|
||||
PITimeMeasurer measurer;
|
||||
piForeach(PIThread * thread, threads) {
|
||||
int timeout = WAIT_THREAD_TIME_MS * THREAD_COUNT - (int)measurer.elapsed_m();
|
||||
thread->waitForFinish(timeout > 0 ? timeout : 0);
|
||||
}
|
||||
for (size_t i = 0; i < threads.size(); ++i)
|
||||
EXPECT_FALSE(threads[i]->isRunning()) << "Thread " << i << " still running";
|
||||
piForeach(PIThread * thread, threads)
|
||||
delete thread;
|
||||
}
|
||||
|
||||
TEST_F(ConditionVariable, wait_is_one_unblock_when_notifyOne) {
|
||||
PIVector<PIThread *> threads;
|
||||
|
||||
for (int i = 0; i < THREAD_COUNT; ++i) {
|
||||
threads.push_back(new PIThread(adapterFunctionDefault));
|
||||
}
|
||||
|
||||
piForeach(PIThread * thread, threads)
|
||||
thread->startOnce();
|
||||
piMSleep(WAIT_THREAD_TIME_MS * THREAD_COUNT);
|
||||
variable->notifyOne();
|
||||
piMSleep(WAIT_THREAD_TIME_MS * THREAD_COUNT);
|
||||
int runningThreadCount = 0;
|
||||
piForeach(PIThread * thread, threads)
|
||||
if (thread->isRunning()) runningThreadCount++;
|
||||
ASSERT_EQ(runningThreadCount, THREAD_COUNT - 1);
|
||||
}
|
||||
|
||||
TEST_F(ConditionVariable, wait_is_protected_unblock_when_notifyOne) {
|
||||
createThread([&]() {
|
||||
m.lock();
|
||||
variable->wait(m);
|
||||
piMSleep(2 * WAIT_THREAD_TIME_MS);
|
||||
// Missing unlock
|
||||
});
|
||||
variable->notifyOne();
|
||||
piMSleep(WAIT_THREAD_TIME_MS);
|
||||
ASSERT_FALSE(m.tryLock());
|
||||
}
|
||||
|
||||
TEST_F(ConditionVariable, wait_condition_is_block) {
|
||||
createThread([&]() {
|
||||
m.lock();
|
||||
variable->wait(m, []() { return false; });
|
||||
m.unlock();
|
||||
});
|
||||
ASSERT_FALSE(thread->waitForFinish(WAIT_THREAD_TIME_MS));
|
||||
}
|
||||
|
||||
TEST_F(ConditionVariable, wait_condition_is_check_condition_before_block) {
|
||||
bool isConditionChecked = false;
|
||||
createThread([&]() {
|
||||
m.lock();
|
||||
variable->wait(m, [&]() {
|
||||
isConditionChecked = true;
|
||||
return false;
|
||||
});
|
||||
m.unlock();
|
||||
});
|
||||
m.lock();
|
||||
ASSERT_TRUE(isConditionChecked);
|
||||
m.unlock();
|
||||
}
|
||||
|
||||
TEST_F(ConditionVariable, wait_condition_is_check_condition_when_notifyOne) {
|
||||
bool isConditionChecked;
|
||||
createThread([&]() {
|
||||
m.lock();
|
||||
variable->wait(m, [&]() {
|
||||
isConditionChecked = true;
|
||||
return false;
|
||||
});
|
||||
m.unlock();
|
||||
});
|
||||
m.lock();
|
||||
isConditionChecked = false;
|
||||
m.unlock();
|
||||
variable->notifyOne();
|
||||
piMSleep(threadStartTime + 1);
|
||||
m.lock();
|
||||
ASSERT_TRUE(isConditionChecked);
|
||||
m.unlock();
|
||||
}
|
||||
|
||||
TEST_F(ConditionVariable, wait_condition_is_unblock_when_condition_and_notifyOne) {
|
||||
bool condition = false;
|
||||
createThread([&]() {
|
||||
m.lock();
|
||||
variable->wait(m, [&]() { return condition; });
|
||||
m.unlock();
|
||||
});
|
||||
m.lock();
|
||||
condition = true;
|
||||
m.unlock();
|
||||
variable->notifyOne();
|
||||
ASSERT_TRUE(thread->waitForFinish(WAIT_THREAD_TIME_MS));
|
||||
}
|
||||
|
||||
TEST_F(ConditionVariable, DISABLED_waitFor_is_block_before_timeout) {
|
||||
createThread([&]() {
|
||||
PITimeMeasurer measurer;
|
||||
m.lock();
|
||||
variable->waitFor(m, WAIT_THREAD_TIME_MS * 2);
|
||||
m.unlock();
|
||||
// Not reliable because spurious wakeup may happen
|
||||
ASSERT_GE(measurer.elapsed_m(), WAIT_THREAD_TIME_MS);
|
||||
});
|
||||
EXPECT_TRUE(thread->waitForFinish(WAIT_THREAD_TIME_MS * 3));
|
||||
}
|
||||
|
||||
TEST_F(ConditionVariable, waitFor_is_unblock_when_timeout) {
|
||||
std::atomic_bool isUnblock(false);
|
||||
createThread([&]() {
|
||||
m.lock();
|
||||
variable->waitFor(m, WAIT_THREAD_TIME_MS);
|
||||
isUnblock = true;
|
||||
m.unlock();
|
||||
});
|
||||
// Test failed if suspend forever
|
||||
EXPECT_TRUE(thread->waitForFinish(2 * WAIT_THREAD_TIME_MS));
|
||||
ASSERT_TRUE(isUnblock);
|
||||
}
|
||||
|
||||
TEST_F(ConditionVariable, waitFor_is_false_when_timeout) {
|
||||
bool waitRet = true;
|
||||
createThread([&]() {
|
||||
m.lock();
|
||||
waitRet = variable->waitFor(m, WAIT_THREAD_TIME_MS);
|
||||
m.unlock();
|
||||
});
|
||||
EXPECT_TRUE(thread->waitForFinish(2 * WAIT_THREAD_TIME_MS));
|
||||
ASSERT_FALSE(waitRet);
|
||||
}
|
||||
|
||||
TEST_F(ConditionVariable, waitFor_is_unblock_when_condition_and_notifyOne) {
|
||||
bool condition = false;
|
||||
createThread([&]() {
|
||||
m.lock();
|
||||
variable->waitFor(m, 3 * WAIT_THREAD_TIME_MS, [&]() { return condition; });
|
||||
m.unlock();
|
||||
});
|
||||
EXPECT_TRUE(thread->isRunning());
|
||||
m.lock();
|
||||
condition = true;
|
||||
m.unlock();
|
||||
variable->notifyOne();
|
||||
piMSleep(WAIT_THREAD_TIME_MS);
|
||||
ASSERT_FALSE(thread->isRunning());
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
#include "pimutex.h"
|
||||
#include "pithreadpoolexecutor.h"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
const int WAIT_THREAD_TIME_MS = 30;
|
||||
|
||||
TEST(ExcutorIntegrationTest, execute_is_runnable_invoke) {
|
||||
PIMutex m;
|
||||
int invokedRunnables = 0;
|
||||
PIThreadPoolExecutor executorService(1);
|
||||
executorService.execute([&]() {
|
||||
m.lock();
|
||||
invokedRunnables++;
|
||||
m.unlock();
|
||||
});
|
||||
piMSleep(WAIT_THREAD_TIME_MS);
|
||||
ASSERT_EQ(invokedRunnables, 1);
|
||||
}
|
||||
|
||||
TEST(ExcutorIntegrationTest, execute_is_not_execute_after_shutdown) {
|
||||
bool isRunnableInvoke = false;
|
||||
PIThreadPoolExecutor executorService(1);
|
||||
executorService.shutdown();
|
||||
executorService.execute([&]() { isRunnableInvoke = true; });
|
||||
piMSleep(WAIT_THREAD_TIME_MS);
|
||||
ASSERT_FALSE(isRunnableInvoke);
|
||||
}
|
||||
|
||||
TEST(ExcutorIntegrationTest, execute_is_execute_before_shutdown) {
|
||||
bool isRunnableInvoke = false;
|
||||
PIThreadPoolExecutor executorService(1);
|
||||
executorService.execute([&]() {
|
||||
piMSleep(WAIT_THREAD_TIME_MS);
|
||||
isRunnableInvoke = true;
|
||||
});
|
||||
executorService.shutdown();
|
||||
piMSleep(2 * WAIT_THREAD_TIME_MS);
|
||||
ASSERT_TRUE(isRunnableInvoke);
|
||||
}
|
||||
|
||||
TEST(ExcutorIntegrationTest, execute_is_awaitTermination_wait) {
|
||||
PIThreadPoolExecutor executorService(1);
|
||||
executorService.execute([&]() { piMSleep(2 * WAIT_THREAD_TIME_MS); });
|
||||
executorService.shutdown();
|
||||
PITimeMeasurer measurer;
|
||||
ASSERT_TRUE(executorService.awaitTermination(3 * WAIT_THREAD_TIME_MS));
|
||||
double waitTime = measurer.elapsed_m();
|
||||
ASSERT_GE(waitTime, WAIT_THREAD_TIME_MS);
|
||||
ASSERT_LE(waitTime, 4 * WAIT_THREAD_TIME_MS);
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
#include "pithreadnotifier.h"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
|
||||
TEST(PIThreadNotifierTest, One) {
|
||||
PIThreadNotifier n;
|
||||
int cnt = 0;
|
||||
PIThread t1(
|
||||
[&n, &cnt]() {
|
||||
n.wait();
|
||||
cnt++;
|
||||
},
|
||||
true);
|
||||
piMSleep(10);
|
||||
n.notifyOnce();
|
||||
piMSleep(10);
|
||||
ASSERT_EQ(cnt, 1);
|
||||
n.notifyOnce();
|
||||
piMSleep(10);
|
||||
ASSERT_EQ(cnt, 2);
|
||||
}
|
||||
|
||||
|
||||
TEST(PIThreadNotifierTest, Two) {
|
||||
PIThreadNotifier n;
|
||||
int cnt1 = 0;
|
||||
int cnt2 = 0;
|
||||
int cnt3 = 0;
|
||||
PIThread t1(
|
||||
[&n, &cnt1]() {
|
||||
n.wait();
|
||||
cnt1++;
|
||||
piMSleep(2);
|
||||
},
|
||||
true);
|
||||
PIThread t2(
|
||||
[&n, &cnt2]() {
|
||||
n.wait();
|
||||
cnt2++;
|
||||
piMSleep(2);
|
||||
},
|
||||
true);
|
||||
PIThread t3(
|
||||
[&n, &cnt3]() {
|
||||
n.notifyOnce();
|
||||
cnt3++;
|
||||
piMSleep(1);
|
||||
},
|
||||
true);
|
||||
piMSleep(20);
|
||||
t3.stop(true);
|
||||
piMSleep(100);
|
||||
t1.stop();
|
||||
t2.stop();
|
||||
ASSERT_EQ(cnt1 + cnt2, cnt3);
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
#ifndef AWRCANFLASHER_TESTUTIL_H
|
||||
#define AWRCANFLASHER_TESTUTIL_H
|
||||
|
||||
#include "pithread.h"
|
||||
|
||||
#include <atomic>
|
||||
|
||||
/**
|
||||
* Minimum wait thread start, switch context or another interthread communication action time. Increase it if tests
|
||||
* write "Start thread timeout reach!" message. You can reduce it if you want increase test performance.
|
||||
*/
|
||||
const int WAIT_THREAD_TIME_MS = 400;
|
||||
|
||||
const int THREAD_COUNT = 5;
|
||||
|
||||
class TestUtil: public PIObject {
|
||||
PIOBJECT(TestUtil)
|
||||
|
||||
public:
|
||||
double threadStartTime;
|
||||
PIThread * thread = new PIThread();
|
||||
std::atomic_bool isRunning;
|
||||
std::function<void()> adapterFunctionDefault;
|
||||
|
||||
TestUtil(): isRunning(false) {}
|
||||
|
||||
bool createThread(const std::function<void()> & fun = nullptr, PIThread * thread_ = nullptr) {
|
||||
std::function<void()> actualFun = fun == nullptr ? adapterFunctionDefault : fun;
|
||||
if (thread_ == nullptr) thread_ = thread;
|
||||
thread_->startOnce([=](void *) {
|
||||
isRunning = true;
|
||||
actualFun();
|
||||
});
|
||||
return waitThread(thread_);
|
||||
}
|
||||
|
||||
bool waitThread(PIThread * thread_, bool runningStatus = true) {
|
||||
PITimeMeasurer measurer;
|
||||
bool isTimeout = !thread_->waitForStart(WAIT_THREAD_TIME_MS);
|
||||
while (!isRunning) {
|
||||
isTimeout = WAIT_THREAD_TIME_MS <= measurer.elapsed_m();
|
||||
if (isTimeout) break;
|
||||
piUSleep(100);
|
||||
}
|
||||
|
||||
threadStartTime = measurer.elapsed_m();
|
||||
|
||||
if (isTimeout) piCout << "Start thread timeout reach!";
|
||||
|
||||
if (threadStartTime > 1) {
|
||||
piCout << "Start time" << threadStartTime << "ms";
|
||||
} else if (threadStartTime > 0.001) {
|
||||
piCout << "Start time" << threadStartTime * 1000 << "mcs";
|
||||
} else {
|
||||
piCout << "Start time" << threadStartTime * 1000 * 1000 << "ns";
|
||||
}
|
||||
|
||||
return !isTimeout;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // AWRCANFLASHER_TESTUTIL_H
|
||||
@@ -376,7 +376,7 @@ TEST(PIMathMatrixT_Test, invert) {
|
||||
matrix3 = matrix1;
|
||||
matrix1.invert();
|
||||
EXPECT_EQ(matrix1, matrix3);
|
||||
EXPECT_DOUBLE_EQ(std::abs(d1 - (1. / d2)), 0.);
|
||||
EXPECT_NEAR(std::abs(d1 - (1. / d2)), 0., 1e-12);
|
||||
}
|
||||
|
||||
TEST(PIMathMatrixT_Test, inverted) {
|
||||
|
||||
@@ -467,11 +467,20 @@ bool procDpkg(const PIString & l) {
|
||||
if (!vs.isEmpty()) {
|
||||
PIStringList lines = vs.split('\n').reverse();
|
||||
for (auto l: lines) {
|
||||
auto sl = l;
|
||||
l = l.left(l.find(":"));
|
||||
if (!l.isEmpty() && !l.endsWith("-cross") && !l.contains(' ')) all_deps << l;
|
||||
// PICout(true) << "** found \"" << l << "\" in \"" << sl << "\"";
|
||||
return true;
|
||||
l = l.left(l.find(":"));
|
||||
if (!l.isEmpty() && !l.contains(' ') && !l.endsWith("-cross") && !l.endsWith("-dev")) {
|
||||
// PICout(true) << "** found \"" << l << "\" in \"" << sl << "\"";
|
||||
all_deps << l;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
for (auto l: lines) {
|
||||
l = l.left(l.find(":"));
|
||||
if (!l.isEmpty() && !l.contains(' ') && !l.endsWith("-cross")) {
|
||||
// PICout(true) << "** found \"" << l << "\" in \"" << sl << "\"";
|
||||
all_deps << l;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
// piCout << "No dep on" << l;
|
||||
|
||||
Reference in New Issue
Block a user