93 Commits

Author SHA1 Message Date
866f71edb5 Merge pull request 'geometry_refact' (#86) from geometry_refact into master
Reviewed-on: https://git.shs.tools/SHS/pip/pulls/86
2022-03-21 14:14:12 +03:00
Andrey
4bae04feec code style 2022-03-21 12:20:11 +03:00
Andrey
415160387b PILine 2022-03-21 10:49:41 +03:00
Andrey
3dd0d0b6cf PIRect complete 2022-03-21 10:35:34 +03:00
Andrey
2596b119ac start refactoring pigeometry.h 2022-03-18 18:06:40 +03:00
58de1ceafc Merge pull request 'micro' (#83) from micro into master
Reviewed-on: https://git.shs.tools/SHS/pip/pulls/83
2022-03-14 12:10:32 +03:00
20e6d1be99 Merge branch 'master' into micro 2022-03-14 11:57:06 +03:00
2a877fbb6b pip_cmg supports for "simple-stream" PIMETA tag for structs and classes for simple de/serialization without PIChunkStream 2022-03-11 14:39:08 +03:00
2a6ebc9d8d piCompare change position 2022-02-14 19:12:41 +03:00
Andrey
c3c98b9d78 include fixes 2022-02-14 14:01:54 +03:00
Andrey
443e8b46a6 Merge branch 'master' of https://git.shs.tools/SHS/pip into micro 2022-02-11 12:00:49 +03:00
Andrey
fff2aa468a PIP_FORCE_NO_PIINTROSPECTION 2022-02-11 12:00:34 +03:00
1918e55a97 piCompare use piAbs 2022-02-08 00:33:12 +03:00
eb6d378de2 deploy tool unchained from "grep" and support qt6 2022-01-31 19:55:23 +03:00
b1b174ba64 missed include 2022-01-23 12:59:13 +03:00
Andrey
4921a3b0fd arduino PISystemTime::current 2022-01-21 17:09:21 +03:00
Andrey
8296e9a32b add FreeRTOS support for PIThread PIMutex PIConditionVariable 2022-01-21 14:15:42 +03:00
Andrey
7403ee67be gitignore 2022-01-20 16:54:20 +03:00
Andrey
cde2341c1f fix freertos includes 2022-01-20 16:46:04 +03:00
Andrey
542f180d9d add Freertos dependency 2022-01-17 18:39:57 +03:00
86130d7105 compiled for esp32 2022-01-15 14:54:36 +03:00
Andrey
c9e329d27d rename PIInit BuildOption 2022-01-14 18:51:37 +03:00
Andrey
d4c6c410da some fixes 2022-01-14 18:25:41 +03:00
Andrey
a7df53fbfe platformio_pre.py 2022-01-14 18:15:56 +03:00
Andrey
0504fa187e define PIP_MICRO
detect AVR_GCC
add library.json
2022-01-14 14:37:51 +03:00
1d9a39f792 piCompare 2022-01-10 17:10:41 +03:00
cbdaabee4a some build fixes 2022-01-07 01:58:38 +03:00
3c8ccf357b PIFile::openTemporary on Windows
PIPair from std::tuple
2021-12-24 14:41:18 +03:00
Andrey
92b20f6f46 PIByteArray getRange 2021-11-16 15:22:03 +03:00
04d7ed77d9 Merge pull request 'condvar_use' (#82) from condvar_use into master
Reviewed-on: https://git.shs.tools/SHS/pip/pulls/82
2021-11-16 14:49:52 +03:00
a2a205cfd2 version 2.33.0
piMinSleep() method
2021-11-16 14:43:57 +03:00
d3b6597042 PIMap range-for decomposition declaration support 2021-11-01 23:29:42 +03:00
Andrey
48c885e12a PIThreadNotifier, rewrite PIObject::deleteLater()
tests for PIThreadNotifier and PIObject::deleteLater()
2021-10-29 18:20:48 +03:00
Andrey
6e5a5a6ade remove msleep, clean PIConditionVariable, rewrite pipipelinethread, etc... 2021-10-29 16:52:03 +03:00
21e03fc8cb flags 2021-10-27 10:53:27 +03:00
b85de0d704 work with PIFile::openTemporary() on Windows 2021-10-26 13:50:27 +03:00
peri4
f781cc3846 binary log improvements 2021-10-21 18:48:01 +03:00
peri4
1cb3d4ffe9 PIBinaryLog fix 2021-10-14 12:45:01 +03:00
peri4
9293706634 PISerial 14400 baudrate only for Windows 2021-10-08 22:11:47 +03:00
peri4
fde6bdf17f PISerial 14400 baudrate 2021-10-08 22:02:51 +03:00
Andrey
a1c1fd8339 Merge branch 'master' of https://git.shs.tools/SHS/pip 2021-10-08 15:16:19 +03:00
Andrey
01b39dc75f pip_cmg fix macros name 2021-10-08 15:16:08 +03:00
07ec32c969 tests 2021-10-05 20:31:00 +03:00
042366e19e Merge branch 'PIMathMatrixTests1-10' 2021-10-04 22:14:38 +03:00
948a90fcd9 option revert 2021-10-04 22:14:15 +03:00
c404688bbd more safety for PIObject::Connection::disconnect() 2021-10-04 21:57:34 +03:00
aa76a15f40 version 2.32.0
PIObject::Connection struct
2021-10-04 21:50:49 +03:00
Andrey
ca20785b53 revert piDisconnectAll 2021-10-04 15:07:14 +03:00
Andrey
13d0b2f960 remove piDisconnectAll 2021-10-04 15:05:58 +03:00
Andrey
46571ac39f piDisconnectAll private 2021-10-04 14:18:23 +03:00
36d770ea2e Merge pull request 'piobject_tests' (#80) from piobject_tests into master
Reviewed-on: https://git.shs.tools/SHS/pip/pulls/80
2021-10-04 12:11:51 +03:00
Andrey
bc7d129a9e piobject/connect.cpp tests 2021-10-04 12:07:01 +03:00
8accc28804 test fix 2021-09-30 19:28:30 +03:00
Andrey
62e130f91b disconnect test failed 2021-09-30 18:41:01 +03:00
a009221092 pidisconnect now work with lambdas 2021-09-30 16:21:28 +03:00
dedc35b466 new class PIThreadPoolLoop 2021-09-24 16:03:20 +03:00
5e33587703 PISerial::setBreak linux fix 2021-09-17 21:27:24 +03:00
950f6830da old gcc pithread fix 2021-09-17 21:20:21 +03:00
Andrey
19a8ca84e6 PIByteArray checksumPlain invert flag
fix PISerial setBreak
2021-09-16 16:18:20 +03:00
Andrey
ece3fb1536 PISerial setBreak 2021-09-16 12:18:17 +03:00
0d119502a8 PIDeque functions same as PIVector
code brush
fix indexOf and entries with start<0
2021-09-09 18:01:57 +03:00
cc5951cfc3 PIVector getRange removeWhere 2021-09-09 17:38:28 +03:00
61d42e0ac5 PIVector: map, reduce
rename arguments in uniform style
2021-09-07 18:29:09 +03:00
127935086c PIVector: any, every, indexWhere, lastIndexWhere
start arg in indexOf, entries, lastIndexOf
and some code brush
2021-09-07 17:29:24 +03:00
76ed60edf3 code brush 2021-09-07 15:39:44 +03:00
3b0a1c70fe documentation fix 2021-09-03 17:12:46 +03:00
186e07e45d PICodeInfo::EnumInfo toPIVariantEnum 2021-09-03 16:19:57 +03:00
047cff7d6e version 2021-09-03 12:42:29 +03:00
305275e3ac PICodeParser namespaces fix 2021-09-03 11:39:26 +03:00
efb0d5f4f9 PICodeParser predefined PIP macros 2021-09-03 11:20:38 +03:00
991a074538 version 2.30
PIStreamPacker remove progresses
picloud various fixes
2021-09-01 23:48:13 +03:00
f82b6c12ee cloud_dispatcher patch 2021-09-01 22:43:40 +03:00
00edfa4ef0 cloud data send optimize 2021-09-01 17:48:58 +03:00
35a3ce6402 picloudtcp.cpp revert some mutex 2021-09-01 10:56:11 +03:00
be3ce454a0 picloud multithread fix 2021-08-31 19:40:22 +03:00
4c85206cfa version 2021-08-23 14:07:45 +03:00
5ecdcbe46e Merge pull request 'cloud_debug' (#78) from cloud_debug into master
Reviewed-on: https://git.shs.tools/SHS/pip/pulls/78
2021-08-23 13:58:08 +03:00
c937d7251a it works 2021-08-23 13:56:21 +03:00
1cc46468c1 fail 2021-08-20 18:30:19 +03:00
5cc8ef1eb0 fail reconnect 2021-08-20 18:25:59 +03:00
99e135caa2 PICloudClient disconnect 2021-08-20 17:22:25 +03:00
9de7045d63 picloud revert to condvars and fix 2021-08-20 16:36:28 +03:00
0e65151e9f PIEthernet error 232
PICloud many fixes
PIBroadcast recursive fix
2021-08-20 10:55:47 +03:00
3c20728210 version 2021-08-19 18:29:05 +03:00
4c0530d89a picloud ping and fix big bugs 2021-08-19 18:13:05 +03:00
f5af8a1da9 disable autostart pibroadcast 2021-08-19 15:02:30 +03:00
44b9c37391 PICloudClient now soft stop thread when closed
last cmake changes
2021-08-16 22:30:56 +03:00
97b0b6fc0c picloud hash key 2021-08-12 22:05:02 +03:00
1a2e9afaef PIVector compare operators 2021-08-12 21:52:14 +03:00
39a3a23a24 PIByteArray compare operators 2021-08-12 21:41:22 +03:00
ee131921a0 add PIByteArray operator <, fix picloud 2021-08-12 20:22:43 +03:00
f8818c8537 picloud patch 2021-08-12 19:50:17 +03:00
b07242226e Tests1-10 2021-02-25 15:41:20 +03:00
119 changed files with 3450 additions and 1692 deletions

1
.gitignore vendored
View File

@@ -3,3 +3,4 @@
/doc/rtf /doc/rtf
_unsused _unsused
CMakeLists.txt.user* CMakeLists.txt.user*
/include

View File

@@ -2,8 +2,8 @@ cmake_minimum_required(VERSION 3.0)
cmake_policy(SET CMP0017 NEW) # need include() with .cmake cmake_policy(SET CMP0017 NEW) # need include() with .cmake
project(pip) project(pip)
set(pip_MAJOR 2) set(pip_MAJOR 2)
set(pip_MINOR 28) set(pip_MINOR 34)
set(pip_REVISION 1) set(pip_REVISION 0)
set(pip_SUFFIX ) set(pip_SUFFIX )
set(pip_COMPANY SHS) set(pip_COMPANY SHS)
set(pip_DOMAIN org.SHS) set(pip_DOMAIN org.SHS)
@@ -284,7 +284,7 @@ endif()
if(APPLE) if(APPLE)
add_definitions(-D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE) add_definitions(-D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE)
endif() endif()
if ((NOT DEFINED LIBPROJECT) AND (DEFINED ANDROID_PLATFORM)) if ((NOT DEFINED SHSTKPROJECT) AND (DEFINED ANDROID_PLATFORM))
include_directories(${ANDROID_SYSTEM_LIBRARY_PATH}/usr/include) include_directories(${ANDROID_SYSTEM_LIBRARY_PATH}/usr/include)
#message("${ANDROID_SYSTEM_LIBRARY_PATH}/usr/include") #message("${ANDROID_SYSTEM_LIBRARY_PATH}/usr/include")
#message("${ANDROID_NDK}/sysroot/usr/include") #message("${ANDROID_NDK}/sysroot/usr/include")
@@ -320,7 +320,7 @@ if(WIN32)
set(CMAKE_CXX_FLAGS "/O2 /Ob2 /Ot /W0") set(CMAKE_CXX_FLAGS "/O2 /Ob2 /Ot /W0")
endif() endif()
else() else()
set(${CMAKE_CXX_FLAGS} "${CMAKE_CXX_FLAGS} -fPIC") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC")
if(DEFINED ENV{QNX_HOST} OR PIP_FREERTOS) if(DEFINED ENV{QNX_HOST} OR PIP_FREERTOS)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ftemplate-depth-32") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ftemplate-depth-32")
endif() endif()
@@ -567,8 +567,8 @@ if ((NOT PIP_FREERTOS) AND (NOT CROSSTOOLS))
list(APPEND DOXY_INPUT "\"${F}\"") list(APPEND DOXY_INPUT "\"${F}\"")
endforeach(F) endforeach(F)
string(REPLACE ";" " " DOXY_INPUT "\"${CMAKE_CURRENT_SOURCE_DIR}/libs\"") string(REPLACE ";" " " DOXY_INPUT "\"${CMAKE_CURRENT_SOURCE_DIR}/libs\"")
string(REPLACE ";" " " DOXY_INCLUDE_PATH "${DOXY_INPUT}") string(REPLACE ";" " " DOXY_INCLUDE_PATH "${PIP_INCLUDES}")
string(REPLACE ";" " " DOXY_DEFINES "${PIP_EXPORTS};DOXYGEN;PIOBJECT;PIOBJECT_SUBCLASS") string(REPLACE ";" " " DOXY_DEFINES "${PIP_EXPORTS}")
add_documentation(doc doc/Doxyfile.in) add_documentation(doc doc/Doxyfile.in)
install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/doc/html DESTINATION ../share/doc/pip COMPONENT doc EXCLUDE_FROM_ALL OPTIONAL) install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/doc/html DESTINATION ../share/doc/pip COMPONENT doc EXCLUDE_FROM_ALL OPTIONAL)
endif() endif()

View File

@@ -71,6 +71,10 @@ if (NOT BUILDING_pip)
find_library(PTHREAD_LIBRARY pthread) find_library(PTHREAD_LIBRARY pthread)
find_library(UTIL_LIBRARY util) find_library(UTIL_LIBRARY util)
set(_PIP_ADD_LIBS_ ${PTHREAD_LIBRARY} ${UTIL_LIBRARY}) set(_PIP_ADD_LIBS_ ${PTHREAD_LIBRARY} ${UTIL_LIBRARY})
if((NOT DEFINED ENV{QNX_HOST}) AND (NOT APPLE) AND (NOT PIP_FREERTOS))
find_library(RT_LIBRARY rt)
list(APPEND _PIP_ADD_LIBS_ ${RT_LIBRARY})
endif()
list(APPEND PIP_LIBRARY ${_PIP_ADD_LIBS_}) list(APPEND PIP_LIBRARY ${_PIP_ADD_LIBS_})
endif() endif()
endif() endif()

View File

@@ -2164,7 +2164,7 @@ INCLUDE_FILE_PATTERNS =
# recursively expanded use the := operator instead of the = operator. # recursively expanded use the := operator instead of the = operator.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES. # This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
PREDEFINED = ${DOXY_DEFINES} PREDEFINED = DOXYGEN PIOBJECT PIOBJECT_SUBCLASS PIIODEVICE NO_COPY_CLASS ${DOXY_DEFINES}
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this

BIN
doc/images/pirect.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB

29
library.json Normal file
View File

@@ -0,0 +1,29 @@
{
"name": "PIP",
"keywords": "pip",
"description": "Platform-Independent Primitives",
"repository":
{
"type": "git",
"url": "https://git.shs.tools/SHS/pip.git"
},
"frameworks": "*",
"platforms": "*",
"dependencies": {
"mike-matera/ArduinoSTL": "^1.3.2",
"linlin-study/FreeRTOS-Kernel": ">=10.0.0"
},
"build":
{
"srcFilter": [
"+<libs/main/core/*.cpp>",
"+<libs/main/containers/*.cpp>",
"+<libs/main/math/*.cpp>",
"+<libs/main/thread/*.cpp>",
"+<libs/main/io_uutils/*.cpp>",
"+<libs/main/geo/*.cpp>"
],
"extraScript": "platformio_pre.py",
"flags": "-DPIP_FREERTOS"
}
}

View File

@@ -2,7 +2,7 @@
PICloudBase::PICloudBase() : eth(PIEthernet::TCP_Client), streampacker(&eth), tcp(&streampacker) { PICloudBase::PICloudBase() : eth(PIEthernet::TCP_Client), streampacker(&eth), tcp(&streampacker) {
eth.setDebug(false);
} }

View File

@@ -25,29 +25,36 @@ PICloudClient::PICloudClient(const PIString & path, PIIODevice::DeviceMode mode)
tcp.setRole(PICloud::TCP::Client); tcp.setRole(PICloud::TCP::Client);
setName("cloud_client"); setName("cloud_client");
is_connected = false; is_connected = false;
CONNECTL(&eth, connected, [this](){tcp.sendStart();}); is_deleted = false;
// setReopenEnabled(false);
CONNECTL(&eth, connected, [this](){opened_ = true; tcp.sendStart();});
CONNECTU(&streampacker, packetReceiveEvent, this, _readed); CONNECTU(&streampacker, packetReceiveEvent, this, _readed);
CONNECTL(&eth, disconnected, [this](bool){ CONNECTL(&eth, disconnected, [this](bool){
piCoutObj << "disconnected"; if (is_deleted) return;
bool need_disconn = is_connected;
//piCoutObj << "eth disconnected";
static_cast<PIThread*>(&eth)->stop();
opened_ = false; opened_ = false;
is_connected = false; internalDisconnect();
cond_connect.notifyOne(); if (need_disconn)
cond_buff.notifyOne(); disconnected();
piMSleep(100); //piCoutObj << "eth disconnected done";
}); });
} }
PICloudClient::~PICloudClient() { PICloudClient::~PICloudClient() {
eth.close(); //piCoutObj << "~PICloudClient()";
if (is_connected) { PIThread::stop();
is_connected = false; //eth.close();
disconnected(); //if (is_connected) disconnected();
cond_buff.notifyOne();
cond_connect.notifyOne();
}
close(); close();
stop(); //piCoutObj << "~PICloudClient() closed";
internalDisconnect();
// stop(false);
is_deleted = true;
internalDisconnect();
//piCoutObj << "~PICloudClient() done";
} }
@@ -63,80 +70,100 @@ void PICloudClient::setKeepConnection(bool on) {
bool PICloudClient::openDevice() { bool PICloudClient::openDevice() {
// piCout << "PICloudClient open device" << path(); //piCoutObj << "open";// << path();
bool op = eth.connect(PIEthernet::Address::resolve(path()), false); bool op = eth.connect(PIEthernet::Address::resolve(path()), false);
if (op) { if (op) {
mutex_buff.lock(); mutex_connect.lock();
eth.startThreadedRead(); eth.startThreadedRead();
bool conn_ok = cond_connect.waitFor(mutex_buff, (int)eth.readTimeout(), [this](){return isConnected();}); //piCoutObj << "connecting...";
piCoutObj << "conn_ok" << conn_ok; bool conn_ok = cond_connect.waitFor(mutex_connect, (int)eth.readTimeout());
mutex_buff.unlock(); //piCoutObj << "conn_ok" << conn_ok << is_connected;
mutex_connect.unlock();
if (!conn_ok) { if (!conn_ok) {
mutex_connect.lock();
eth.stop(); eth.stop();
eth.close(); eth.close();
piMSleep(100); mutex_connect.unlock();
} }
return isConnected(); return is_connected;
} else { } else {
eth.close(); //eth.close();
return false; return false;
} }
} }
bool PICloudClient::closeDevice() { bool PICloudClient::closeDevice() {
//PIThread::stop();
if (is_connected) { if (is_connected) {
is_connected = false; internalDisconnect();
disconnected();
cond_buff.notifyOne();
cond_connect.notifyOne();
} }
eth.stop(); eth.stop();
if (eth.isOpened()) eth.close(); eth.close();
return true; return true;
} }
int PICloudClient::readDevice(void * read_to, int max_size) { int PICloudClient::readDevice(void * read_to, int max_size) {
// piCoutObj << "readDevice"; if (is_deleted) return -1;
if (!is_connected) return -1; //piCoutObj << "readDevice";
if (!is_connected && eth.isClosed()) openDevice();
int sz = -1;
mutex_buff.lock(); mutex_buff.lock();
cond_buff.wait(mutex_buff, [this](){return !buff.isEmpty();}); cond_buff.wait(mutex_buff, [this](){return !buff.isEmpty() || !is_connected;});
int sz = piMini(max_size, buff.size()); if (is_connected) {
sz = piMini(max_size, buff.size());
memcpy(read_to, buff.data(), sz); memcpy(read_to, buff.data(), sz);
buff.remove(0, sz); buff.remove(0, sz);
}
mutex_buff.unlock(); mutex_buff.unlock();
if (!is_connected) opened_ = false;
//piCoutObj << "readDevice done" << sz;
return sz; return sz;
} }
int PICloudClient::writeDevice(const void * data, int size) { int PICloudClient::writeDevice(const void * data, int size) {
if (is_deleted) return -1;
// piCoutObj << "writeDevice"; // piCoutObj << "writeDevice";
return tcp.sendData(PIByteArray(data, size)); return tcp.sendData(PIByteArray(data, size));
} }
void PICloudClient::internalDisconnect() {
is_connected = false;
cond_buff.notifyOne();
cond_connect.notifyOne();
streampacker.clear();
buff.clear();
}
void PICloudClient::_readed(PIByteArray & ba) { void PICloudClient::_readed(PIByteArray & ba) {
mutex_buff.lock(); if (is_deleted) return;
PIPair<PICloud::TCP::Type, PICloud::TCP::Role> hdr = tcp.parseHeader(ba); PIPair<PICloud::TCP::Type, PICloud::TCP::Role> hdr = tcp.parseHeader(ba);
//piCoutObj << "_readed" << ba.size() << hdr.first << hdr.second;
if (hdr.second == tcp.role()) { if (hdr.second == tcp.role()) {
switch (hdr.first) { switch (hdr.first) {
case PICloud::TCP::Connect: case PICloud::TCP::Connect:
if (tcp.parseConnect(ba) == 1) { if (tcp.parseConnect(ba) == 1) {
mutex_connect.lock();
is_connected = true; is_connected = true;
connected(); mutex_connect.unlock();
cond_connect.notifyOne(); cond_connect.notifyOne();
connected();
} }
break; break;
case PICloud::TCP::Disconnect: case PICloud::TCP::Disconnect:
is_connected = false; static_cast<PIThread*>(&eth)->stop();
eth.stop(); opened_ = false;
eth.close(); eth.close();
disconnected();
break; break;
case PICloud::TCP::Data: case PICloud::TCP::Data:
if (is_connected) { if (is_connected) {
mutex_buff.lock();
buff.append(ba); buff.append(ba);
mutex_buff.unlock();
cond_buff.notifyOne(); cond_buff.notifyOne();
} }
break; break;
@@ -145,7 +172,7 @@ void PICloudClient::_readed(PIByteArray & ba) {
} }
//piCoutObj << "readed" << ba.toHex(); //piCoutObj << "readed" << ba.toHex();
} }
mutex_buff.unlock(); while (buff.size_s() > threadedReadBufferSize()) piMSleep(100); // FIXME: sleep here is bad
while (buff.size_s() > threadedReadBufferSize()) piMSleep(100); //piCoutObj << "_readed done";
} }

View File

@@ -26,12 +26,17 @@ PICloudServer::PICloudServer(const PIString & path, PIIODevice::DeviceMode mode)
tcp.setServerName(server_name); tcp.setServerName(server_name);
setName("cloud_server__" + server_name); setName("cloud_server__" + server_name);
CONNECTU(&streampacker, packetReceiveEvent, this, _readed); CONNECTU(&streampacker, packetReceiveEvent, this, _readed);
CONNECTL(&eth, connected, [this](){tcp.sendStart();}); CONNECTL(&eth, connected, [this](){opened_ = true; piCoutObj << "connected"; tcp.sendStart();});
CONNECTL(&eth, disconnected, [this](bool){ CONNECTL(&eth, disconnected, [this](bool){
piCoutObj << "disconnected"; piCoutObj << "disconnected";
static_cast<PIThread*>(&eth)->stop();
opened_ = false; opened_ = false;
ping_timer.stop(false);
piMSleep(100); piMSleep(100);
}); });
CONNECTL(&ping_timer, tickEvent, [this] (void *, int){
if (eth.isConnected()) tcp.sendPing();
});
} }
@@ -54,12 +59,14 @@ PIVector<PICloudServer::Client *> PICloudServer::clients() const {
bool PICloudServer::openDevice() { bool PICloudServer::openDevice() {
piCout << "PICloudServer open device" << path(); //piCout << "PICloudServer open device" << path();
bool op = eth.connect(PIEthernet::Address::resolve(path()), false); bool op = eth.connect(PIEthernet::Address::resolve(path()), false);
if (op) { if (op) {
eth.startThreadedRead(); eth.startThreadedRead();
ping_timer.start(5000);
return true; return true;
} }
ping_timer.stop(false);
eth.close(); eth.close();
return false; return false;
} }
@@ -67,6 +74,7 @@ bool PICloudServer::openDevice() {
bool PICloudServer::closeDevice() { bool PICloudServer::closeDevice() {
eth.stop(); eth.stop();
ping_timer.stop(false);
clients_mutex.lock(); clients_mutex.lock();
for (auto c : clients_) { for (auto c : clients_) {
c->close(); c->close();
@@ -82,7 +90,8 @@ bool PICloudServer::closeDevice() {
int PICloudServer::readDevice(void * read_to, int max_size) { int PICloudServer::readDevice(void * read_to, int max_size) {
//piCoutObj << "readDevice"; //piCoutObj << "readDevice";
piMSleep(eth.readTimeout()); if (!opened_) openDevice();
else piMSleep(eth.readTimeout());
return -1; return -1;
} }
@@ -126,22 +135,26 @@ bool PICloudServer::Client::openDevice() {
bool PICloudServer::Client::closeDevice() { bool PICloudServer::Client::closeDevice() {
PIThread::stop(false);
if (is_connected) { if (is_connected) {
server->clientDisconnect(client_id); server->clientDisconnect(client_id);
is_connected = false; is_connected = false;
cond_buff.notifyOne();
} }
cond_buff.notifyOne();
return true; return true;
} }
int PICloudServer::Client::readDevice(void * read_to, int max_size) { int PICloudServer::Client::readDevice(void * read_to, int max_size) {
if (!is_connected) return -1; if (!is_connected) return -1;
int sz = -1;
mutex_buff.lock(); mutex_buff.lock();
cond_buff.wait(mutex_buff, [this](){return !buff.isEmpty();}); cond_buff.wait(mutex_buff, [this](){return !buff.isEmpty() || !is_connected;});
int sz = piMini(max_size, buff.size()); if (is_connected) {
sz = piMini(max_size, buff.size());
memcpy(read_to, buff.data(), sz); memcpy(read_to, buff.data(), sz);
buff.remove(0, sz); buff.remove(0, sz);
}
mutex_buff.unlock(); mutex_buff.unlock();
return sz; return sz;
} }
@@ -158,7 +171,7 @@ void PICloudServer::Client::pushBuffer(const PIByteArray & ba) {
buff.append(ba); buff.append(ba);
cond_buff.notifyOne(); cond_buff.notifyOne();
mutex_buff.unlock(); mutex_buff.unlock();
while (buff.size_s() > threadedReadBufferSize()) piMSleep(100); while (buff.size_s() > threadedReadBufferSize()) piMSleep(100); // FIXME: sleep here is bad
} }
@@ -174,7 +187,7 @@ void PICloudServer::_readed(PIByteArray & ba) {
if (oc) { if (oc) {
tcp.sendDisconnected(id); tcp.sendDisconnected(id);
} else { } else {
piCoutObj << "new Client" << id; //piCoutObj << "new Client" << id;
Client * c = new Client(this, id); Client * c = new Client(this, id);
CONNECTU(c, deleted, this, clientDeleted); CONNECTU(c, deleted, this, clientDeleted);
clients_mutex.lock(); clients_mutex.lock();
@@ -186,7 +199,7 @@ void PICloudServer::_readed(PIByteArray & ba) {
} break; } break;
case PICloud::TCP::Disconnect: { case PICloud::TCP::Disconnect: {
uint id = tcp.parseDisconnect(ba); uint id = tcp.parseDisconnect(ba);
piCoutObj << "remove Client" << id; //piCoutObj << "remove Client" << id;
clients_mutex.lock(); clients_mutex.lock();
Client * oc = index_clients.value(id, nullptr); Client * oc = index_clients.value(id, nullptr);
clients_mutex.unlock(); clients_mutex.unlock();

View File

@@ -24,7 +24,7 @@
#include "pistreampacker.h" #include "pistreampacker.h"
const char hash_def_key[] = "_picrypt_"; const char hash_cloud_key[] = "_picloud_";
PICloud::TCP::Header::Header() { PICloud::TCP::Header::Header() {
@@ -33,7 +33,7 @@ PICloud::TCP::Header::Header() {
PICloud::TCP::TCP(PIStreamPacker * s) : streampacker(s) { PICloud::TCP::TCP(PIStreamPacker * s) : streampacker(s) {
streampacker->setMaxPacketSize(63*1024);
} }
void PICloud::TCP::setRole(PICloud::TCP::Role r) { void PICloud::TCP::setRole(PICloud::TCP::Role r) {
@@ -43,7 +43,7 @@ void PICloud::TCP::setRole(PICloud::TCP::Role r) {
void PICloud::TCP::setServerName(const PIString & server_name_) { void PICloud::TCP::setServerName(const PIString & server_name_) {
server_name = server_name_; server_name = server_name_;
suuid = PICrypt::hash(server_name_); suuid = PICrypt::hash(PIByteArray(server_name_.data(), server_name_.size()), (const unsigned char *)hash_cloud_key, sizeof(hash_cloud_key));
} }
@@ -62,7 +62,9 @@ void PICloud::TCP::sendStart() {
PIByteArray ba; PIByteArray ba;
ba << header; ba << header;
ba.append(suuid); ba.append(suuid);
//mutex_send.lock();
streampacker->send(ba); streampacker->send(ba);
//mutex_send.unlock();
} }
@@ -70,7 +72,9 @@ void PICloud::TCP::sendConnected(uint client_id) {
header.type = PICloud::TCP::Connect; header.type = PICloud::TCP::Connect;
PIByteArray ba; PIByteArray ba;
ba << header << client_id; ba << header << client_id;
// mutex_send.lock();
streampacker->send(ba); streampacker->send(ba);
// mutex_send.unlock();
} }
@@ -78,7 +82,9 @@ void PICloud::TCP::sendDisconnected(uint client_id) {
header.type = PICloud::TCP::Disconnect; header.type = PICloud::TCP::Disconnect;
PIByteArray ba; PIByteArray ba;
ba << header << client_id; ba << header << client_id;
// mutex_send.lock();
streampacker->send(ba); streampacker->send(ba);
// mutex_send.unlock();
} }
@@ -87,8 +93,10 @@ int PICloud::TCP::sendData(const PIByteArray & data) {
PIByteArray ba; PIByteArray ba;
ba << header; ba << header;
ba.append(data); ba.append(data);
// piCout << "sendData" << ba.toHex(); // piCout << "[PICloud::TCP] sendData" << ba.toHex();
mutex_send.lock();
streampacker->send(ba); streampacker->send(ba);
mutex_send.unlock();
return data.size_s(); return data.size_s();
} }
@@ -98,11 +106,24 @@ int PICloud::TCP::sendData(const PIByteArray & data, uint client_id) {
PIByteArray ba; PIByteArray ba;
ba << header << client_id; ba << header << client_id;
ba.append(data); ba.append(data);
mutex_send.lock();
streampacker->send(ba); streampacker->send(ba);
mutex_send.unlock();
return data.size_s(); return data.size_s();
} }
void PICloud::TCP::sendPing() {
header.type = PICloud::TCP::Ping;
PIByteArray ba;
ba << header;
ba.append(suuid);
mutex_send.lock();
streampacker->send(ba);
mutex_send.unlock();
}
PIPair<PICloud::TCP::Type, PICloud::TCP::Role> PICloud::TCP::parseHeader(PIByteArray & ba) { PIPair<PICloud::TCP::Type, PICloud::TCP::Role> PICloud::TCP::parseHeader(PIByteArray & ba) {
PIPair<PICloud::TCP::Type, PICloud::TCP::Role> ret; PIPair<PICloud::TCP::Type, PICloud::TCP::Role> ret;
ret.first = InvalidType; ret.first = InvalidType;
@@ -120,11 +141,8 @@ PIPair<PICloud::TCP::Type, PICloud::TCP::Role> PICloud::TCP::parseHeader(PIByteA
} }
PIByteArray PICloud::TCP::parseData(PIByteArray & ba) { bool PICloud::TCP::canParseData(PIByteArray & ba) {
if (header.role == Client) { return header.role == Client;
return ba;
}
return PIByteArray();
} }
@@ -133,7 +151,7 @@ PIPair<uint, PIByteArray> PICloud::TCP::parseDataServer(PIByteArray & ba) {
ret.first = 0; ret.first = 0;
if (header.role == Server) { if (header.role == Server) {
ba >> ret.first; ba >> ret.first;
ret.second = ba; ret.second.swap(ba);
} }
return ret; return ret;
} }

View File

@@ -19,7 +19,7 @@
#include "picompress.h" #include "picompress.h"
#ifdef PIP_COMPRESS #ifdef PIP_COMPRESS
# ifdef FREERTOS # ifdef ESP_PLATFORM
# include "esp32/rom/miniz.h" # include "esp32/rom/miniz.h"
# define compress2 mz_compress2 # define compress2 mz_compress2
# define Z_OK MZ_OK # define Z_OK MZ_OK

View File

@@ -23,6 +23,7 @@
# include <fcntl.h> # include <fcntl.h>
# include <termios.h> # include <termios.h>
#else #else
# include <wingdi.h>
# include <wincon.h> # include <wincon.h>
# ifndef COMMON_LVB_UNDERSCORE # ifndef COMMON_LVB_UNDERSCORE
# define COMMON_LVB_UNDERSCORE 0x8000 # define COMMON_LVB_UNDERSCORE 0x8000
@@ -62,7 +63,7 @@ PIScreen::SystemConsole::SystemConsole() {
GetConsoleMode(PRIVATE->hOut, &PRIVATE->smode); GetConsoleMode(PRIVATE->hOut, &PRIVATE->smode);
GetConsoleCursorInfo(PRIVATE->hOut, &PRIVATE->curinfo); GetConsoleCursorInfo(PRIVATE->hOut, &PRIVATE->curinfo);
#else #else
# ifdef FREERTOS # ifdef MICRO_PIP
w = 80; w = 80;
h = 24; h = 24;
# else # else
@@ -108,16 +109,13 @@ void PIScreen::SystemConsole::end() {
void PIScreen::SystemConsole::prepare() { void PIScreen::SystemConsole::prepare() {
int w, h; int w = 80, h = 24;
#ifdef WINDOWS #ifdef WINDOWS
GetConsoleScreenBufferInfo(PRIVATE->hOut, &PRIVATE->csbi); GetConsoleScreenBufferInfo(PRIVATE->hOut, &PRIVATE->csbi);
w = PRIVATE->csbi.srWindow.Right - PRIVATE->csbi.srWindow.Left + 1; w = PRIVATE->csbi.srWindow.Right - PRIVATE->csbi.srWindow.Left + 1;
h = PRIVATE->csbi.srWindow.Bottom - PRIVATE->csbi.srWindow.Top + 1; h = PRIVATE->csbi.srWindow.Bottom - PRIVATE->csbi.srWindow.Top + 1;
#else #else
# ifdef FREERTOS # ifndef MICRO_PIP
w = 80;
h = 24;
# else
winsize ws; winsize ws;
ioctl(0, TIOCGWINSZ, &ws); ioctl(0, TIOCGWINSZ, &ws);
w = ws.ws_col; w = ws.ws_col;

View File

@@ -19,9 +19,10 @@
#include "piincludes_p.h" #include "piincludes_p.h"
#include "piterminal.h" #include "piterminal.h"
#include "pisharedmemory.h" #include "pisharedmemory.h"
#ifndef FREERTOS #ifndef MICRO_PIP
#ifdef WINDOWS #ifdef WINDOWS
# include <windows.h> # include <windows.h>
# include <wingdi.h>
# include <wincon.h> # include <wincon.h>
# include <winuser.h> # include <winuser.h>
#else #else
@@ -917,4 +918,4 @@ bool PITerminal::resize(int cols, int rows) {
return ret; return ret;
} }
#endif // FREERTOS #endif // MICRO_PIP

View File

@@ -169,6 +169,19 @@ PIByteArray PICrypt::hash(const PIByteArray & data) {
} }
PIByteArray PICrypt::hash(const PIByteArray & data, const unsigned char *key, size_t keylen) {
PIByteArray hash;
#ifdef PIP_CRYPT
if (!init()) return hash;
hash.resize(crypto_generichash_BYTES);
crypto_generichash(hash.data(), hash.size(), data.data(), data.size(), key, keylen);
#else
PICRYPT_DISABLED_WARNING
#endif
return hash;
}
size_t PICrypt::sizeHash() { size_t PICrypt::sizeHash() {
#ifdef PIP_CRYPT #ifdef PIP_CRYPT
return crypto_generichash_BYTES; return crypto_generichash_BYTES;

View File

@@ -53,8 +53,6 @@ PIBroadcast::PIBroadcast(bool send_only): PIThread(), PIEthUtilBase() {
_started = false; _started = false;
_send_only = send_only; _send_only = send_only;
_reinit = true; _reinit = true;
//initMcast(PIEthernet::allAddresses());
PIThread::start(3000);
} }
@@ -140,7 +138,6 @@ void PIBroadcast::initAll(PIVector<PIEthernet::Address> al) {
piForeachC (PIEthernet::Address & a, al) { piForeachC (PIEthernet::Address & a, al) {
PIEthernet * ce = 0; PIEthernet * ce = 0;
//piCout << "mcast try" << a; //piCout << "mcast try" << a;
if (_channels[Multicast]) { if (_channels[Multicast]) {
ce = new PIEthernet(); ce = new PIEthernet();
ce->setDebug(false); ce->setDebug(false);
@@ -184,7 +181,6 @@ void PIBroadcast::initAll(PIVector<PIEthernet::Address> al) {
eth_mcast << ce; eth_mcast << ce;
} }
} }
} }
if (_channels[Loopback]) { if (_channels[Loopback]) {
@@ -207,11 +203,14 @@ void PIBroadcast::initAll(PIVector<PIEthernet::Address> al) {
void PIBroadcast::send(const PIByteArray & data) { void PIBroadcast::send(const PIByteArray & data) {
if (!isRunning()) {
reinit();
PIThread::start(3000);
}
PIByteArray cd = cryptData(data); PIByteArray cd = cryptData(data);
if (cd.isEmpty()) return; if (cd.isEmpty()) return;
PIMutexLocker ml(mcast_mutex); PIMutexLocker ml(mcast_mutex);
piForeach (PIEthernet * e, eth_mcast) piForeach (PIEthernet * e, eth_mcast) e->send(cd);
e->send(cd);
if (eth_lo) { if (eth_lo) {
for (int i = 0; i < lo_pcnt; ++i) { for (int i = 0; i < lo_pcnt; ++i) {
eth_lo->send("127.0.0.1", lo_port + i, cd); eth_lo->send("127.0.0.1", lo_port + i, cd);
@@ -221,30 +220,31 @@ void PIBroadcast::send(const PIByteArray & data) {
void PIBroadcast::startRead() { void PIBroadcast::startRead() {
if (!isRunning()) {
_started = false;
reinit();
PIThread::start(3000);
}
if (_send_only) return; if (_send_only) return;
PIMutexLocker ml(mcast_mutex); PIMutexLocker ml(mcast_mutex);
piForeach (PIEthernet * e, eth_mcast) piForeach (PIEthernet * e, eth_mcast) e->startThreadedRead();
e->startThreadedRead(); if (eth_lo) eth_lo->startThreadedRead();
if (eth_lo)
eth_lo->startThreadedRead();
_started = true; _started = true;
} }
void PIBroadcast::stopRead() { void PIBroadcast::stopRead() {
if (isRunning()) stop();
PIMutexLocker ml(mcast_mutex); PIMutexLocker ml(mcast_mutex);
piForeach (PIEthernet * e, eth_mcast) piForeach (PIEthernet * e, eth_mcast) e->stopThreadedRead();
e->stopThreadedRead(); if (eth_lo) eth_lo->stopThreadedRead();
if (eth_lo)
eth_lo->stopThreadedRead();
_started = false; _started = false;
} }
void PIBroadcast::reinit() { void PIBroadcast::reinit() {
initAll(PIEthernet::allAddresses()); initAll(PIEthernet::allAddresses());
if (_started) if (_started) startRead();
startRead();
} }
@@ -261,8 +261,6 @@ void PIBroadcast::run() {
mcast_mutex.lock(); mcast_mutex.lock();
bool r = _reinit, ac = (al != prev_al); bool r = _reinit, ac = (al != prev_al);
mcast_mutex.unlock(); mcast_mutex.unlock();
if (ac || r) if (ac || r) reinit();
reinit(); if (ac) addressesChanged();
if (ac)
addressesChanged();
} }

View File

@@ -68,6 +68,13 @@ void PIStreamPacker::setCryptSizeEnabled(bool on) {
} }
void PIStreamPacker::clear() {
packet.clear();
packet_size = -1;
stream.clear();
}
void PIStreamPacker::send(const PIByteArray & data) { void PIStreamPacker::send(const PIByteArray & data) {
if (data.isEmpty()) return; if (data.isEmpty()) return;
PIByteArray cd; PIByteArray cd;
@@ -94,31 +101,12 @@ void PIStreamPacker::send(const PIByteArray & data) {
hdr << int(cd.size_s()); hdr << int(cd.size_s());
cd.insert(0, hdr); cd.insert(0, hdr);
int pcnt = (cd.size_s() - 1) / max_packet_size + 1, pst = 0; int pcnt = (cd.size_s() - 1) / max_packet_size + 1, pst = 0;
if (pcnt > 1) {
prog_s_mutex.lock();
prog_s.active = true;
prog_s.bytes_all = data.size_s();
prog_s.bytes_current = 0;
prog_s.progress = 0.;
prog_s_mutex.unlock();
}
for (int i = 0; i < pcnt; ++i) { for (int i = 0; i < pcnt; ++i) {
if (i == pcnt - 1) part = PIByteArray(cd.data(pst), cd.size_s() - pst); if (i == pcnt - 1) part = PIByteArray(cd.data(pst), cd.size_s() - pst);
else part = PIByteArray(cd.data(pst), max_packet_size); else part = PIByteArray(cd.data(pst), max_packet_size);
//piCout << "send" << part.size(); //piCout << "send" << part.size();
sendRequest(part); sendRequest(part);
pst += max_packet_size; pst += max_packet_size;
if (pcnt > 1) {
prog_s_mutex.lock();
prog_s.bytes_current += part.size_s();
prog_s.progress = (double)prog_s.bytes_current / prog_s.bytes_all;
prog_s_mutex.unlock();
}
}
if (pcnt > 1) {
prog_s_mutex.lock();
prog_s.active = false;
prog_s_mutex.unlock();
} }
} }
@@ -166,22 +154,10 @@ void PIStreamPacker::received(const PIByteArray & data) {
packet_size = sz; packet_size = sz;
if (packet_size == 0) if (packet_size == 0)
packet_size = -1; packet_size = -1;
else {
prog_r_mutex.lock();
prog_r.active = true;
prog_r.bytes_all = packet_size;
prog_r.bytes_current = 0;
prog_r.progress = 0.;
prog_r_mutex.unlock();
}
continue; continue;
} else { } else {
int ps = piMini(stream.size_s(), packet_size - packet.size_s()); int ps = piMini(stream.size_s(), packet_size - packet.size_s());
packet.append(stream.data(), ps); packet.append(stream.data(), ps);
prog_r_mutex.lock();
prog_r.bytes_current = packet.size_s();
prog_r.progress = (double)prog_r.bytes_current / piMaxi(1, prog_r.bytes_all);
prog_r_mutex.unlock();
stream.remove(0, ps); stream.remove(0, ps);
if (packet.size_s() == packet_size) { if (packet.size_s() == packet_size) {
PIByteArray cd; PIByteArray cd;
@@ -211,9 +187,6 @@ void PIStreamPacker::received(const PIByteArray & data) {
} }
packet.clear(); packet.clear();
packet_size = -1; packet_size = -1;
prog_r_mutex.lock();
prog_r.active = false;
prog_r_mutex.unlock();
} }
} }
} }
@@ -227,30 +200,3 @@ void PIStreamPacker::assignDevice(PIIODevice * dev) {
CONNECTU(dev, threadedReadEvent, this, received); CONNECTU(dev, threadedReadEvent, this, received);
CONNECTU(this, sendRequest, dev, write); CONNECTU(this, sendRequest, dev, write);
} }
PIStreamPacker::Progress PIStreamPacker::progressSend() const {
PIStreamPacker::Progress ret;
prog_s_mutex.lock();
ret = prog_s;
prog_s_mutex.unlock();
return ret;
}
PIStreamPacker::Progress PIStreamPacker::progressReceive() const {
PIStreamPacker::Progress ret;
prog_r_mutex.lock();
ret = prog_r;
prog_r_mutex.unlock();
return ret;
}
PIStreamPacker::Progress::Progress() {
active = false;
bytes_all = bytes_current = 0;
progress = 0.;
}

View File

@@ -52,12 +52,15 @@ protected:
private: private:
EVENT_HANDLER1(void, _readed, PIByteArray &, data); EVENT_HANDLER1(void, _readed, PIByteArray &, data);
void internalDisconnect();
PIByteArray buff; PIByteArray buff;
PIMutex mutex_buff; PIMutex mutex_buff;
PIMutex mutex_connect; PIMutex mutex_connect;
PIConditionVariable cond_buff; PIConditionVariable cond_buff;
PIConditionVariable cond_connect; PIConditionVariable cond_connect;
std::atomic_bool is_connected; std::atomic_bool is_connected;
std::atomic_bool is_deleted;
}; };
#endif // PICLOUDCLIENT_H #endif // PICLOUDCLIENT_H

View File

@@ -78,6 +78,7 @@ private:
PIVector<Client *> clients_; PIVector<Client *> clients_;
PIMap<uint, Client *> index_clients; PIMap<uint, Client *> index_clients;
PITimer ping_timer;
mutable PIMutex clients_mutex; mutable PIMutex clients_mutex;
}; };

View File

@@ -25,6 +25,7 @@
#include "pip_cloud_export.h" #include "pip_cloud_export.h"
#include "pistring.h" #include "pistring.h"
#include "pimutex.h"
class PIEthernet; class PIEthernet;
@@ -52,6 +53,7 @@ public:
Connect = 1, Connect = 1,
Disconnect = 2, Disconnect = 2,
Data = 3, Data = 3,
Ping = 4,
}; };
TCP(PIStreamPacker * s); TCP(PIStreamPacker * s);
@@ -65,8 +67,9 @@ public:
void sendDisconnected(uint client_id); void sendDisconnected(uint client_id);
int sendData(const PIByteArray & data); int sendData(const PIByteArray & data);
int sendData(const PIByteArray & data, uint client_id); int sendData(const PIByteArray & data, uint client_id);
void sendPing();
PIPair<PICloud::TCP::Type, PICloud::TCP::Role> parseHeader(PIByteArray & ba); PIPair<PICloud::TCP::Type, PICloud::TCP::Role> parseHeader(PIByteArray & ba);
PIByteArray parseData(PIByteArray & ba); bool canParseData(PIByteArray & ba);
PIPair<uint, PIByteArray> parseDataServer(PIByteArray & ba); PIPair<uint, PIByteArray> parseDataServer(PIByteArray & ba);
PIByteArray parseConnect_d(PIByteArray & ba); PIByteArray parseConnect_d(PIByteArray & ba);
uint parseConnect(PIByteArray & ba); uint parseConnect(PIByteArray & ba);
@@ -84,6 +87,8 @@ private:
PIByteArray suuid; PIByteArray suuid;
PIString server_name; PIString server_name;
PIStreamPacker * streampacker; PIStreamPacker * streampacker;
PIMutex mutex_send;
}; };
} }

View File

@@ -37,6 +37,14 @@ int PICodeInfo::EnumInfo::memberValue(const PIString & name_) const {
} }
PIVariantTypes::Enum PICodeInfo::EnumInfo::toPIVariantEnum() {
PIVariantTypes::Enum en(name);
for (auto m: members) en << m.toPIVariantEnumerator();
if (!en.isEmpty()) en.selectValue(members.front().value);
return en;
}
PIMap<PIString, PICodeInfo::ClassInfo * > * PICodeInfo::classesInfo; PIMap<PIString, PICodeInfo::ClassInfo * > * PICodeInfo::classesInfo;
PIMap<PIString, PICodeInfo::EnumInfo * > * PICodeInfo::enumsInfo; PIMap<PIString, PICodeInfo::EnumInfo * > * PICodeInfo::enumsInfo;
PIMap<PIString, PICodeInfo::AccessValueFunction> * PICodeInfo::accessValueFunctions; PIMap<PIString, PICodeInfo::AccessValueFunction> * PICodeInfo::accessValueFunctions;

View File

@@ -25,6 +25,8 @@
#define PICODEINFO_H #define PICODEINFO_H
#include "pistringlist.h" #include "pistringlist.h"
#include "pivarianttypes.h"
class PIVariant; class PIVariant;
@@ -77,6 +79,7 @@ struct PIP_EXPORT ClassInfo {
struct PIP_EXPORT EnumeratorInfo { struct PIP_EXPORT EnumeratorInfo {
EnumeratorInfo(const PIString & n = PIString(), int v = 0) {name = n; value = v;} EnumeratorInfo(const PIString & n = PIString(), int v = 0) {name = n; value = v;}
PIVariantTypes::Enumerator toPIVariantEnumerator() {return PIVariantTypes::Enumerator(value, name);}
MetaMap meta; MetaMap meta;
PIString name; PIString name;
int value; int value;
@@ -85,6 +88,7 @@ struct PIP_EXPORT EnumeratorInfo {
struct PIP_EXPORT EnumInfo { struct PIP_EXPORT EnumInfo {
PIString memberName(int value) const; PIString memberName(int value) const;
int memberValue(const PIString & name) const; int memberValue(const PIString & name) const;
PIVariantTypes::Enum toPIVariantEnum();
MetaMap meta; MetaMap meta;
PIString name; PIString name;
PIVector<PICodeInfo::EnumeratorInfo> members; PIVector<PICodeInfo::EnumeratorInfo> members;

View File

@@ -190,10 +190,39 @@ void PICodeParser::clear() {
piForeachC (PIString & d, defs) piForeachC (PIString & d, defs)
defines << Define(d, ""); defines << Define(d, "");
defines << Define(PIStringAscii("PICODE"), "") << custom_defines; defines << Define(PIStringAscii("PICODE"), "") << custom_defines;
macros << Macro(PIStringAscii("PIOBJECT"), "", PIStringList() << "name")
<< Macro(PIStringAscii("PIOBJECT_PARENT"), "", PIStringList() << "parent")
<< Macro(PIStringAscii("PIOBJECT_SUBCLASS"), "", PIStringList() << "name" << "parent")
<< Macro(PIStringAscii("PIIODEVICE"), "", PIStringList() << "name")
<< Macro(PIStringAscii("NO_COPY_CLASS"), "", PIStringList() << "name")
<< Macro(PIStringAscii("PRIVATE_DECLARATION"))
<< Macro(PIStringAscii("EVENT" ), "void name();", PIStringList() << "name")
<< Macro(PIStringAscii("EVENT0"), "void name();", PIStringList() << "name")
<< Macro(PIStringAscii("EVENT1"), "void name(a0 n0);", PIStringList() << "name" << "a0" << "n0")
<< Macro(PIStringAscii("EVENT2"), "void name(a0 n0, a1 n1);", PIStringList() << "name" << "a0" << "n0" << "a1" << "n1")
<< Macro(PIStringAscii("EVENT3"), "void name(a0 n0, a1 n1, a2 n2);", PIStringList() << "name" << "a0" << "n0" << "a1" << "n1" << "a2" << "n2")
<< Macro(PIStringAscii("EVENT4"), "void name(a0 n0, a1 n1, a2 n2, a3 n3);", PIStringList() << "name" << "a0" << "n0" << "a1" << "n1" << "a2" << "n2" << "a3" << "n3")
<< Macro(PIStringAscii("EVENT_HANDLER" ), "ret name()", PIStringList() << "ret" << "name")
<< Macro(PIStringAscii("EVENT_HANDLER0"), "ret name()", PIStringList() << "ret" << "name")
<< Macro(PIStringAscii("EVENT_HANDLER1"), "ret name(a0 n0)", PIStringList() << "ret" << "name" << "a0" << "n0")
<< Macro(PIStringAscii("EVENT_HANDLER2"), "ret name(a0 n0, a1 n1)", PIStringList() << "ret" << "name" << "a0" << "n0" << "a1" << "n1")
<< Macro(PIStringAscii("EVENT_HANDLER3"), "ret name(a0 n0, a1 n1, a2 n2)", PIStringList() << "ret" << "name" << "a0" << "n0" << "a1" << "n1" << "a2" << "n2")
<< Macro(PIStringAscii("EVENT_HANDLER4"), "ret name(a0 n0, a1 n1, a2 n2, a3 n3)", PIStringList() << "ret" << "name" << "a0" << "n0" << "a1" << "n1" << "a2" << "n2" << "a3" << "n3")
<< Macro(PIStringAscii("EVENT_VHANDLER" ), "virtual ret name()", PIStringList() << "ret" << "name")
<< Macro(PIStringAscii("EVENT_VHANDLER0"), "virtual ret name()", PIStringList() << "ret" << "name")
<< Macro(PIStringAscii("EVENT_VHANDLER1"), "virtual ret name(a0 n0)", PIStringList() << "ret" << "name" << "a0" << "n0")
<< Macro(PIStringAscii("EVENT_VHANDLER2"), "virtual ret name(a0 n0, a1 n1)", PIStringList() << "ret" << "name" << "a0" << "n0" << "a1" << "n1")
<< Macro(PIStringAscii("EVENT_VHANDLER3"), "virtual ret name(a0 n0, a1 n1, a2 n2)", PIStringList() << "ret" << "name" << "a0" << "n0" << "a1" << "n1" << "a2" << "n2")
<< Macro(PIStringAscii("EVENT_VHANDLER4"), "virtual ret name(a0 n0, a1 n1, a2 n2, a3 n3)", PIStringList() << "ret" << "name" << "a0" << "n0" << "a1" << "n1" << "a2" << "n2" << "a3" << "n3")
;
} }
bool PICodeParser::parseFileContent(PIString & fc, bool main) { bool PICodeParser::parseFileContent(PIString & fc, bool main) {
static const PIString s_ns = PIStringAscii("::");
static const PIString s_bo = PIStringAscii("{\n"); static const PIString s_bo = PIStringAscii("{\n");
static const PIString s_bc = PIStringAscii("\n}\n"); static const PIString s_bc = PIStringAscii("\n}\n");
static const PIString s_class = PIStringAscii("class"); static const PIString s_class = PIStringAscii("class");
@@ -280,7 +309,7 @@ bool PICodeParser::parseFileContent(PIString & fc, bool main) {
replaceMeta(pfc); replaceMeta(pfc);
//piCout << NewLine << "file" << cur_file << pfc; //piCout << PICoutManipulators::NewLine << "file" << cur_file << pfc;
int pl = -1; int pl = -1;
while (!pfc.isEmpty()) { while (!pfc.isEmpty()) {
pfc.trim(); pfc.trim();
@@ -288,7 +317,12 @@ bool PICodeParser::parseFileContent(PIString & fc, bool main) {
if (pl == nl) break; if (pl == nl) break;
pl = nl; pl = nl;
if (pfc.left(9) == s_namespace) { if (pfc.left(9) == s_namespace) {
pfc.cutLeft(pfc.find('{') + 1); pfc.cutLeft(9);
PIString prev_namespace = cur_namespace, ccmn;
cur_namespace += pfc.takeCWord() + s_ns;
ccmn = pfc.takeRange('{', '}');
parseClass(0, ccmn);
cur_namespace = prev_namespace;
continue; continue;
} }
if (pfc.left(8) == s_template) { if (pfc.left(8) == s_template) {
@@ -417,7 +451,7 @@ PIString PICodeParser::parseClass(Entity * parent, PIString & fc) {
int ps = -1; int ps = -1;
bool def = false; bool def = false;
PIString prev_namespace = cur_namespace, stmp; PIString prev_namespace = cur_namespace, stmp;
cur_namespace = ce->name + s_ns; cur_namespace += ce->name + s_ns;
//piCout << "parse class" << ce->name << "namespace" << cur_namespace; //piCout << "parse class" << ce->name << "namespace" << cur_namespace;
//piCout << "\nparse class" << ce->name << "namespace" << cur_namespace; //piCout << "\nparse class" << ce->name << "namespace" << cur_namespace;
while (!fc.isEmpty()) { while (!fc.isEmpty()) {
@@ -1074,9 +1108,19 @@ bool PICodeParser::parseDirective(PIString d) {
if (mname == s_PIMETA) return true; if (mname == s_PIMETA) return true;
if (d.left(1) == PIChar('(')) { // macro if (d.left(1) == PIChar('(')) { // macro
PIStringList args = d.takeRange('(', ')').split(',').trim(); PIStringList args = d.takeRange('(', ')').split(',').trim();
for (int i = 0; i < macros.size_s(); ++i)
if (macros[i].name == mname) {
macros.remove(i);
break;
}
macros << Macro(mname, d.trim(), args); macros << Macro(mname, d.trim(), args);
} else { // define } else { // define
d.trim(); d.trim();
for (int i = 0; i < defines.size_s(); ++i)
if (defines[i].first == mname) {
defines.remove(i);
break;
}
defines << Define(mname, d); defines << Define(mname, d);
evaluator.setVariable(mname, complexd_1); evaluator.setVariable(mname, complexd_1);
} }

View File

@@ -21,6 +21,7 @@
#ifndef WINDOWS #ifndef WINDOWS
# include <termios.h> # include <termios.h>
#else #else
# include <wingdi.h>
# include <wincon.h> # include <wincon.h>
#endif #endif

View File

@@ -25,7 +25,7 @@
#include "pithread.h" #include "pithread.h"
#define WAIT_FOR_EXIT while (!PIKbdListener::exiting) piMSleep(PIP_MIN_MSLEEP*5); #define WAIT_FOR_EXIT while (!PIKbdListener::exiting) piMSleep(PIP_MIN_MSLEEP*5); // TODO: rewrite with condvar
class PIP_EXPORT PIKbdListener: public PIThread class PIP_EXPORT PIKbdListener: public PIThread

View File

@@ -53,7 +53,7 @@ public:
PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T)) PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T))
resize(pid_size, f); resize(pid_size, f);
} }
inline PIDeque(size_t piv_size, std::function<T(size_t)> f): pid_data(0), pid_size(0), pid_rsize(0), pid_start(0) { inline PIDeque(size_t piv_size, std::function<T(size_t i)> f): pid_data(0), pid_size(0), pid_rsize(0), pid_start(0) {
PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T)) PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T))
resize(piv_size, f); resize(piv_size, f);
} }
@@ -174,6 +174,20 @@ public:
inline size_t capacity() const {return pid_rsize;} inline size_t capacity() const {return pid_rsize;}
inline size_t _start() const {return pid_start;} inline size_t _start() const {return pid_start;}
inline bool isEmpty() const {return (pid_size == 0);} inline bool isEmpty() const {return (pid_size == 0);}
inline bool isNotEmpty() const {return (pid_size > 0);}
inline bool any(std::function<bool(const T & e)> test) const {
for (ssize_t i = pid_start; i < pid_start + (ssize_t)pid_size; ++i) {
if (test(pid_data[i])) return true;
}
return false;
}
inline bool every(std::function<bool(const T & e)> test) const {
for (ssize_t i = pid_start; i < pid_start + (ssize_t)pid_size; ++i) {
if (!test(pid_data[i])) return false;
}
return true;
}
inline T & operator [](size_t index) {return pid_data[pid_start + index];} inline T & operator [](size_t index) {return pid_data[pid_start + index];}
inline const T & operator [](size_t index) const {return pid_data[pid_start + index];} inline const T & operator [](size_t index) const {return pid_data[pid_start + index];}
@@ -182,48 +196,102 @@ public:
inline const T & back() const {return pid_data[pid_start + pid_size - 1];} inline const T & back() const {return pid_data[pid_start + pid_size - 1];}
inline T & front() {return pid_data[pid_start];} inline T & front() {return pid_data[pid_start];}
inline const T & front() const {return pid_data[pid_start];} inline const T & front() const {return pid_data[pid_start];}
inline bool operator ==(const PIDeque<T> & t) const { inline bool operator ==(const PIDeque<T> & v) const {
if (pid_size != t.pid_size) return false; if (pid_size != v.pid_size) return false;
for (size_t i = 0; i < pid_size; ++i) for (size_t i = 0; i < pid_size; ++i) {
if (t[i] != (*this)[i]) if (v[i] != (*this)[i]) {
return false; return false;
}
}
return true; return true;
} }
inline bool operator !=(const PIDeque<T> & t) const {return !(*this == t);} inline bool operator !=(const PIDeque<T> & v) const {return !(*this == v);}
inline bool operator >(const PIDeque<T> & t) const { inline bool operator <(const PIDeque<T> & v) const {
if (pid_size != t.pid_size) return pid_size > t.pid_size; if (pid_size != v.pid_size) return pid_size < v.pid_size;
for (size_t i = 0; i < pid_size; ++i) for (size_t i = 0; i < pid_size; ++i) {
if (t[i] != (*this)[i]) return t[i] > (*this)[i]; if ((*this)[i] != v[i]) return (*this)[i] < v[i];
}
return false; return false;
} }
inline bool contains(const T & v) const { inline bool operator >(const PIDeque<T> & v) const {
for (size_t i = pid_start; i < pid_start + pid_size; ++i) if (pid_size != v.pid_size) return pid_size > v.pid_size;
if (v == pid_data[i]) for (size_t i = 0; i < pid_size; ++i) {
if ((*this)[i] != v[i]) return (*this)[i] > v[i];
}
return false;
}
inline bool contains(const T & e) const {
for (ssize_t i = pid_start; i < pid_start + (ssize_t)pid_size; ++i) {
if (e == pid_data[i]) {
return true; return true;
}
}
return false; return false;
} }
inline int etries(const T & v) const { inline int etries(const T & e, size_t start = 0) const {
int ec = 0; int ec = 0;
for (size_t i = pid_start; i < pid_start + pid_size; ++i) if (start >= pid_size) return ec;
if (v == pid_data[i]) ++ec; for (ssize_t i = pid_start + start; i < pid_start + (ssize_t)pid_size; ++i) {
if (e == pid_data[i]) ++ec;
}
return ec; return ec;
} }
inline ssize_t indexOf(const T & v) const { inline int etries(std::function<bool(const T & e)> test, size_t start = 0) const {
for (ssize_t i = pid_start; i < pid_start + (ssize_t)pid_size; ++i) int ec = 0;
if (v == pid_data[i]) if (start >= pid_size) return ec;
for (ssize_t i = pid_start + start; i < pid_start + (ssize_t)pid_size; ++i) {
if (test(pid_data[i])) ++ec;
}
return ec;
}
inline ssize_t indexOf(const T & e, size_t start = 0) const {
if (start >= pid_size) return -1;
for (ssize_t i = pid_start + start; i < pid_start + (ssize_t)pid_size; ++i) {
if (e == pid_data[i]) {
return i - pid_start; return i - pid_start;
}
}
return -1; return -1;
} }
inline ssize_t lastIndexOf(const T & v) const { inline ssize_t indexWhere(std::function<bool(const T & e)> test, size_t start = 0) const {
for (ssize_t i = pid_start + (ssize_t)pid_size - 1; i >= pid_start; --i) if (start >= pid_size) return -1;
if (v == pid_data[i]) for (ssize_t i = pid_start + start; i < pid_start + (ssize_t)pid_size; ++i) {
if (test(pid_data[i])) {
return i - pid_start; return i - pid_start;
}
}
return -1;
}
inline ssize_t lastIndexOf(const T & e, ssize_t start = -1) const {
if (start < 0) start = pid_size - 1;
else start = piMin<ssize_t>(pid_size - 1, start);
for (ssize_t i = pid_start + start; i >= pid_start; --i) {
if (e == pid_data[i]) {
return i - pid_start;
}
}
return -1;
}
inline ssize_t lastIndexWhere(std::function<bool(const T & e)> test, ssize_t start = -1) const {
if (start < 0) start = pid_size - 1;
else start = piMin<ssize_t>(pid_size - 1, start);
for (ssize_t i = pid_start + start; i >= pid_start; --i) {
if (test(pid_data[i])) {
return i - pid_start;
}
}
return -1; return -1;
} }
inline T * data(size_t index = 0) {return &(pid_data[pid_start + index]);} inline T * data(size_t index = 0) {return &(pid_data[pid_start + index]);}
inline const T * data(size_t index = 0) const {return &(pid_data[pid_start + index]);} inline const T * data(size_t index = 0) const {return &(pid_data[pid_start + index]);}
PIDeque<T> getRange(size_t index, size_t count) const {
if (index >= pid_size || count == 0) return PIDeque<T>();
if (index + count > pid_size) count = pid_size - index;
return PIDeque(&(pid_data[pid_start + index]), count);
}
template<typename T1 = T, typename std::enable_if< template<typename T1 = T, typename std::enable_if<
!std::is_trivially_copyable<T1>::value !std::is_trivially_copyable<T1>::value
, int>::type = 0> , int>::type = 0>
@@ -244,15 +312,17 @@ public:
inline PIDeque<T> & fill(const T & f = T()) { inline PIDeque<T> & fill(const T & f = T()) {
deleteT(pid_data + pid_start, pid_size); deleteT(pid_data + pid_start, pid_size);
PIINTROSPECTION_CONTAINER_USED(T, pid_size) PIINTROSPECTION_CONTAINER_USED(T, pid_size)
for (size_t i = pid_start; i < pid_start + pid_size; ++i) for (size_t i = pid_start; i < pid_start + pid_size; ++i) {
elementNew(pid_data + i, f); elementNew(pid_data + i, f);
}
return *this; return *this;
} }
inline PIDeque<T> & fill(std::function<T(size_t)> f) { inline PIDeque<T> & fill(std::function<T(size_t i)> f) {
deleteT(pid_data + pid_start, pid_size); deleteT(pid_data + pid_start, pid_size);
PIINTROSPECTION_CONTAINER_USED(T, pid_size) PIINTROSPECTION_CONTAINER_USED(T, pid_size)
for (size_t i = pid_start; i < pid_start + pid_size; ++i) for (size_t i = pid_start; i < pid_start + pid_size; ++i) {
elementNew(pid_data + i, f(i)); elementNew(pid_data + i, f(i));
}
return *this; return *this;
} }
inline PIDeque<T> & assign(const T & f = T()) {return fill(f);} inline PIDeque<T> & assign(const T & f = T()) {return fill(f);}
@@ -275,32 +345,36 @@ public:
if (new_size < pid_size) { if (new_size < pid_size) {
deleteT(&(pid_data[new_size + pid_start]), pid_size - new_size); deleteT(&(pid_data[new_size + pid_start]), pid_size - new_size);
pid_size = new_size; pid_size = new_size;
if (new_size == 0) if (new_size == 0) {
pid_start = (pid_rsize - pid_size) / 2; pid_start = (pid_rsize - pid_size) / 2;
} }
}
if (new_size > pid_size) { if (new_size > pid_size) {
size_t os = pid_size; size_t os = pid_size;
alloc(new_size, true); alloc(new_size, true);
PIINTROSPECTION_CONTAINER_USED(T, (new_size-os)) PIINTROSPECTION_CONTAINER_USED(T, (new_size-os))
for (size_t i = os + pid_start; i < new_size + pid_start; ++i) for (size_t i = os + pid_start; i < new_size + pid_start; ++i) {
elementNew(pid_data + i, f); elementNew(pid_data + i, f);
} }
}
return *this; return *this;
} }
inline PIDeque<T> & resize(size_t new_size, std::function<T(size_t)> f) { inline PIDeque<T> & resize(size_t new_size, std::function<T(size_t i)> f) {
if (new_size < pid_size) { if (new_size < pid_size) {
deleteT(&(pid_data[new_size + pid_start]), pid_size - new_size); deleteT(&(pid_data[new_size + pid_start]), pid_size - new_size);
pid_size = new_size; pid_size = new_size;
if (new_size == 0) if (new_size == 0) {
pid_start = (pid_rsize - pid_size) / 2; pid_start = (pid_rsize - pid_size) / 2;
} }
}
if (new_size > pid_size) { if (new_size > pid_size) {
size_t os = pid_size; size_t os = pid_size;
alloc(new_size, true); alloc(new_size, true);
PIINTROSPECTION_CONTAINER_USED(T, (new_size-os)) PIINTROSPECTION_CONTAINER_USED(T, (new_size-os))
for (size_t i = os + pid_start; i < new_size + pid_start; ++i) for (size_t i = os + pid_start; i < new_size + pid_start; ++i) {
elementNew(pid_data + i, f(i)); elementNew(pid_data + i, f(i));
} }
}
return *this; return *this;
} }
@@ -326,8 +400,8 @@ public:
return *this; return *this;
} }
inline PIDeque<T> & insert(size_t index, const T & v = T()) { inline PIDeque<T> & insert(size_t index, const T & e = T()) {
if (index == pid_size) return push_back(v); if (index == pid_size) return push_back(e);
PIINTROSPECTION_CONTAINER_USED(T, 1) PIINTROSPECTION_CONTAINER_USED(T, 1)
bool dir = pid_rsize <= 2 ? true : (index >= pid_rsize / 2 ? true : false); bool dir = pid_rsize <= 2 ? true : (index >= pid_rsize / 2 ? true : false);
if (dir) { if (dir) {
@@ -338,14 +412,15 @@ public:
} }
} else { } else {
alloc(pid_size + 1, false, -1); alloc(pid_size + 1, false, -1);
if (index > 0) if (index > 0) {
memmove((void*)(&(pid_data[pid_start])), (const void*)(&(pid_data[pid_start + 1])), index * sizeof(T)); memmove((void*)(&(pid_data[pid_start])), (const void*)(&(pid_data[pid_start + 1])), index * sizeof(T));
} }
elementNew(pid_data + pid_start + index, v); }
elementNew(pid_data + pid_start + index, e);
return *this; return *this;
} }
inline PIDeque<T> & insert(size_t index, T && v) { inline PIDeque<T> & insert(size_t index, T && e) {
if (index == pid_size) return push_back(v); if (index == pid_size) return push_back(e);
PIINTROSPECTION_CONTAINER_USED(T, 1) PIINTROSPECTION_CONTAINER_USED(T, 1)
bool dir = pid_rsize <= 2 ? true : (index >= pid_rsize / 2 ? true : false); bool dir = pid_rsize <= 2 ? true : (index >= pid_rsize / 2 ? true : false);
if (dir) { if (dir) {
@@ -356,10 +431,11 @@ public:
} }
} else { } else {
alloc(pid_size + 1, false, -1); alloc(pid_size + 1, false, -1);
if (index > 0) if (index > 0) {
memmove((void*)(&(pid_data[pid_start])), (const void*)(&(pid_data[pid_start + 1])), index * sizeof(T)); memmove((void*)(&(pid_data[pid_start])), (const void*)(&(pid_data[pid_start + 1])), index * sizeof(T));
} }
elementNew(pid_data + pid_start + index, std::move(v)); }
elementNew(pid_data + pid_start + index, std::move(e));
return *this; return *this;
} }
inline PIDeque<T> & insert(size_t index, const PIDeque<T> & other) { inline PIDeque<T> & insert(size_t index, const PIDeque<T> & other) {
@@ -369,13 +445,15 @@ public:
if (dir) { if (dir) {
ssize_t os = pid_size - index; ssize_t os = pid_size - index;
alloc(pid_size + other.pid_size, true); alloc(pid_size + other.pid_size, true);
if (os > 0) if (os > 0) {
memmove((void*)(&(pid_data[index + pid_start + other.pid_size])), (const void*)(&(pid_data[index + pid_start])), os * sizeof(T)); memmove((void*)(&(pid_data[index + pid_start + other.pid_size])), (const void*)(&(pid_data[index + pid_start])), os * sizeof(T));
}
} else { } else {
alloc(pid_size + other.pid_size, false, -other.pid_size); alloc(pid_size + other.pid_size, false, -other.pid_size);
if (index > 0) if (index > 0) {
memmove((void*)(&(pid_data[pid_start])), (const void*)(&(pid_data[pid_start + other.pid_size])), index * sizeof(T)); memmove((void*)(&(pid_data[pid_start])), (const void*)(&(pid_data[pid_start + other.pid_size])), index * sizeof(T));
} }
}
newT(pid_data + pid_start + index, other.pid_data + other.pid_start, other.pid_size); newT(pid_data + pid_start + index, other.pid_data + other.pid_start, other.pid_size);
return *this; return *this;
} }
@@ -389,9 +467,13 @@ public:
size_t os = pid_size - index - count; size_t os = pid_size - index - count;
deleteT(&(pid_data[index + pid_start]), count); deleteT(&(pid_data[index + pid_start]), count);
if (os <= index) { if (os <= index) {
if (os > 0) memmove((void*)(&(pid_data[index + pid_start])), (const void*)(&(pid_data[index + pid_start + count])), os * sizeof(T)); if (os > 0) {
memmove((void*)(&(pid_data[index + pid_start])), (const void*)(&(pid_data[index + pid_start + count])), os * sizeof(T));
}
} else { } else {
if (index > 0) memmove((void*)(&(pid_data[pid_start + count])), (const void*)(&(pid_data[pid_start])), index * sizeof(T)); if (index > 0) {
memmove((void*)(&(pid_data[pid_start + count])), (const void*)(&(pid_data[pid_start])), index * sizeof(T));
}
pid_start += count; pid_start += count;
} }
pid_size -= count; pid_size -= count;
@@ -419,88 +501,114 @@ public:
return *this; return *this;
} }
inline PIDeque<T> & removeOne(const T & v) { inline PIDeque<T> & removeOne(const T & e) {
for (size_t i = 0; i < pid_size; ++i) for (size_t i = 0; i < pid_size; ++i) {
if (pid_data[i + pid_start] == v) { if (pid_data[i + pid_start] == e) {
remove(i); remove(i);
return *this; return *this;
} }
}
return *this; return *this;
} }
inline PIDeque<T> & removeAll(const T & v) { inline PIDeque<T> & removeAll(const T & e) {
for (ssize_t i = 0; i < ssize_t(pid_size); ++i) for (ssize_t i = 0; i < ssize_t(pid_size); ++i) {
if (pid_data[i + pid_start] == v) { if (pid_data[i + pid_start] == e) {
remove(i); remove(i);
--i; --i;
} }
}
return *this;
}
inline PIDeque<T> & removeWhere(std::function<bool(const T & e)> test) {
for (ssize_t i = 0; i < ssize_t(pid_size); ++i) {
if (test(pid_data[i + pid_start])) {
remove(i);
--i;
}
}
return *this; return *this;
} }
inline PIDeque<T> & push_back(const T & v) { inline PIDeque<T> & push_back(const T & e) {
alloc(pid_size + 1, true); alloc(pid_size + 1, true);
PIINTROSPECTION_CONTAINER_USED(T, 1); PIINTROSPECTION_CONTAINER_USED(T, 1);
elementNew(pid_data + pid_start + pid_size - 1, v); elementNew(pid_data + pid_start + pid_size - 1, e);
return *this; return *this;
} }
inline PIDeque<T> & push_back(T && v) { inline PIDeque<T> & push_back(T && e) {
alloc(pid_size + 1, true); alloc(pid_size + 1, true);
PIINTROSPECTION_CONTAINER_USED(T, 1); PIINTROSPECTION_CONTAINER_USED(T, 1);
elementNew(pid_data + pid_start + pid_size - 1, std::move(v)); elementNew(pid_data + pid_start + pid_size - 1, std::move(e));
return *this; return *this;
} }
inline PIDeque<T> & append(const T & v) {return push_back(v);} inline PIDeque<T> & append(const T & e) {return push_back(e);}
inline PIDeque<T> & append(T && v) {return push_back(std::move(v));} inline PIDeque<T> & append(T && e) {return push_back(std::move(e));}
inline PIDeque<T> & append(const PIDeque<T> & t) { inline PIDeque<T> & append(const PIDeque<T> & v) {
assert(&t != this); assert(&v != this);
size_t ps = pid_size; size_t ps = pid_size;
alloc(pid_size + t.pid_size, true); alloc(pid_size + v.pid_size, true);
newT(pid_data + ps + pid_start, t.pid_data + t.pid_start, t.pid_size); newT(pid_data + ps + pid_start, v.pid_data + v.pid_start, v.pid_size);
return *this; return *this;
} }
inline PIDeque<T> & operator <<(const T & v) {return push_back(v);} inline PIDeque<T> & operator <<(const T & e) {return push_back(e);}
inline PIDeque<T> & operator <<(T && v) {return push_back(std::move(v));} inline PIDeque<T> & operator <<(T && e) {return push_back(std::move(e));}
inline PIDeque<T> & operator <<(const PIDeque<T> & t) {return append(t);} inline PIDeque<T> & operator <<(const PIDeque<T> & v) {return append(v);}
inline PIDeque<T> & push_front(const T & v) {insert(0, v); return *this;} inline PIDeque<T> & push_front(const T & e) {insert(0, e); return *this;}
inline PIDeque<T> & push_front(T && v) {insert(0, std::move(v)); return *this;} inline PIDeque<T> & push_front(T && e) {insert(0, std::move(e)); return *this;}
inline PIDeque<T> & prepend(const T & v) {return push_front(v);} inline PIDeque<T> & prepend(const T & e) {return push_front(e);}
inline PIDeque<T> & prepend(T && v) {return push_front(std::move(v));} inline PIDeque<T> & prepend(T && e) {return push_front(std::move(e));}
inline PIDeque<T> & pop_back() {if (pid_size == 0) return *this; resize(pid_size - 1); return *this;} inline PIDeque<T> & pop_back() {if (pid_size == 0) return *this; resize(pid_size - 1); return *this;}
inline PIDeque<T> & pop_front() {if (pid_size == 0) return *this; remove(0); return *this;} inline PIDeque<T> & pop_front() {if (pid_size == 0) return *this; remove(0); return *this;}
inline T take_back() {T t(back()); pop_back(); return t;} inline T take_back() {T e(back()); pop_back(); return e;}
inline T take_front() {T t(front()); pop_front(); return t;} inline T take_front() {T e(front()); pop_front(); return e;}
template <typename ST> template <typename ST>
PIDeque<ST> toType() const { PIDeque<ST> toType() const {
PIDeque<ST> ret(pid_size); PIDeque<ST> ret(pid_size);
for (uint i = 0; i < pid_size; ++i) for (size_t i = 0; i < pid_size; ++i) {
ret[i] = ST(pid_data[i + pid_start]); ret[i] = ST(pid_data[i + pid_start]);
}
return ret; return ret;
} }
const PIDeque<T> & forEach(std::function<void(const T &)> f) const { const PIDeque<T> & forEach(std::function<void(const T & e)> f) const {
for (uint i = 0; i < pid_size; ++i) for (size_t i = 0; i < pid_size; ++i) {
f(pid_data[i + pid_start]); f(pid_data[i + pid_start]);
}
return *this; return *this;
} }
PIDeque<T> copyForEach(std::function<T(const T &)> f) const { PIDeque<T> copyForEach(std::function<T(const T & e)> f) const {
PIDeque<T> ret; ret.reserve(pid_size); PIDeque<T> ret; ret.reserve(pid_size);
for (uint i = 0; i < pid_size; ++i) for (size_t i = 0; i < pid_size; ++i) {
ret << f(pid_data[i + pid_start]); ret << f(pid_data[i + pid_start]);
}
return ret; return ret;
} }
PIDeque<T> & forEachInplace(std::function<T(const T &)> f) { PIDeque<T> & forEachInplace(std::function<T(const T & e)> f) {
for (uint i = 0; i < pid_size; ++i) for (size_t i = 0; i < pid_size; ++i)
pid_data[i + pid_start] = f(pid_data[i + pid_start]); pid_data[i + pid_start] = f(pid_data[i + pid_start]);
return *this; return *this;
} }
template <typename ST> template <typename ST>
PIDeque<ST> toType(std::function<ST(const T &)> f) const { PIDeque<ST> map(std::function<ST(const T & e)> f) const {
PIDeque<ST> ret; ret.reserve(pid_size); PIDeque<ST> ret; ret.reserve(pid_size);
for (uint i = 0; i < pid_size; ++i) for (size_t i = 0; i < pid_size; ++i) {
ret << f(pid_data[i + pid_start]); ret << f(pid_data[i + pid_start]);
}
return ret;
}
template <typename ST>
PIDeque<ST> toType(std::function<ST(const T & e)> f) const {return map(f);}
template <typename ST>
ST reduce(std::function<ST(const T & e, const ST & acc)> f, const ST & initial = ST()) const {
ST ret(initial);
for (size_t i = 0; i < pid_size; ++i) {
ret = f(pid_data[i + pid_start], ret);
}
return ret; return ret;
} }
@@ -510,16 +618,18 @@ public:
assert(rows*cols == pid_size); assert(rows*cols == pid_size);
ret.resize(rows); ret.resize(rows);
if (order == byRow) { if (order == byRow) {
for (size_t r = 0; r < rows; r++) for (size_t r = 0; r < rows; r++) {
ret[r] = PIDeque<T>(&(pid_data[r*cols]), cols); ret[r] = PIDeque<T>(&(pid_data[r*cols]), cols);
} }
}
if (order == byColumn) { if (order == byColumn) {
for (size_t r = 0; r < rows; r++) { for (size_t r = 0; r < rows; r++) {
ret[r].resize(cols); ret[r].resize(cols);
for (size_t c = 0; c < cols; c++) for (size_t c = 0; c < cols; c++) {
ret[r][c] = pid_data[c*rows + r]; ret[r][c] = pid_data[c*rows + r];
} }
} }
}
return ret; return ret;
} }
@@ -533,14 +643,17 @@ public:
size_t cols = at(0).size(); size_t cols = at(0).size();
ret.reserve(rows * cols); ret.reserve(rows * cols);
if (order == byRow) { if (order == byRow) {
for (size_t r = 0; r < rows; r++) for (size_t r = 0; r < rows; r++) {
ret.append(at(r)); ret.append(at(r));
} }
}
if (order == byColumn) { if (order == byColumn) {
for (size_t c = 0; c < cols; c++) for (size_t c = 0; c < cols; c++) {
for (size_t r = 0; r < rows; r++) for (size_t r = 0; r < rows; r++) {
ret << at(r)[c]; ret << at(r)[c];
} }
}
}
ret.resize(rows * cols); ret.resize(rows * cols);
return ret; return ret;
} }
@@ -549,11 +662,13 @@ private:
inline void _reset() {pid_size = pid_rsize = pid_start = 0; pid_data = 0;} inline void _reset() {pid_size = pid_rsize = pid_start = 0; pid_data = 0;}
inline size_t asize(ssize_t s) { inline size_t asize(ssize_t s) {
if (s <= 0) return 0; if (s <= 0) return 0;
if (pid_rsize + pid_rsize >= size_t(s) && pid_rsize < size_t(s)) if (pid_rsize + pid_rsize >= size_t(s) && pid_rsize < size_t(s)) {
return pid_rsize + pid_rsize; return pid_rsize + pid_rsize;
}
ssize_t t = 0, s_ = s - 1; ssize_t t = 0, s_ = s - 1;
while (s_ >> t) while (s_ >> t) {
++t; ++t;
}
return (1 << t); return (1 << t);
} }
template<typename T1 = T, typename std::enable_if< template<typename T1 = T, typename std::enable_if<
@@ -577,10 +692,11 @@ private:
inline void deleteT(T * d, size_t sz) { inline void deleteT(T * d, size_t sz) {
PIINTROSPECTION_CONTAINER_UNUSED(T, sz) PIINTROSPECTION_CONTAINER_UNUSED(T, sz)
if ((uchar*)d != 0) { if ((uchar*)d != 0) {
for (size_t i = 0; i < sz; ++i) for (size_t i = 0; i < sz; ++i) {
elementDelete(d[i]); elementDelete(d[i]);
} }
} }
}
template<typename T1 = T, typename std::enable_if< template<typename T1 = T, typename std::enable_if<
std::is_trivially_copyable<T1>::value std::is_trivially_copyable<T1>::value
, int>::type = 0> , int>::type = 0>
@@ -652,10 +768,11 @@ private:
} }
} else { } else {
size_t as; size_t as;
if (pid_start + start_offset < 0) if (pid_start + start_offset < 0) {
as = asize(pid_rsize - start_offset); as = asize(pid_rsize - start_offset);
else as = pid_rsize; } else {
as = pid_rsize;
}
if (as > pid_rsize) { if (as > pid_rsize) {
T * td = (T*)(malloc(as * sizeof(T))); T * td = (T*)(malloc(as * sizeof(T)));
ssize_t ns = pid_start + as - pid_rsize; ssize_t ns = pid_start + as - pid_rsize;
@@ -682,7 +799,15 @@ private:
#ifdef PIP_STD_IOSTREAM #ifdef PIP_STD_IOSTREAM
template<typename T> template<typename T>
inline std::ostream & operator <<(std::ostream & s, const PIDeque<T> & v) {s << "{"; for (size_t i = 0; i < v.size(); ++i) {s << v[i]; if (i < v.size() - 1) s << ", ";} s << "}"; return s;} inline std::ostream & operator <<(std::ostream & s, const PIDeque<T> & v) {
s << "{";
for (size_t i = 0; i < v.size(); ++i) {
s << v[i];
if (i < v.size() - 1) s << ", ";
}
s << "}";
return s;
}
#endif #endif
template<typename T> template<typename T>
@@ -692,8 +817,7 @@ inline PICout operator <<(PICout s, const PIDeque<T> & v) {
s << "{"; s << "{";
for (size_t i = 0; i < v.size(); ++i) { for (size_t i = 0; i < v.size(); ++i) {
s << v[i]; s << v[i];
if (i < v.size() - 1) if (i < v.size() - 1) s << ", ";
s << ", ";
} }
s << "}"; s << "}";
s.restoreControl(); s.restoreControl();

View File

@@ -107,6 +107,7 @@ public:
iterator(): parent(0), pos(0) {} iterator(): parent(0), pos(0) {}
const Key & key() const {return const_cast<PIMap<Key, T> * >(parent)->_key(pos);} const Key & key() const {return const_cast<PIMap<Key, T> * >(parent)->_key(pos);}
T & value() {return const_cast<PIMap<Key, T> * >(parent)->_value(pos);} T & value() {return const_cast<PIMap<Key, T> * >(parent)->_value(pos);}
inline PIPair<Key, T> operator *() const {return PIPair<Key, T>(const_cast<PIMap<Key, T> * >(parent)->_key(pos), const_cast<PIMap<Key, T> * >(parent)->_value(pos));}
void operator ++() {++pos;} void operator ++() {++pos;}
void operator ++(int) {++pos;} void operator ++(int) {++pos;}
void operator --() {--pos;} void operator --() {--pos;}
@@ -125,6 +126,7 @@ public:
reverse_iterator(): parent(0), pos(0) {} reverse_iterator(): parent(0), pos(0) {}
const Key & key() const {return const_cast<PIMap<Key, T> * >(parent)->_key(pos);} const Key & key() const {return const_cast<PIMap<Key, T> * >(parent)->_key(pos);}
T & value() const {return const_cast<PIMap<Key, T> * >(parent)->_value(pos);} T & value() const {return const_cast<PIMap<Key, T> * >(parent)->_value(pos);}
inline PIPair<Key, T> operator *() const {return PIPair<Key, T>(const_cast<PIMap<Key, T> * >(parent)->_key(pos), const_cast<PIMap<Key, T> * >(parent)->_value(pos));}
void operator ++() {--pos;} void operator ++() {--pos;}
void operator ++(int) {--pos;} void operator ++(int) {--pos;}
void operator --() {++pos;} void operator --() {++pos;}

View File

@@ -33,6 +33,7 @@ template<typename Type0, typename Type1>
class PIPair { class PIPair {
public: public:
PIPair() {first = Type0(); second = Type1();} PIPair() {first = Type0(); second = Type1();}
PIPair(std::tuple<Type0, Type1> tuple) {first = std::get<0>(tuple); second = std::get<1>(tuple);}
PIPair(const Type0 & value0, const Type1 & value1) {first = value0; second = value1;} PIPair(const Type0 & value0, const Type1 & value1) {first = value0; second = value1;}
Type0 first; Type0 first;
Type1 second; Type1 second;

View File

@@ -39,10 +39,10 @@ public:
alloc(size); alloc(size);
newT(piv_data, data, piv_size); newT(piv_data, data, piv_size);
} }
inline PIVector(const PIVector<T> & other): piv_data(0), piv_size(0), piv_rsize(0) { inline PIVector(const PIVector<T> & v): piv_data(0), piv_size(0), piv_rsize(0) {
PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T)) PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T))
alloc(other.piv_size); alloc(v.piv_size);
newT(piv_data, other.piv_data, piv_size); newT(piv_data, v.piv_data, piv_size);
} }
inline PIVector(std::initializer_list<T> init_list): piv_data(0), piv_size(0), piv_rsize(0) { inline PIVector(std::initializer_list<T> init_list): piv_data(0), piv_size(0), piv_rsize(0) {
PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T)) PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T))
@@ -53,13 +53,13 @@ public:
PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T)) PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T))
resize(piv_size, f); resize(piv_size, f);
} }
inline PIVector(size_t piv_size, std::function<T(size_t)> f): piv_data(0), piv_size(0), piv_rsize(0) { inline PIVector(size_t piv_size, std::function<T(size_t i)> f): piv_data(0), piv_size(0), piv_rsize(0) {
PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T)) PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T))
resize(piv_size, f); resize(piv_size, f);
} }
inline PIVector(PIVector<T> && other): piv_data(other.piv_data), piv_size(other.piv_size), piv_rsize(other.piv_rsize) { inline PIVector(PIVector<T> && v): piv_data(v.piv_data), piv_size(v.piv_size), piv_rsize(v.piv_rsize) {
PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T)) PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T))
other._reset(); v._reset();
} }
inline virtual ~PIVector() { inline virtual ~PIVector() {
PIINTROSPECTION_CONTAINER_DELETE(T) PIINTROSPECTION_CONTAINER_DELETE(T)
@@ -69,17 +69,17 @@ public:
_reset(); _reset();
} }
inline PIVector<T> & operator =(const PIVector<T> & other) { inline PIVector<T> & operator =(const PIVector<T> & v) {
if (this == &other) return *this; if (this == &v) return *this;
clear(); clear();
deleteT(piv_data, piv_size); deleteT(piv_data, piv_size);
alloc(other.piv_size); alloc(v.piv_size);
newT(piv_data, other.piv_data, piv_size); newT(piv_data, v.piv_data, piv_size);
return *this; return *this;
} }
inline PIVector<T> & operator =(PIVector<T> && other) { inline PIVector<T> & operator =(PIVector<T> && v) {
swap(other); swap(v);
return *this; return *this;
} }
@@ -174,6 +174,19 @@ public:
inline size_t length() const {return piv_size;} inline size_t length() const {return piv_size;}
inline size_t capacity() const {return piv_rsize;} inline size_t capacity() const {return piv_rsize;}
inline bool isEmpty() const {return (piv_size == 0);} inline bool isEmpty() const {return (piv_size == 0);}
inline bool isNotEmpty() const {return (piv_size > 0);}
inline bool any(std::function<bool(const T & e)> test) const {
for (size_t i = 0; i < piv_size; ++i) {
if (test(piv_data[i])) return true;
}
return false;
}
inline bool every(std::function<bool(const T & e)> test) const {
for (size_t i = 0; i < piv_size; ++i) {
if (!test(piv_data[i])) return false;
}
return true;
}
inline T & operator [](size_t index) {return piv_data[index];} inline T & operator [](size_t index) {return piv_data[index];}
inline const T & operator [](size_t index) const {return piv_data[index];} inline const T & operator [](size_t index) const {return piv_data[index];}
@@ -183,42 +196,103 @@ public:
inline T & front() {return piv_data[0];} inline T & front() {return piv_data[0];}
inline const T & front() const {return piv_data[0];} inline const T & front() const {return piv_data[0];}
inline bool operator ==(const PIVector<T> & t) const { inline bool operator ==(const PIVector<T> & t) const {
if (piv_size != t.piv_size) if (piv_size != t.piv_size) {
return false; return false;
for (size_t i = 0; i < piv_size; ++i) }
if (t[i] != piv_data[i]) for (size_t i = 0; i < piv_size; ++i) {
if (t[i] != piv_data[i]) {
return false; return false;
}
}
return true; return true;
} }
inline bool operator !=(const PIVector<T> & t) const {return !(*this == t);} inline bool operator !=(const PIVector<T> & t) const {return !(*this == t);}
inline bool contains(const T & v) const { inline bool operator <(const PIVector<T> & t) const {
for (size_t i = 0; i < piv_size; ++i) if (piv_size != t.piv_size) return piv_size < t.piv_size;
if (v == piv_data[i]) for (size_t i = 0; i < piv_size; ++i) {
return true; if ((*this)[i] != t[i]) return (*this)[i] < t[i];
}
return false; return false;
} }
inline int etries(const T & v) const { inline bool operator >(const PIVector<T> & t) const {
if (piv_size != t.piv_size) return piv_size > t.piv_size;
for (size_t i = 0; i < piv_size; ++i) {
if ((*this)[i] != t[i]) return (*this)[i] > t[i];
}
return false;
}
inline bool contains(const T & e) const {
for (size_t i = 0; i < piv_size; ++i) {
if (e == piv_data[i]) {
return true;
}
}
return false;
}
inline int etries(const T & e, size_t start = 0) const {
int ec = 0; int ec = 0;
for (size_t i = 0; i < piv_size; ++i) if (start >= piv_size) return ec;
if (v == piv_data[i]) ++ec; for (size_t i = start; i < piv_size; ++i) {
if (e == piv_data[i]) ++ec;
}
return ec; return ec;
} }
inline ssize_t indexOf(const T & v) const { inline int etries(std::function<bool(const T & e)> test, size_t start = 0) const {
for (size_t i = 0; i < piv_size; ++i) int ec = 0;
if (v == piv_data[i]) if (start >= piv_size) return ec;
for (size_t i = start; i < piv_size; ++i) {
if (test(piv_data[i])) ++ec;
}
return ec;
}
inline ssize_t indexOf(const T & e, size_t start = 0) const {
if (start >= piv_size) return -1;
for (size_t i = start; i < piv_size; ++i) {
if (e == piv_data[i]) {
return i; return i;
}
}
return -1; return -1;
} }
inline ssize_t lastIndexOf(const T & v) const { inline ssize_t indexWhere(std::function<bool(const T & e)> test, size_t start = 0) const {
for (ssize_t i = piv_size - 1; i >= 0; --i) if (start >= piv_size) return -1;
if (v == piv_data[i]) for (size_t i = start; i < piv_size; ++i) {
if (test(piv_data[i])) {
return i; return i;
}
}
return -1;
}
inline ssize_t lastIndexOf(const T & e, ssize_t start = -1) const {
if (start < 0) start = piv_size - 1;
else start = piMin<ssize_t>(piv_size - 1, start);
for (ssize_t i = start; i >= 0; --i) {
if (e == piv_data[i]) {
return i;
}
}
return -1;
}
inline ssize_t lastIndexWhere(std::function<bool(const T & e)> test, ssize_t start = -1) const {
if (start < 0) start = piv_size - 1;
else start = piMin<ssize_t>(piv_size - 1, start);
for (ssize_t i = start; i >= 0; --i) {
if (test(piv_data[i])) {
return i;
}
}
return -1; return -1;
} }
inline T * data(size_t index = 0) {return &(piv_data[index]);} inline T * data(size_t index = 0) {return &(piv_data[index]);}
inline const T * data(size_t index = 0) const {return &(piv_data[index]);} inline const T * data(size_t index = 0) const {return &(piv_data[index]);}
PIVector<T> getRange(size_t index, size_t count) const {
if (index >= piv_size || count == 0) return PIVector<T>();
if (index + count > piv_size) count = piv_size - index;
return PIVector(&(piv_data[index]), count);
}
template<typename T1 = T, typename std::enable_if< template<typename T1 = T, typename std::enable_if<
!std::is_trivially_copyable<T1>::value !std::is_trivially_copyable<T1>::value
, int>::type = 0> , int>::type = 0>
@@ -238,15 +312,17 @@ public:
inline PIVector<T> & fill(const T & f = T()) { inline PIVector<T> & fill(const T & f = T()) {
deleteT(piv_data, piv_size); deleteT(piv_data, piv_size);
PIINTROSPECTION_CONTAINER_USED(T, piv_size) PIINTROSPECTION_CONTAINER_USED(T, piv_size)
for (size_t i = 0; i < piv_size; ++i) for (size_t i = 0; i < piv_size; ++i) {
elementNew(piv_data + i, f); elementNew(piv_data + i, f);
}
return *this; return *this;
} }
inline PIVector<T> & fill(std::function<T(size_t)> f) { inline PIVector<T> & fill(std::function<T(size_t i)> f) {
deleteT(piv_data, piv_size); deleteT(piv_data, piv_size);
PIINTROSPECTION_CONTAINER_USED(T, piv_size) PIINTROSPECTION_CONTAINER_USED(T, piv_size)
for (size_t i = 0; i < piv_size; ++i) for (size_t i = 0; i < piv_size; ++i) {
elementNew(piv_data + i, f(i)); elementNew(piv_data + i, f(i));
}
return *this; return *this;
} }
inline PIVector<T> & assign(const T & f = T()) {return fill(f);} inline PIVector<T> & assign(const T & f = T()) {return fill(f);}
@@ -275,12 +351,13 @@ public:
size_t os = piv_size; size_t os = piv_size;
alloc(new_size); alloc(new_size);
PIINTROSPECTION_CONTAINER_USED(T, (new_size-os)) PIINTROSPECTION_CONTAINER_USED(T, (new_size-os))
for (size_t i = os; i < new_size; ++i) for (size_t i = os; i < new_size; ++i) {
elementNew(piv_data + i, f); elementNew(piv_data + i, f);
} }
}
return *this; return *this;
} }
inline PIVector<T> & resize(size_t new_size, std::function<T(size_t)> f) { inline PIVector<T> & resize(size_t new_size, std::function<T(size_t i)> f) {
if (new_size < piv_size) { if (new_size < piv_size) {
T * de = &(piv_data[new_size]); T * de = &(piv_data[new_size]);
deleteT(de, piv_size - new_size); deleteT(de, piv_size - new_size);
@@ -290,9 +367,10 @@ public:
size_t os = piv_size; size_t os = piv_size;
alloc(new_size); alloc(new_size);
PIINTROSPECTION_CONTAINER_USED(T, (new_size-os)) PIINTROSPECTION_CONTAINER_USED(T, (new_size-os))
for (size_t i = os; i < new_size; ++i) for (size_t i = os; i < new_size; ++i) {
elementNew(piv_data + i, f(i)); elementNew(piv_data + i, f(i));
} }
}
return *this; return *this;
} }
template<typename T1 = T, typename std::enable_if< template<typename T1 = T, typename std::enable_if<
@@ -320,34 +398,35 @@ public:
return *this; return *this;
} }
inline PIVector<T> & insert(size_t index, const T & v = T()) { inline PIVector<T> & insert(size_t index, const T & e = T()) {
alloc(piv_size + 1); alloc(piv_size + 1);
if (index < piv_size - 1) { if (index < piv_size - 1) {
size_t os = piv_size - index - 1; size_t os = piv_size - index - 1;
memmove((void*)(&(piv_data[index + 1])), (const void*)(&(piv_data[index])), os * sizeof(T)); memmove((void*)(&(piv_data[index + 1])), (const void*)(&(piv_data[index])), os * sizeof(T));
} }
PIINTROSPECTION_CONTAINER_USED(T, 1) PIINTROSPECTION_CONTAINER_USED(T, 1)
elementNew(piv_data + index, v); elementNew(piv_data + index, e);
return *this; return *this;
} }
inline PIVector<T> & insert(size_t index, T && v) { inline PIVector<T> & insert(size_t index, T && e) {
alloc(piv_size + 1); alloc(piv_size + 1);
if (index < piv_size - 1) { if (index < piv_size - 1) {
size_t os = piv_size - index - 1; size_t os = piv_size - index - 1;
memmove((void*)(&(piv_data[index + 1])), (const void*)(&(piv_data[index])), os * sizeof(T)); memmove((void*)(&(piv_data[index + 1])), (const void*)(&(piv_data[index])), os * sizeof(T));
} }
PIINTROSPECTION_CONTAINER_USED(T, 1) PIINTROSPECTION_CONTAINER_USED(T, 1)
elementNew(piv_data + index, std::move(v)); elementNew(piv_data + index, std::move(e));
return *this; return *this;
} }
inline PIVector<T> & insert(size_t index, const PIVector<T> & other) { inline PIVector<T> & insert(size_t index, const PIVector<T> & v) {
if (other.isEmpty()) return *this; if (v.isEmpty()) return *this;
assert(&other != this); assert(&v != this);
ssize_t os = piv_size - index; ssize_t os = piv_size - index;
alloc(piv_size + other.piv_size); alloc(piv_size + v.piv_size);
if (os > 0) if (os > 0) {
memmove((void*)(&(piv_data[index + other.piv_size])), (const void*)(&(piv_data[index])), os * sizeof(T)); memmove((void*)(&(piv_data[index + v.piv_size])), (const void*)(&(piv_data[index])), os * sizeof(T));
newT(piv_data + index, other.piv_data, other.piv_size); }
newT(piv_data + index, v.piv_data, v.piv_size);
return *this; return *this;
} }
@@ -364,10 +443,10 @@ public:
return *this; return *this;
} }
inline void swap(PIVector<T> & other) { inline void swap(PIVector<T> & v) {
piSwap<T*>(piv_data, other.piv_data); piSwap<T*>(piv_data, v.piv_data);
piSwap<size_t>(piv_size, other.piv_size); piSwap<size_t>(piv_size, v.piv_size);
piSwap<size_t>(piv_rsize, other.piv_rsize); piSwap<size_t>(piv_rsize, v.piv_rsize);
} }
typedef int (*CompareFunc)(const T * , const T * ); typedef int (*CompareFunc)(const T * , const T * );
@@ -384,98 +463,126 @@ public:
return *this; return *this;
} }
inline PIVector<T> & removeOne(const T & v) { inline PIVector<T> & removeOne(const T & e) {
for (size_t i = 0; i < piv_size; ++i) for (size_t i = 0; i < piv_size; ++i) {
if (piv_data[i] == v) { if (piv_data[i] == e) {
remove(i); remove(i);
return *this; return *this;
} }
}
return *this; return *this;
} }
inline PIVector<T> & removeAll(const T & v) { inline PIVector<T> & removeAll(const T & e) {
for (ssize_t i = 0; i < ssize_t(piv_size); ++i) for (ssize_t i = 0; i < ssize_t(piv_size); ++i) {
if (piv_data[i] == v) { if (piv_data[i] == e) {
remove(i); remove(i);
--i; --i;
} }
}
return *this;
}
inline PIVector<T> & removeWhere(std::function<bool(const T & e)> test) {
for (ssize_t i = 0; i < ssize_t(piv_size); ++i) {
if (test(piv_data[i])) {
remove(i);
--i;
}
}
return *this; return *this;
} }
inline PIVector<T> & push_back(const T & v) { inline PIVector<T> & push_back(const T & e) {
alloc(piv_size + 1); alloc(piv_size + 1);
PIINTROSPECTION_CONTAINER_USED(T, 1); PIINTROSPECTION_CONTAINER_USED(T, 1);
elementNew(piv_data + piv_size - 1, v); elementNew(piv_data + piv_size - 1, e);
return *this; return *this;
} }
inline PIVector<T> & push_back(T && v) {
inline PIVector<T> & push_back(T && e) {
alloc(piv_size + 1); alloc(piv_size + 1);
PIINTROSPECTION_CONTAINER_USED(T, 1); PIINTROSPECTION_CONTAINER_USED(T, 1);
elementNew(piv_data + piv_size - 1, std::move(v)); elementNew(piv_data + piv_size - 1, std::move(e));
return *this; return *this;
} }
inline PIVector<T> & append(const T & v) {return push_back(v);}
inline PIVector<T> & append(T && v) {return push_back(std::move(v));} inline PIVector<T> & append(const T & e) {return push_back(e);}
inline PIVector<T> & append(const PIVector<T> & other) { inline PIVector<T> & append(T && e) {return push_back(std::move(e));}
assert(&other != this); inline PIVector<T> & append(const PIVector<T> & v) {
assert(&v != this);
size_t ps = piv_size; size_t ps = piv_size;
alloc(piv_size + other.piv_size); alloc(piv_size + v.piv_size);
newT(piv_data + ps, other.piv_data, other.piv_size); newT(piv_data + ps, v.piv_data, v.piv_size);
return *this; return *this;
} }
inline PIVector<T> & operator <<(const T & v) {return push_back(v);} inline PIVector<T> & operator <<(const T & e) {return push_back(e);}
inline PIVector<T> & operator <<(T && v) {return push_back(std::move(v));} inline PIVector<T> & operator <<(T && e) {return push_back(std::move(e));}
inline PIVector<T> & operator <<(const PIVector<T> & other) {return append(other);} inline PIVector<T> & operator <<(const PIVector<T> & v) {return append(v);}
inline PIVector<T> & push_front(const T & v) {insert(0, v); return *this;} inline PIVector<T> & push_front(const T & e) {insert(0, e); return *this;}
inline PIVector<T> & push_front(T && v) {insert(0, std::move(v)); return *this;} inline PIVector<T> & push_front(T && e) {insert(0, std::move(e)); return *this;}
inline PIVector<T> & prepend(const T & v) {return push_front(v);} inline PIVector<T> & prepend(const T & e) {return push_front(e);}
inline PIVector<T> & prepend(T && v) {return push_front(std::move(v));} inline PIVector<T> & prepend(T && e) {return push_front(std::move(e));}
inline PIVector<T> & pop_back() { inline PIVector<T> & pop_back() {
if (piv_size == 0) if (piv_size == 0) return *this;
return *this;
resize(piv_size - 1); resize(piv_size - 1);
return *this; return *this;
} }
inline PIVector<T> & pop_front() { inline PIVector<T> & pop_front() {
if (piv_size == 0) if (piv_size == 0) return *this;
return *this;
remove(0); remove(0);
return *this; return *this;
} }
inline T take_back() {T t(back()); pop_back(); return t;} inline T take_back() {T e(back()); pop_back(); return e;}
inline T take_front() {T t(front()); pop_front(); return t;} inline T take_front() {T e(front()); pop_front(); return e;}
template <typename ST> template <typename ST>
PIVector<ST> toType() const { PIVector<ST> toType() const {
PIVector<ST> ret(piv_size); PIVector<ST> ret(piv_size);
for (uint i = 0; i < piv_size; ++i) for (size_t i = 0; i < piv_size; ++i) {
ret[i] = ST(piv_data[i]); ret[i] = ST(piv_data[i]);
}
return ret; return ret;
} }
const PIVector<T> & forEach(std::function<void(const T &)> f) const { const PIVector<T> & forEach(std::function<void(const T & e)> f) const {
for (uint i = 0; i < piv_size; ++i) for (size_t i = 0; i < piv_size; ++i) {
f(piv_data[i]); f(piv_data[i]);
}
return *this; return *this;
} }
PIVector<T> copyForEach(std::function<T(const T &)> f) const { PIVector<T> copyForEach(std::function<T(const T & e)> f) const {
PIVector<T> ret; ret.reserve(piv_size); PIVector<T> ret; ret.reserve(piv_size);
for (uint i = 0; i < piv_size; ++i) for (size_t i = 0; i < piv_size; ++i) {
ret << f(piv_data[i]); ret << f(piv_data[i]);
}
return ret; return ret;
} }
PIVector<T> & forEachInplace(std::function<T(const T &)> f) { PIVector<T> & forEachInplace(std::function<T(const T & e)> f) {
for (uint i = 0; i < piv_size; ++i) for (size_t i = 0; i < piv_size; ++i) {
piv_data[i] = f(piv_data[i]); piv_data[i] = f(piv_data[i]);
}
return *this; return *this;
} }
template <typename ST> template <typename ST>
PIVector<ST> toType(std::function<ST(const T &)> f) const { PIVector<ST> map(std::function<ST(const T & e)> f) const {
PIVector<ST> ret; ret.reserve(piv_size); PIVector<ST> ret; ret.reserve(piv_size);
for (uint i = 0; i < piv_size; ++i) for (size_t i = 0; i < piv_size; ++i) {
ret << f(piv_data[i]); ret << f(piv_data[i]);
}
return ret;
}
template <typename ST>
PIVector<ST> toType(std::function<ST(const T & e)> f) const {return map(f);}
template <typename ST>
ST reduce(std::function<ST(const T & e, const ST & acc)> f, const ST & initial = ST()) const {
ST ret(initial);
for (size_t i = 0; i < piv_size; ++i) {
ret = f(piv_data[i], ret);
}
return ret; return ret;
} }
@@ -485,16 +592,18 @@ public:
assert(rows*cols == piv_size); assert(rows*cols == piv_size);
ret.resize(rows); ret.resize(rows);
if (order == byRow) { if (order == byRow) {
for (size_t r = 0; r < rows; r++) for (size_t r = 0; r < rows; r++) {
ret[r] = PIVector<T>(&(piv_data[r*cols]), cols); ret[r] = PIVector<T>(&(piv_data[r*cols]), cols);
} }
}
if (order == byColumn) { if (order == byColumn) {
for (size_t r = 0; r < rows; r++) { for (size_t r = 0; r < rows; r++) {
ret[r].resize(cols); ret[r].resize(cols);
for (size_t c = 0; c < cols; c++) for (size_t c = 0; c < cols; c++) {
ret[r][c] = piv_data[c*rows + r]; ret[r][c] = piv_data[c*rows + r];
} }
} }
}
return ret; return ret;
} }
@@ -508,14 +617,17 @@ public:
size_t cols = at(0).size(); size_t cols = at(0).size();
ret.reserve(rows * cols); ret.reserve(rows * cols);
if (order == byRow) { if (order == byRow) {
for (size_t r = 0; r < rows; r++) for (size_t r = 0; r < rows; r++) {
ret.append(at(r)); ret.append(at(r));
} }
}
if (order == byColumn) { if (order == byColumn) {
for (size_t c = 0; c < cols; c++) for (size_t c = 0; c < cols; c++) {
for (size_t r = 0; r < rows; r++) for (size_t r = 0; r < rows; r++) {
ret << at(r)[c]; ret << at(r)[c];
} }
}
}
ret.resize(rows * cols); ret.resize(rows * cols);
return ret; return ret;
} }
@@ -524,8 +636,9 @@ private:
inline void _reset() {piv_size = piv_rsize = 0; piv_data = 0;} inline void _reset() {piv_size = piv_rsize = 0; piv_data = 0;}
inline size_t asize(size_t s) { inline size_t asize(size_t s) {
if (s == 0) return 0; if (s == 0) return 0;
if (piv_rsize + piv_rsize >= s && piv_rsize < s) if (piv_rsize + piv_rsize >= s && piv_rsize < s) {
return piv_rsize + piv_rsize; return piv_rsize + piv_rsize;
}
ssize_t t = 0, s_ = s - 1; ssize_t t = 0, s_ = s - 1;
while (s_ >> t) ++t; while (s_ >> t) ++t;
return (1 << t); return (1 << t);
@@ -551,10 +664,11 @@ private:
inline void deleteT(T * d, size_t sz) { inline void deleteT(T * d, size_t sz) {
PIINTROSPECTION_CONTAINER_UNUSED(T, sz) PIINTROSPECTION_CONTAINER_UNUSED(T, sz)
if ((uchar*)d != 0) { if ((uchar*)d != 0) {
for (size_t i = 0; i < sz; ++i) for (size_t i = 0; i < sz; ++i) {
elementDelete(d[i]); elementDelete(d[i]);
} }
} }
}
template<typename T1 = T, typename std::enable_if< template<typename T1 = T, typename std::enable_if<
std::is_trivially_copyable<T1>::value std::is_trivially_copyable<T1>::value
, int>::type = 0> , int>::type = 0>
@@ -612,7 +726,15 @@ private:
#ifdef PIP_STD_IOSTREAM #ifdef PIP_STD_IOSTREAM
template<typename T> template<typename T>
inline std::ostream & operator <<(std::ostream & s, const PIVector<T> & v) {s << "{"; for (size_t i = 0; i < v.size(); ++i) {s << v[i]; if (i < v.size() - 1) s << ", ";} s << "}"; return s;} inline std::ostream & operator <<(std::ostream & s, const PIVector<T> & v) {
s << "{";
for (size_t i = 0; i < v.size(); ++i) {
s << v[i];
if (i < v.size() - 1) s << ", ";
}
s << "}";
return s;
}
#endif #endif
template<typename T> template<typename T>
@@ -622,9 +744,10 @@ inline PICout operator <<(PICout s, const PIVector<T> & v) {
s << "{"; s << "{";
for (size_t i = 0; i < v.size(); ++i) { for (size_t i = 0; i < v.size(); ++i) {
s << v[i]; s << v[i];
if (i < v.size() - 1) if (i < v.size() - 1) {
s << ", "; s << ", ";
} }
}
s << "}"; s << "}";
s.restoreControl(); s.restoreControl();
return s; return s;

View File

@@ -31,7 +31,6 @@
#include "pip_export.h" #include "pip_export.h"
#include "pip_defs.h" #include "pip_defs.h"
#include "string.h" #include "string.h"
//! Meta-information section for any entity. //! Meta-information section for any entity.
//! Parsing by \a pip_cmg and can be accessed by \a PICodeInfo. //! Parsing by \a pip_cmg and can be accessed by \a PICodeInfo.
//! Contains sequence of key=value pairs, e.g. //! Contains sequence of key=value pairs, e.g.
@@ -118,9 +117,15 @@
#endif //DOXYGEN #endif //DOXYGEN
#ifdef CC_AVR_GCC
# include <ArduinoSTL.h>
#endif
#include <functional> #include <functional>
#include <cstddef> #include <cstddef>
#include <cassert>
#include <limits>
#include <atomic>
#ifdef WINDOWS #ifdef WINDOWS
# ifdef CC_VC # ifdef CC_VC
# define SHUT_RDWR 2 # define SHUT_RDWR 2
@@ -161,7 +166,6 @@
#ifdef NDEBUG #ifdef NDEBUG
# undef NDEBUG # undef NDEBUG
#endif #endif
#include <cassert>
#ifndef assert #ifndef assert
# define assert(x) # define assert(x)
# define assertm(exp, msg) # define assertm(exp, msg)
@@ -274,7 +278,7 @@
} _PIP_ADD_COUNTER(_pip_initializer_); } _PIP_ADD_COUNTER(_pip_initializer_);
#ifdef FREERTOS #ifdef MICRO_PIP
# define PIP_MIN_MSLEEP 10. # define PIP_MIN_MSLEEP 10.
#else #else
# define PIP_MIN_MSLEEP 1. # define PIP_MIN_MSLEEP 1.
@@ -285,10 +289,10 @@
#define FOREVER for (;;) #define FOREVER for (;;)
//! Macro used for infinite wait //! Macro used for infinite wait
#define FOREVER_WAIT FOREVER msleep(PIP_MIN_MSLEEP); #define FOREVER_WAIT FOREVER piMinSleep;
//! Macro used for infinite wait //! Macro used for infinite wait
#define WAIT_FOREVER FOREVER msleep(PIP_MIN_MSLEEP); #define WAIT_FOREVER FOREVER piMinSleep;
//! global variable enabling output to piCout, default is true //! global variable enabling output to piCout, default is true
@@ -471,6 +475,17 @@ inline void piLetobe(void * data, int size) {
piSwap<uchar>(((uchar*)data)[size - i - 1], ((uchar*)data)[i]); piSwap<uchar>(((uchar*)data)[size - i - 1], ((uchar*)data)[i]);
} }
/*! @brief Function for compare two numeric values with epsilon
* \details Example:\n \snippet piincludes.cpp compare
* There are some macros:
* - \c piComparef for "float"
* - \c piCompared for "double"
*/
template<typename T>
inline bool piCompare(const T & a, const T & b, const T & epsilon = std::numeric_limits<T>::epsilon()) {
return piAbs(a - b) <= epsilon;
}
/// @brief Templated function that inverse byte order of value "v" /// @brief Templated function that inverse byte order of value "v"
template<typename T> inline void piLetobe(T * v) {piLetobe(v, sizeof(T));} template<typename T> inline void piLetobe(T * v) {piLetobe(v, sizeof(T));}
@@ -487,13 +502,13 @@ template<typename T> inline void piLetobe(T * v) {piLetobe(v, sizeof(T));}
template<typename T> inline T piLetobe(const T & v) {T tv(v); piLetobe(&tv, sizeof(T)); return tv;} template<typename T> inline T piLetobe(const T & v) {T tv(v); piLetobe(&tv, sizeof(T)); return tv;}
// specialization // specialization
template<> inline ushort piLetobe(const ushort & v) {return (v << 8) | (v >> 8);} template<> inline uint16_t piLetobe(const uint16_t & v) {return (v << 8) | (v >> 8);}
template<> inline uint piLetobe(const uint & v) {return (v >> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | ((v << 24) & 0xFF000000);} template<> inline uint32_t piLetobe(const uint32_t & v) {return (v >> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | ((v << 24) & 0xFF000000);}
template<> inline float piLetobe(const float & v) { template<> inline float piLetobe(const float & v) {
union _pletobe_f { union _pletobe_f {
_pletobe_f(const float &f_) {f = f_;} _pletobe_f(const float &f_) {f = f_;}
float f; float f;
uint v; uint32_t v;
}; };
_pletobe_f a(v); _pletobe_f a(v);
a.v = (a.v >> 24) | ((a.v >> 8) & 0xFF00) | ((a.v << 8) & 0xFF0000) | ((a.v << 24) & 0xFF000000); a.v = (a.v >> 24) | ((a.v >> 8) & 0xFF00) | ((a.v << 8) & 0xFF0000) | ((a.v << 24) & 0xFF000000);
@@ -558,6 +573,8 @@ template<> inline uint piHash(const ldouble & v) {return piHashData((const uchar
#define piRoundf piRound<float> #define piRoundf piRound<float>
#define piRoundd piRound<double> #define piRoundd piRound<double>
#define piComparef piCompare<float>
#define piCompared piCompare<double>
#define piFloorf piFloor<float> #define piFloorf piFloor<float>
#define piFloord piFloor<double> #define piFloord piFloor<double>
#define piCeilf piCeil<float> #define piCeilf piCeil<float>

View File

@@ -221,22 +221,22 @@ PIByteArray & PIByteArray::decompressRLE(uchar threshold) {
} }
uchar PIByteArray::checksumPlain8() const { uchar PIByteArray::checksumPlain8(bool inverse) const {
uchar c = 0; uchar c = 0;
int sz = size_s(); int sz = size_s();
for (int i = 0; i < sz; ++i) for (int i = 0; i < sz; ++i)
c += at(i); c += at(i);
c = ~(c + 1); if (inverse) c = ~(c + 1);
return c; return c;
} }
uint PIByteArray::checksumPlain32() const { uint PIByteArray::checksumPlain32(bool inverse) const {
uint c = 0; uint c = 0;
int sz = size_s(); int sz = size_s();
for (int i = 0; i < sz; ++i) for (int i = 0; i < sz; ++i)
c += at(i) * (i + 1); c += at(i) * (i + 1);
c = ~(c + 1); if (inverse) c = ~(c + 1);
return c; return c;
} }

View File

@@ -27,8 +27,9 @@
#include "pibitarray.h" #include "pibitarray.h"
#include "pimap.h" #include "pimap.h"
#include "pivector2d.h" #include "pivector2d.h"
#include <stdio.h>
#ifdef FREERTOS #ifdef MICRO_PIP
# define _TYPENAME_(T) "?" # define _TYPENAME_(T) "?"
#else #else
# define _TYPENAME_(T) typeid(T).name() # define _TYPENAME_(T) typeid(T).name()
@@ -85,6 +86,8 @@ public:
PIByteArray(const PIByteArray & o): PIDeque<uchar>(o) {} PIByteArray(const PIByteArray & o): PIDeque<uchar>(o) {}
PIByteArray(const PIDeque<uchar> & o): PIDeque<uchar>(o) {}
PIByteArray(PIByteArray && o): PIDeque<uchar>(std::move(o)) {} PIByteArray(PIByteArray && o): PIDeque<uchar>(std::move(o)) {}
//! Constructs 0-filled byte array with size "size" //! Constructs 0-filled byte array with size "size"
@@ -116,6 +119,12 @@ public:
//! Return resized byte array //! Return resized byte array
PIByteArray resized(uint new_size) const {PIByteArray ret(new_size); memcpy(ret.data(), data(), new_size); return ret;} PIByteArray resized(uint new_size) const {PIByteArray ret(new_size); memcpy(ret.data(), data(), new_size); return ret;}
//! Return sub-array starts from "index" and has "count" or less bytes
PIByteArray getRange(size_t index, size_t count) const {
return PIDeque<uchar>::getRange(index, count);
}
//! Convert data to Base 64 and return this byte array //! Convert data to Base 64 and return this byte array
PIByteArray & convertToBase64(); PIByteArray & convertToBase64();
@@ -146,18 +155,18 @@ public:
PIByteArray & append(uchar t) {push_back(t); return *this;} PIByteArray & append(uchar t) {push_back(t); return *this;}
//! Returns 8-bit checksum //! Returns 8-bit checksum
//! sum all bytes, add 1, inverse //! sum all bytes, if inverse - add 1, inverse
//! Pseudocode: //! Pseudocode:
//! sum += at(i); //! sum += at(i);
//! return ~(sum + 1) //! return ~(sum + 1)
uchar checksumPlain8() const; uchar checksumPlain8(bool inverse = true) const;
//! Returns 32-bit checksum //! Returns 32-bit checksum
//! sum all bytes multiplyed by index+1, add 1, inverse //! sum all bytes multiplyed by index+1, if inverse - add 1, inverse
//! Pseudocode: //! Pseudocode:
//! sum += at(i) * (i + 1); //! sum += at(i) * (i + 1);
//! return ~(sum + 1) //! return ~(sum + 1)
uint checksumPlain32() const; uint checksumPlain32(bool inverse = true) const;
//! Returns hash //! Returns hash
uint hash() const; uint hash() const;
@@ -190,34 +199,39 @@ public:
//! \relatesalso PIByteArray @brief Byte arrays compare operator //! \relatesalso PIByteArray @brief Byte arrays compare operator
inline bool operator <(const PIByteArray & v0, const PIByteArray & v1) { inline bool operator <(const PIByteArray & v0, const PIByteArray & v1) {
if (v0.size() == v1.size()) { if (v0.size() == v1.size()) {
for (uint i = 0; i < v0.size(); ++i) if (v0.isEmpty()) return false;
if (v0[i] != v1[i]) return memcmp(v0.data(), v1.data(), v0.size()) < 0;
return v0[i] < v1[i];
return false;
} }
return v0.size() < v1.size(); return v0.size() < v1.size();
} }
//! \relatesalso PIByteArray @brief Byte arrays compare operator //! \relatesalso PIByteArray @brief Byte arrays compare operator
inline bool operator ==(PIByteArray & f, PIByteArray & s) { inline bool operator >(const PIByteArray & v0, const PIByteArray & v1) {
if (f.size_s() != s.size_s()) if (v0.size() == v1.size()) {
return false; if (v0.isEmpty()) return false;
for (int i = 0; i < f.size_s(); ++i) return memcmp(v0.data(), v1.data(), v0.size()) > 0;
if (f[i] != s[i]) }
return false; return v0.size() > v1.size();
return true;
} }
//! \relatesalso PIByteArray @brief Byte arrays compare operator //! \relatesalso PIByteArray @brief Byte arrays compare operator
inline bool operator !=(PIByteArray & f, PIByteArray & s) { inline bool operator ==(const PIByteArray & v0, const PIByteArray & v1) {
if (f.size_s() != s.size_s()) if (v0.size() == v1.size()) {
return true; if (v0.isEmpty()) return true;
for (int i = 0; i < f.size_s(); ++i) return memcmp(v0.data(), v1.data(), v0.size()) == 0;
if (f[i] != s[i]) }
return true;
return false; return false;
} }
//! \relatesalso PIByteArray @brief Byte arrays compare operator
inline bool operator !=(const PIByteArray & v0, const PIByteArray & v1) {
if (v0.size() == v1.size()) {
if (v0.isEmpty()) return false;
return memcmp(v0.data(), v1.data(), v0.size()) != 0;
}
return true;
}
#ifdef PIP_STD_IOSTREAM #ifdef PIP_STD_IOSTREAM
//! \relatesalso PIByteArray @brief Output to std::ostream operator //! \relatesalso PIByteArray @brief Output to std::ostream operator
inline std::ostream & operator <<(std::ostream & s, const PIByteArray & ba); inline std::ostream & operator <<(std::ostream & s, const PIByteArray & ba);

View File

@@ -24,6 +24,7 @@
#include "pistring_std.h" #include "pistring_std.h"
#ifdef WINDOWS #ifdef WINDOWS
# include <windows.h> # include <windows.h>
# include <wingdi.h>
# include <wincon.h> # include <wincon.h>
# define COMMON_LVB_UNDERSCORE 0x8000 # define COMMON_LVB_UNDERSCORE 0x8000
#endif #endif

View File

@@ -26,15 +26,15 @@
#ifdef PIP_STD_IOSTREAM #ifdef PIP_STD_IOSTREAM
# include <iostream> # include <iostream>
#endif #endif
#include <atomic>
class PIMutex; class PIMutex;
class PIMutexLocker; class PIMutexLocker;
class PIObject; class PIObject;
class PIString; class PIString;
class PIByteArray; class PIByteArray;
#ifndef MICRO_PIP
class PIInit; class PIInit;
#endif
class PIChar; class PIChar;
class PICout; class PICout;

View File

@@ -40,6 +40,15 @@ typedef LONG(NTAPI*PINtSetTimerResolution)(ULONG, BOOLEAN, PULONG);
#include <cstdio> #include <cstdio>
#include <iostream> #include <iostream>
#ifdef FREERTOS
# ifdef ESP_PLATFORM
# include "freertos/FreeRTOS.h"
# include "freertos/task.h"
# endif
# ifdef ARDUINO_ARCH_STM32
# include <STM32FreeRTOS.h>
# endif
#endif
#endif // PIINCLUDES_P_H #endif // PIINCLUDES_P_H

View File

@@ -19,15 +19,15 @@
#include "piincludes_p.h" #include "piincludes_p.h"
#include "piinit.h" #include "piinit.h"
#ifndef MICRO_PIP
#include "pitime.h" #include "pitime.h"
#include "pisignals.h" #include "pisignals.h"
#include "piobject.h" #include "piobject.h"
#include "pisysteminfo.h" #include "pisysteminfo.h"
#include "piresourcesstorage.h" #include "piresourcesstorage.h"
#include "pidir.h" #include "pidir.h"
#ifndef FREERTOS #include "piprocess.h"
# include "piprocess.h"
#endif
#ifdef ESP_PLATFORM #ifdef ESP_PLATFORM
# include "esp_system.h" # include "esp_system.h"
#endif #endif
@@ -49,9 +49,7 @@ void __PISetTimerResolution() {
} }
#else #else
# include <pwd.h> # include <pwd.h>
# ifndef FREERTOS
# include <sys/utsname.h> # include <sys/utsname.h>
# endif
# include <pthread.h> # include <pthread.h>
# ifdef BLACKBERRY # ifdef BLACKBERRY
# include <signal.h> # include <signal.h>
@@ -84,7 +82,6 @@ ULONG prev_res;
bool delete_locs; bool delete_locs;
PRIVATE_DEFINITION_END(PIInit) PRIVATE_DEFINITION_END(PIInit)
#ifndef FREERTOS
void __sighandler__(PISignals::Signal s) { void __sighandler__(PISignals::Signal s) {
//piCout << Hex << int(s); //piCout << Hex << int(s);
if (s == PISignals::StopTTYInput || s == PISignals::StopTTYOutput) if (s == PISignals::StopTTYInput || s == PISignals::StopTTYOutput)
@@ -92,7 +89,6 @@ void __sighandler__(PISignals::Signal s) {
if (s == PISignals::UserDefined1) if (s == PISignals::UserDefined1)
dumpApplicationToFile(PIDir::home().path() + PIDir::separator + PIStringAscii("_PIP_DUMP_") + PIString::fromNumber(PIProcess::currentPID())); dumpApplicationToFile(PIDir::home().path() + PIDir::separator + PIStringAscii("_PIP_DUMP_") + PIString::fromNumber(PIProcess::currentPID()));
} }
#endif
#ifdef ANDROID #ifdef ANDROID
@@ -107,7 +103,6 @@ PIInit::PIInit() {
PISystemInfo * sinfo = PISystemInfo::instance(); PISystemInfo * sinfo = PISystemInfo::instance();
sinfo->execDateTime = PIDateTime::current(); sinfo->execDateTime = PIDateTime::current();
setFileCharset("UTF-8"); setFileCharset("UTF-8");
#ifndef FREERTOS
#ifndef ANDROID #ifndef ANDROID
PISignals::setSlot(__sighandler__); PISignals::setSlot(__sighandler__);
PISignals::grabSignals(PISignals::UserDefined1); PISignals::grabSignals(PISignals::UserDefined1);
@@ -128,7 +123,7 @@ PIInit::PIInit() {
break; break;
} }
} }
# else # else //WINDOWS
// OS version // OS version
DWORD dwVersion = GetVersion(); DWORD dwVersion = GetVersion();
DWORD dwMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion))); DWORD dwMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion)));
@@ -154,7 +149,7 @@ PIInit::PIInit() {
setTimerResolutionAddr = (PINtSetTimerResolution)GetProcAddress(PRIVATE->ntlib, "NtSetTimerResolution"); setTimerResolutionAddr = (PINtSetTimerResolution)GetProcAddress(PRIVATE->ntlib, "NtSetTimerResolution");
__PISetTimerResolution(); __PISetTimerResolution();
} }
# endif # endif //WINDOWS
# ifdef HAS_LOCALE # ifdef HAS_LOCALE
//cout << "has locale" << endl; //cout << "has locale" << endl;
if (currentLocale_t != 0) { if (currentLocale_t != 0) {
@@ -162,18 +157,18 @@ PIInit::PIInit() {
currentLocale_t = 0; currentLocale_t = 0;
} }
currentLocale_t = newlocale(LC_ALL, setlocale(LC_ALL, ""), 0); currentLocale_t = newlocale(LC_ALL, setlocale(LC_ALL, ""), 0);
# else # else //HAS_LOCALE
setlocale(LC_ALL, ""); setlocale(LC_ALL, "");
setlocale(LC_NUMERIC, "C"); setlocale(LC_NUMERIC, "C");
# endif # endif //HAS_LOCALE
#else #else //ANDROID
struct sigaction actions; struct sigaction actions;
memset(&actions, 0, sizeof(actions)); memset(&actions, 0, sizeof(actions));
sigemptyset(&actions.sa_mask); sigemptyset(&actions.sa_mask);
actions.sa_flags = 0; actions.sa_flags = 0;
actions.sa_handler = android_thread_exit_handler; actions.sa_handler = android_thread_exit_handler;
sigaction(SIGTERM, &actions, 0); sigaction(SIGTERM, &actions, 0);
#endif #endif //ANDROID
PRIVATE->delete_locs = false; PRIVATE->delete_locs = false;
__syslocname__ = __sysoemname__ = 0; __syslocname__ = __sysoemname__ = 0;
__utf8name__ = const_cast<char*>("UTF-8"); __utf8name__ = const_cast<char*>("UTF-8");
@@ -201,13 +196,13 @@ PIInit::PIInit() {
# endif # endif
//piCout << __syslocname__; //piCout << __syslocname__;
//piCout << __sysoemname__; //piCout << __sysoemname__;
#else #else //PIP_ICU
# ifdef WINDOWS # ifdef WINDOWS
__syslocname__ = (char *)CP_ACP; __syslocname__ = (char *)CP_ACP;
__sysoemname__ = (char *)CP_OEMCP; __sysoemname__ = (char *)CP_OEMCP;
__utf8name__ = (char *)CP_UTF8; __utf8name__ = (char *)CP_UTF8;
# endif # endif
#endif #endif //PIP_ICU
#ifdef MAC_OS #ifdef MAC_OS
host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &__pi_mac_clock); host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &__pi_mac_clock);
#endif #endif
@@ -236,7 +231,7 @@ PIInit::PIInit() {
ulong unlen = 1023; ulong unlen = 1023;
if (GetUserName(cbuff, &unlen) != 0) if (GetUserName(cbuff, &unlen) != 0)
sinfo->user = cbuff; sinfo->user = cbuff;
#else #else //WINDOWS
sinfo->processorsCount = piMaxi(1, int(sysconf(_SC_NPROCESSORS_ONLN))); sinfo->processorsCount = piMaxi(1, int(sysconf(_SC_NPROCESSORS_ONLN)));
passwd * ps = getpwuid(getuid()); passwd * ps = getpwuid(getuid());
if (ps) if (ps)
@@ -252,8 +247,8 @@ PIInit::PIInit() {
sinfo->OS_version = uns.release; sinfo->OS_version = uns.release;
sinfo->architecture = uns.machine; sinfo->architecture = uns.machine;
} }
# endif #endif //WINDOWS
#endif
#ifdef ESP_PLATFORM #ifdef ESP_PLATFORM
esp_chip_info_t chip_info; esp_chip_info_t chip_info;
esp_chip_info(&chip_info); esp_chip_info(&chip_info);
@@ -275,6 +270,8 @@ PIInit::PIInit() {
PIStringAscii("FreeBSD"); PIStringAscii("FreeBSD");
#elif defined(FREERTOS) #elif defined(FREERTOS)
PIStringAscii("FreeRTOS"); PIStringAscii("FreeRTOS");
#elif defined(MICRO_PIP)
PIStringAscii("MicroPIP");
#else #else
uns.sysname; uns.sysname;
#endif #endif
@@ -305,49 +302,49 @@ PIInit::~PIInit() {
bool PIInit::isBuildOptionEnabled(PIInit::BuildOption o) { bool PIInit::isBuildOptionEnabled(PIInit::BuildOption o) {
switch (o) { switch (o) {
case ICU: return case boICU: return
#ifdef PIP_ICU #ifdef PIP_ICU
true; true;
#else #else
false; false;
#endif #endif
case USB: return case boUSB: return
#ifdef PIP_USB #ifdef PIP_USB
true; true;
#else #else
false; false;
#endif #endif
case Crypt: return case boCrypt: return
#ifdef PIP_CRYPT #ifdef PIP_CRYPT
true; true;
#else #else
false; false;
#endif #endif
case Introspection: return case boIntrospection: return
#ifdef PIP_INTROSPECTION #ifdef PIP_INTROSPECTION
true; true;
#else #else
false; false;
#endif #endif
case FFTW: return case boFFTW: return
#ifdef PIP_FFTW #ifdef PIP_FFTW
true; true;
#else #else
false; false;
#endif #endif
case Compress: return case boCompress: return
#ifdef PIP_COMPRESS #ifdef PIP_COMPRESS
true; true;
#else #else
false; false;
#endif #endif
case OpenCL: return case boOpenCL: return
#ifdef PIP_OPENCL #ifdef PIP_OPENCL
true; true;
#else #else
false; false;
#endif #endif
case Cloud: return case boCloud: return
#ifdef PIP_CLOUD #ifdef PIP_CLOUD
true; true;
#else #else
@@ -361,14 +358,14 @@ bool PIInit::isBuildOptionEnabled(PIInit::BuildOption o) {
PIStringList PIInit::buildOptions() { PIStringList PIInit::buildOptions() {
PIStringList ret; PIStringList ret;
if (isBuildOptionEnabled(ICU)) ret << "ICU"; if (isBuildOptionEnabled(boICU)) ret << "ICU";
if (isBuildOptionEnabled(USB)) ret << "USB"; if (isBuildOptionEnabled(boUSB)) ret << "USB";
if (isBuildOptionEnabled(Crypt)) ret << "Crypt"; if (isBuildOptionEnabled(boCrypt)) ret << "Crypt";
if (isBuildOptionEnabled(Introspection)) ret << "Introspection"; if (isBuildOptionEnabled(boIntrospection)) ret << "Introspection";
if (isBuildOptionEnabled(FFTW)) ret << "FFTW"; if (isBuildOptionEnabled(boFFTW)) ret << "FFTW";
if (isBuildOptionEnabled(Compress)) ret << "Compress"; if (isBuildOptionEnabled(boCompress)) ret << "Compress";
if (isBuildOptionEnabled(OpenCL)) ret << "OpenCL"; if (isBuildOptionEnabled(boOpenCL)) ret << "OpenCL";
if (isBuildOptionEnabled(Cloud)) ret << "Cloud"; if (isBuildOptionEnabled(boCloud)) ret << "Cloud";
return ret; return ret;
} }
@@ -415,3 +412,6 @@ __PIInit_Initializer__::~__PIInit_Initializer__() {
__instance__ = 0; __instance__ = 0;
} }
} }
#endif // MICRO_PIP

View File

@@ -23,6 +23,10 @@
#ifndef PIINIT_H #ifndef PIINIT_H
#define PIINIT_H #define PIINIT_H
#include "pibase.h"
#ifndef MICRO_PIP
#include "piincludes.h" #include "piincludes.h"
@@ -49,14 +53,14 @@ public:
//! @brief Build options which PIP library was built //! @brief Build options which PIP library was built
enum BuildOption { enum BuildOption {
ICU /*! Unicode support */ = 0x01, boICU /*! Unicode support */ = 0x01,
USB /*! USB support */ = 0x02, boUSB /*! USB support */ = 0x02,
Crypt /*! Crypt support */ = 0x08, boCrypt /*! Crypt support */ = 0x08,
Introspection /*! Introspection */ = 0x010, boIntrospection /*! Introspection */ = 0x010,
FFTW /*! FFTW3 support */ = 0x40, boFFTW /*! FFTW3 support */ = 0x40,
Compress /*! Zlib compression support */ = 0x80, boCompress /*! Zlib compression support */ = 0x80,
OpenCL /*! OpenCL support */ = 0x100, boOpenCL /*! OpenCL support */ = 0x100,
Cloud /*! Cloud transport support */ = 0x200, boCloud /*! Cloud transport support */ = 0x200,
}; };
static PIInit * instance() {return __PIInit_Initializer__::__instance__;} static PIInit * instance() {return __PIInit_Initializer__::__instance__;}
static bool isBuildOptionEnabled(BuildOption o); static bool isBuildOptionEnabled(BuildOption o);
@@ -70,4 +74,5 @@ private:
}; };
#endif // MICRO_PIP
#endif // PIINIT_H #endif // PIINIT_H

View File

@@ -18,10 +18,10 @@
*/ */
#include "piobject.h" #include "piobject.h"
#include "pisysteminfo.h"
#include "pithread.h" #include "pithread.h"
#include "piconditionvar.h" #include "piconditionvar.h"
#ifndef FREERTOS #ifndef MICRO_PIP
# include "pisysteminfo.h"
# include "pifile.h" # include "pifile.h"
#endif #endif
@@ -91,9 +91,11 @@ PIObject::~PIObject() {
mutexObjects().lock(); mutexObjects().lock();
objects().removeAll(this); objects().removeAll(this);
mutexObjects().unlock(); mutexObjects().unlock();
piDisconnect(this); deleted(this);
piDisconnectAll();
} }
PIMap<PIString, PIVariant> PIObject::properties() const { PIMap<PIString, PIVariant> PIObject::properties() const {
PIMap<PIString, PIVariant> ret; PIMap<PIString, PIVariant> ret;
piForeachC (PropertyHash p, properties_) piForeachC (PropertyHash p, properties_)
@@ -141,50 +143,6 @@ bool PIObject::executeQueued(PIObject * performer, const PIString & method, cons
} }
void PIObject::piConnect(const PIString & src, const PIString & sig, void * dest, void * ev_h) {
PIObject * o = findByName(src);
if (o == 0) {
piCout << "[PIObject] Can`t find object with name \"" << src << "\"!";
return;
}
PIMutexLocker _ml(o->mutex_connect);
PIMutexLocker _mld(((PIObject*)dest)->mutex_connect, ((PIObject*)dest) != o);
o->connections << __Connection(ev_h, 0, sig, (PIObject*)dest, dest);
((PIObject*)dest)->connectors << o;
}
void PIObject::piConnect(PIObject * src, const PIString & sig, const PIString & dest, void * ev_h) {
PIObject * o = findByName(dest);
if (o == 0) {
piCout << "[PIObject] Can`t find object with name \"" << dest << "\"!";
return;
}
PIMutexLocker _ml(src->mutex_connect);
PIMutexLocker _mld(o->mutex_connect, src != o);
src->connections << __Connection(ev_h, 0, sig, o, o);
((PIObject*)o)->connectors << src;
}
void PIObject::piConnect(const PIString & src, const PIString & sig, const PIString & dest, void * ev_h) {
PIObject * s = findByName(src);
if (s == 0) {
piCout << "[PIObject] Can`t find object with name \"" << src << "\"!";
return;
}
PIObject * d = findByName(dest);
if (d == 0) {
piCout << "[PIObject] Can`t find object with name \"" << dest << "\"!";
return;
}
PIMutexLocker _ml(s->mutex_connect);
PIMutexLocker _mld(d->mutex_connect, s != d);
s->connections << __Connection(ev_h, 0, sig, d, d);
d->connectors << s;
}
PIStringList PIObject::scopeList() const { PIStringList PIObject::scopeList() const {
PIMutexLocker ml(__meta_mutex()); PIMutexLocker ml(__meta_mutex());
return __meta_data()[classNameID()].scope_list; return __meta_data()[classNameID()].scope_list;
@@ -256,31 +214,33 @@ PIObject::__MetaFunc PIObject::methodEH(const void * addr) const {
} }
void PIObject::piConnect(PIObject * src, const PIString & sig, PIObject * dest_o, void * dest, void * ev_h, void * e_h, int args, const char * loc) { PIObject::Connection PIObject::piConnect(PIObject * src, const PIString & sig, PIObject * dest_o, void * dest, void * ev_h, void * e_h, int args, const char * loc) {
//piCout << "piConnect ..."; //piCout << "piConnect ...";
//piCout << "piConnect" << src << (void*)(dest) << sig; //piCout << "piConnect" << src << (void*)(dest) << sig;
//piCout << "piConnect" << src->className() << "->" << ((PIObject*)dest)->className(); //piCout << "piConnect" << src->className() << "->" << ((PIObject*)dest)->className();
PIMutexLocker _ml(src->mutex_connect); PIMutexLocker _ml(src->mutex_connect);
PIMutexLocker _mld(dest_o->mutex_connect, src != dest_o); PIMutexLocker _mld(dest_o->mutex_connect, src != dest_o);
src->connections << __Connection(ev_h, e_h, sig, dest_o, dest, args); Connection conn(ev_h, e_h, sig, src, dest_o, dest, args);
src->connections << conn;
//piCout << "piConnect" << ((PIObject*)dest) << sig << ((PIObject*)dest)->connectors.size_s() << "..."; //piCout << "piConnect" << ((PIObject*)dest) << sig << ((PIObject*)dest)->connectors.size_s() << "...";
//piCout << "addConnector" << dest_o << src; //piCout << "addConnector" << dest_o << src;
dest_o->connectors << src; dest_o->connectors << src;
//piCout << "piConnect" << ((PIObject*)dest) << sig << ((PIObject*)dest)->connectors.size_s(); //piCout << "piConnect" << ((PIObject*)dest) << sig << ((PIObject*)dest)->connectors.size_s();
//piCout << "piConnect ok"; //piCout << "piConnect ok";
return conn;
} }
bool PIObject::piConnectU(PIObject * src, const PIString & sig, PIObject * dest_o, void * dest, const PIString & hname, const char * loc, PIObject * performer) { PIObject::Connection PIObject::piConnectU(PIObject * src, const PIString & sig, PIObject * dest_o, void * dest, const PIString & hname, const char * loc, PIObject * performer) {
if (src == 0 || dest_o == 0 || dest == 0) return false; if (src == 0 || dest_o == 0 || dest == 0) return Connection();
if (!src->isPIObject()) { if (!src->isPIObject()) {
piCout << "[piConnectU] \"" << sig << "\" -> \"" << hname << "\" error: source object is not PIObject! (" << loc << ")"; piCout << "[piConnectU] \"" << sig << "\" -> \"" << hname << "\" error: source object is not PIObject! (" << loc << ")";
return false; return Connection();
} }
if (!dest_o->isPIObject()) { if (!dest_o->isPIObject()) {
piCout << "[piConnectU] \"" << sig << "\" -> \"" << hname << "\" error: destination object is not PIObject! (" << loc << ")"; piCout << "[piConnectU] \"" << sig << "\" -> \"" << hname << "\" error: destination object is not PIObject! (" << loc << ")";
return false; return Connection();
} }
PIMutexLocker ml(__meta_mutex()); PIMutexLocker ml(__meta_mutex());
PIMutexLocker mls(src->mutex_connect); PIMutexLocker mls(src->mutex_connect);
@@ -288,11 +248,11 @@ bool PIObject::piConnectU(PIObject * src, const PIString & sig, PIObject * dest_
PIVector<__MetaFunc> m_src = src->findEH(sig), m_dest = dest_o->findEH(hname); PIVector<__MetaFunc> m_src = src->findEH(sig), m_dest = dest_o->findEH(hname);
if (m_src.isEmpty()) { if (m_src.isEmpty()) {
piCout << "[piConnectU] Error: can`t find event \"" << sig << "\" in class \"" << src->className() << "\"! (" << loc << ")"; piCout << "[piConnectU] Error: can`t find event \"" << sig << "\" in class \"" << src->className() << "\"! (" << loc << ")";
return false; return Connection();
} }
if (m_dest.isEmpty()) { if (m_dest.isEmpty()) {
piCout << "[piConnectU] Error: can`t find handler \"" << hname << "\" in class \"" << dest_o->className() << "\"! (" << loc << ")"; piCout << "[piConnectU] Error: can`t find handler \"" << hname << "\" in class \"" << dest_o->className() << "\"! (" << loc << ")";
return false; return Connection();
} }
void * addr_src(0), * addr_dest(0); void * addr_src(0), * addr_dest(0);
int args(0); int args(0);
@@ -311,25 +271,26 @@ bool PIObject::piConnectU(PIObject * src, const PIString & sig, PIObject * dest_
if (addr_src == 0) { if (addr_src == 0) {
piCout << "[piConnectU] Error: can`t find suitable pair of event \"" << sig << "\" in class \"" << src->className() piCout << "[piConnectU] Error: can`t find suitable pair of event \"" << sig << "\" in class \"" << src->className()
<< "\" and handler \"" << hname << "\" in class \"" << dest_o->className() << "\"! (" << loc << ")"; << "\" and handler \"" << hname << "\" in class \"" << dest_o->className() << "\"! (" << loc << ")";
return false; return Connection();
} }
src->connections << PIObject::__Connection(addr_dest, addr_src, sig, dest_o, dest, args, performer); Connection conn(addr_dest, addr_src, sig, src, dest_o, dest, args, performer);
src->connections << conn;
if (que) performer->proc_event_queue = true; if (que) performer->proc_event_queue = true;
dest_o->connectors << src; dest_o->connectors << src;
//piCout << cc << cq << _ol.size();//"connect" << src << "->" << dest_o << ", dest.connectors.size() =" << dest_o->connectors.size(); //piCout << cc << cq << _ol.size();//"connect" << src << "->" << dest_o << ", dest.connectors.size() =" << dest_o->connectors.size();
return true; return conn;
} }
bool PIObject::piConnectLS(PIObject * src, const PIString & sig, std::function<void()> * f, const char * loc) { PIObject::Connection PIObject::piConnectLS(PIObject * src, const PIString & sig, std::function<void()> * f, const char * loc) {
if (src == 0) { if (src == 0) {
delete f; delete f;
return false; return Connection();
} }
if (!src->isPIObject()) { if (!src->isPIObject()) {
piCout << "[piConnectLS] \"" << sig << "\" -> [lambda] error: source object is not PIObject! (" << loc << ")"; piCout << "[piConnectLS] \"" << sig << "\" -> [lambda] error: source object is not PIObject! (" << loc << ")";
delete f; delete f;
return false; return Connection();
} }
PIMutexLocker ml(__meta_mutex()); PIMutexLocker ml(__meta_mutex());
PIMutexLocker mls(src->mutex_connect); PIMutexLocker mls(src->mutex_connect);
@@ -338,19 +299,19 @@ bool PIObject::piConnectLS(PIObject * src, const PIString & sig, std::function<v
if (m_src.isEmpty()) { if (m_src.isEmpty()) {
piCout << "[piConnectLS] Error: can`t find event \"" << sig << "\" in class \"" << src->className() << "\"! (" << loc << ")"; piCout << "[piConnectLS] Error: can`t find event \"" << sig << "\" in class \"" << src->className() << "\"! (" << loc << ")";
delete f; delete f;
return false; return Connection();
} }
if (m_src.size() != 1) { if (m_src.size() != 1) {
piCout << "[piConnectLS] Error: can`t connect overloaded event \"" << sig << "\" in class \"" << src->className() << "\"! (" << loc << ")"; piCout << "[piConnectLS] Error: can`t connect overloaded event \"" << sig << "\" in class \"" << src->className() << "\"! (" << loc << ")";
delete f; delete f;
return false; return Connection();
} }
PIObject::__Connection conn(0, m_src[0].addr, sig); PIObject::Connection conn(0, m_src[0].addr, sig, src);
//piCout << "found"; //piCout << "found";
conn.functor = f; conn.functor = f;
src->connections << conn; src->connections << conn;
//piCout << "finished"; //piCout << "finished";
return true; return conn;
} }
@@ -358,7 +319,7 @@ void PIObject::piDisconnect(PIObject * src, const PIString & sig, PIObject * des
PIMutexLocker _ml(src->mutex_connect); PIMutexLocker _ml(src->mutex_connect);
PIMutexLocker _mld(dest->mutex_connect, src != dest); PIMutexLocker _mld(dest->mutex_connect, src != dest);
for (int i = 0; i < src->connections.size_s(); ++i) { for (int i = 0; i < src->connections.size_s(); ++i) {
__Connection & cc(src->connections[i]); Connection & cc(src->connections[i]);
if (cc.event == sig && cc.dest_o == dest && cc.slot == ev_h) { if (cc.event == sig && cc.dest_o == dest && cc.slot == ev_h) {
src->connections[i].destroy(); src->connections[i].destroy();
src->connections.remove(i); src->connections.remove(i);
@@ -373,7 +334,7 @@ void PIObject::piDisconnect(PIObject * src, const PIString & sig, PIObject * des
PIMutexLocker _ml(src->mutex_connect); PIMutexLocker _ml(src->mutex_connect);
PIMutexLocker _mld(dest->mutex_connect, src != dest); PIMutexLocker _mld(dest->mutex_connect, src != dest);
for (int i = 0; i < src->connections.size_s(); ++i) { for (int i = 0; i < src->connections.size_s(); ++i) {
__Connection & cc(src->connections[i]); Connection & cc(src->connections[i]);
if (cc.event == sig && cc.dest_o == dest) { if (cc.event == sig && cc.dest_o == dest) {
src->connections[i].destroy(); src->connections[i].destroy();
src->connections.remove(i); src->connections.remove(i);
@@ -387,14 +348,14 @@ void PIObject::piDisconnect(PIObject * src, const PIString & sig, PIObject * des
void PIObject::piDisconnect(PIObject * src, const PIString & sig) { void PIObject::piDisconnect(PIObject * src, const PIString & sig) {
PIMutexLocker _ml(src->mutex_connect); PIMutexLocker _ml(src->mutex_connect);
for (int i = 0; i < src->connections.size_s(); ++i) { for (int i = 0; i < src->connections.size_s(); ++i) {
__Connection & cc(src->connections[i]); Connection & cc(src->connections[i]);
if (cc.event == sig) { if (cc.event == sig) {
PIObject * dest = cc.dest_o; PIObject * dest = cc.dest_o;
if (!dest) {
src->connections[i].destroy(); src->connections[i].destroy();
src->connections.remove(i); src->connections.remove(i);
i--; i--;
#if !defined(ANDROID) && !defined(MAC_OS) && !defined(FREERTOS) if (dest) {
#if !defined(ANDROID) && !defined(MAC_OS) && !defined(MICRO_PIP)
PIMutexLocker _mld(dest->mutex_connect, src != dest); PIMutexLocker _mld(dest->mutex_connect, src != dest);
#endif #endif
dest->updateConnectors(); dest->updateConnectors();
@@ -404,37 +365,38 @@ void PIObject::piDisconnect(PIObject * src, const PIString & sig) {
} }
void PIObject::piDisconnect(PIObject * src) { void PIObject::piDisconnectAll() {
src->deleted(src); PIMutexLocker _ml(mutex_connect);
PIMutexLocker _ml(src->mutex_connect); PIVector<PIObject * > cv = connectors.toVector();
PIVector<PIObject * > cv = src->connectors.toVector(); // piCout << "disconnect connectors =" << connectors.size();
piForeach (PIObject * o, cv) { piForeach (PIObject * o, cv) {
//piCout << "disconnect"<< src->className()<< o->className(); // piCout << "disconnect"<< src << o;
if (!o || (o == src)) continue; if (!o || (o == this)) continue;
if (!o->isPIObject()) continue; if (!o->isPIObject()) continue;
#if !defined(ANDROID) && !defined(MAC_OS) && !defined(FREERTOS) #if !defined(ANDROID) && !defined(MAC_OS) && !defined(MICRO_PIP)
PIMutexLocker _mld(o->mutex_connect, src != o); PIMutexLocker _mld(o->mutex_connect, this != o);
#endif #endif
PIVector<__Connection> & oc(o->connections); PIVector<Connection> & oc(o->connections);
for (int i = 0; i < oc.size_s(); ++i) { for (int i = 0; i < oc.size_s(); ++i) {
if (oc[i].functor) continue; if (oc[i].functor) continue;
//piCout << " check" << (void*)(oc[i].dest_o) << "==" << (void*)(src); //piCout << " check" << (void*)(oc[i].dest_o) << "==" << (void*)(src);
if (oc[i].dest_o == src) { if (oc[i].dest_o == this) {
oc[i].destroy(); oc[i].destroy();
oc.remove(i); oc.remove(i);
--i; --i;
} }
} }
} }
piForeachC (PIObject::__Connection & c, src->connections) { // piCout << "disconnect connections =" << connections.size();
piForeachC (PIObject::Connection & c, connections) {
if (c.functor) continue; if (c.functor) continue;
if (!c.dest_o) continue; if (!c.dest_o) continue;
if (!c.dest_o->isPIObject()) continue; if (!c.dest_o->isPIObject()) continue;
c.dest_o->connectors.remove(src); c.dest_o->connectors.remove(this);
} }
for (int i = 0; i < src->connections.size_s(); ++i) for (int i = 0; i < connections.size_s(); ++i)
src->connections[i].destroy(); connections[i].destroy();
src->connections.clear(); connections.clear();
} }
@@ -444,8 +406,8 @@ void PIObject::updateConnectors() {
PIMutexLocker _ml(mutexObjects()); PIMutexLocker _ml(mutexObjects());
piForeach (PIObject * o, objects()) { piForeach (PIObject * o, objects()) {
if (o == this) continue; if (o == this) continue;
PIVector<__Connection> & oc(o->connections); PIVector<Connection> & oc(o->connections);
piForeach (__Connection & c, oc) piForeach (Connection & c, oc)
if (c.dest == this) if (c.dest == this)
connectors << o; connectors << o;
} }
@@ -606,7 +568,7 @@ void PIObject::dump(const PIString & line_prefix) const {
PICout(PICoutManipulators::AddNewLine) << line_prefix << " connections {"; PICout(PICoutManipulators::AddNewLine) << line_prefix << " connections {";
PICout(PICoutManipulators::AddNewLine) << line_prefix << " count: " << connections.size_s(); PICout(PICoutManipulators::AddNewLine) << line_prefix << " count: " << connections.size_s();
//printf("dump %d connections\n",connections.size()); //printf("dump %d connections\n",connections.size());
piForeachC (__Connection & c, connections) { piForeachC (Connection & c, connections) {
PIObject * dst = c.dest_o; PIObject * dst = c.dest_o;
__MetaFunc ef = methodEH(c.signal); __MetaFunc ef = methodEH(c.signal);
PIString src(c.event); PIString src(c.event);
@@ -627,6 +589,7 @@ void PIObject::dump(const PIString & line_prefix) const {
} }
#ifndef MICRO_PIP
void dumpApplication() { void dumpApplication() {
PIMutexLocker _ml(PIObject::mutexObjects()); PIMutexLocker _ml(PIObject::mutexObjects());
//printf("dump application ...\n"); //printf("dump application ...\n");
@@ -653,7 +616,6 @@ void dumpApplication() {
} }
#ifndef FREERTOS
bool dumpApplicationToFile(const PIString & path) { bool dumpApplicationToFile(const PIString & path) {
PIFile f(path + "_tmp"); PIFile f(path + "_tmp");
f.setName("__S__DumpFile"); f.setName("__S__DumpFile");
@@ -679,41 +641,87 @@ void PIObject::__MetaData::addScope(const PIString & s, uint shash) {
} }
void PIObject::__Connection::destroy() {
void PIObject::Connection::destroy() {
if (functor) delete functor; if (functor) delete functor;
functor = nullptr; functor = nullptr;
} }
PIObject::Connection::Connection() {
slot = signal = dest = nullptr;
src_o = dest_o = performer = nullptr;
functor = nullptr;
eventID = 0;
args_count = 0;
}
bool PIObject::Connection::disconnect() {
if (!isValid() || !src_o) return false;
if (!src_o->isPIObject()) return false;
bool ndm = dest_o && (src_o != dest_o), ret = false, found = false;
if (dest_o) {
if (!dest_o->isPIObject()) ndm = false;
}
PIMutexLocker _ml(src_o->mutex_connect);
if (ndm) dest_o->mutex_connect.lock();
for (int i = 0; i < src_o->connections.size_s(); ++i) {
Connection & cc(src_o->connections[i]);
if (cc.eventID == eventID) {
if (dest_o && (cc.dest_o == dest_o)) {
if (cc.slot == slot)
found = true;
}
if (functor && (cc.functor == functor))
found = true;
}
if (found) {
src_o->connections[i].destroy();
src_o->connections.remove(i);
ret = true;
break;
}
}
if (dest_o) {
if (dest_o->isPIObject())
dest_o->updateConnectors();
}
if (ndm) dest_o->mutex_connect.unlock();
return ret;
}
PRIVATE_DEFINITION_START(PIObject::Deleter) PRIVATE_DEFINITION_START(PIObject::Deleter)
PIThread thread; PIThread thread;
PIConditionVariable cond_var; PIConditionVariable cond_var;
PIMutex cond_mutex, queue_mutex;
PIVector<PIObject*> obj_queue; PIVector<PIObject*> obj_queue;
PRIVATE_DEFINITION_END(PIObject::Deleter) PRIVATE_DEFINITION_END(PIObject::Deleter)
PIObject::Deleter::Deleter() { PIObject::Deleter::Deleter() {
//piCout << "Deleter start ..."; //piCout << "Deleter start ...";
stopping = started = posted = false; PRIVATE->thread.setSlot([this](){
CONNECTL(&(PRIVATE->thread), started, [this](){proc();}); PIVector<PIObject*> oq;
PRIVATE->thread.startOnce(); PRIVATE->thread.lock();
while (!started) while(PRIVATE->obj_queue.isEmpty()) PRIVATE->cond_var.wait(PRIVATE->thread.mutex());
piMSleep(1); oq.swap(PRIVATE->obj_queue);
PRIVATE->thread.unlock();
for (PIObject * o : oq) deleteObject(o);
});
PRIVATE->thread.start();
} }
PIObject::Deleter::~Deleter() { PIObject::Deleter::~Deleter() {
//piCout << "~Deleter ..."; //piCout << "~Deleter ...";
stopping = true; PRIVATE->thread.stop();
PRIVATE->cond_var.notifyAll(); PRIVATE->cond_var.notifyAll();
#ifndef WINDOWS PRIVATE->thread.waitForFinish();
while (PRIVATE->thread.isRunning()) for (PIObject * o : PRIVATE->obj_queue) deleteObject(o);
piMSleep(1);
#endif
deleteAll();
//piCout << "~Deleter ok"; //piCout << "~Deleter ok";
} }
@@ -727,58 +735,22 @@ PIObject::Deleter * PIObject::Deleter::instance() {
void PIObject::Deleter::post(PIObject * o) { void PIObject::Deleter::post(PIObject * o) {
if (!o->isPIObject()) return; if (!o->isPIObject()) return;
//piCout << "[Deleter] post" << o << "..."; //piCout << "[Deleter] post" << o << "...";
PRIVATE->queue_mutex.lock(); PRIVATE->thread.lock();
if (!PRIVATE->obj_queue.contains(o)) if (!PRIVATE->obj_queue.contains(o)) {
PRIVATE->obj_queue << o; PRIVATE->obj_queue << o;
PRIVATE->queue_mutex.unlock();
PRIVATE->cond_var.notifyAll(); PRIVATE->cond_var.notifyAll();
posted = true; }
PRIVATE->thread.unlock();
//piCout << "[Deleter] post" << o << "done"; //piCout << "[Deleter] post" << o << "done";
} }
void PIObject::Deleter::proc() {
//piCout << "[Deleter] proc start";
while (!stopping) {
//piMSleep(1);
//piCout << "[Deleter] proc wait ...";
if (posted) {
posted = false;
started = true;
} else {
PRIVATE->cond_mutex.lock();
started = true;
PRIVATE->cond_var.wait(PRIVATE->cond_mutex);
PRIVATE->cond_mutex.unlock();
}
//piCout << "[Deleter] proc wait done";
deleteAll();
}
//piCout << "[Deleter] proc end ok";
}
void PIObject::Deleter::deleteAll() {
PIVector<PIObject*> oq;
PRIVATE->queue_mutex.lock();
oq = PRIVATE->obj_queue;
//piCout << "[Deleter] deleteAll" << oq.size_s() << "...";
PRIVATE->obj_queue.clear();
PRIVATE->queue_mutex.unlock();
piForeach (PIObject * o, oq)
deleteObject(o);
}
void PIObject::Deleter::deleteObject(PIObject * o) { void PIObject::Deleter::deleteObject(PIObject * o) {
//piCout << "[Deleter] delete" << (uintptr_t)o << "..."; //piCout << "[Deleter] delete" << (uintptr_t)o << "...";
if (o->isPIObject()) { if (o->isPIObject()) {
//piCout << "[Deleter] delete" << (uintptr_t)o << "wait atomic ..."; //piCout << "[Deleter] delete" << (uintptr_t)o << "wait atomic ...";
while (o->isInEvent()) { while (o->isInEvent()) piMinSleep();
piMSleep(1);
}
//piCout << "[Deleter] delete" << (uintptr_t)o << "wait atomic done"; //piCout << "[Deleter] delete" << (uintptr_t)o << "wait atomic done";
if (o->isPIObject())
delete o; delete o;
} }
//piCout << "[Deleter] delete" << (uintptr_t)o << "done"; //piCout << "[Deleter] delete" << (uintptr_t)o << "done";

View File

@@ -37,11 +37,13 @@
typedef void (*Handler)(void * ); typedef void (*Handler)(void * );
class PIP_EXPORT PIObject { class PIP_EXPORT PIObject {
#ifndef MICRO_PIP
friend class PIObjectManager; friend class PIObjectManager;
friend void dumpApplication(); friend void dumpApplication();
friend class PIIntrospection;
#endif
typedef PIObject __PIObject__; typedef PIObject __PIObject__;
typedef void __Parent__; typedef void __Parent__;
friend class PIIntrospection;
public: public:
NO_COPY_CLASS(PIObject) NO_COPY_CLASS(PIObject)
@@ -50,6 +52,54 @@ public:
virtual ~PIObject(); virtual ~PIObject();
//! Helper class for obtain info about if connection successful and disconnect single connection
class PIP_EXPORT Connection {
friend class PIObject;
Connection(void * sl, void * si, const PIString & e = PIString(),
PIObject * s_o = nullptr, PIObject * d_o = nullptr,
void * d = nullptr, int ac = 0, PIObject * p = nullptr) {
slot = sl;
signal = si;
event = e;
eventID = e.hash();
src_o = s_o;
dest_o = d_o;
dest = d;
args_count = ac;
performer = p;
functor = 0;
}
void destroy();
void * slot;
void * signal;
std::function<void()> * functor;
PIString event;
uint eventID;
PIObject * src_o, * dest_o;
PIObject * performer;
void * dest;
int args_count;
public:
//! Contructs invalid %Connection
Connection();
//! Returns if %Connection is valid
bool isValid() const {return signal;}
//! Returns source object
PIObject * sourceObject() const {return src_o;}
//! Returns destination object or nullptr if this is lambda connection
PIObject * destinationObject() const {return dest_o;}
//! Returns performer object or nullptr if this is non-queued connection
PIObject * performerObject() const {return performer;}
//! Disconnect this %Connection, returns if operation successful
bool disconnect();
};
private: private:
uint _signature_; uint _signature_;
@@ -141,33 +191,38 @@ public:
PIString methodEHFromAddr(const void * addr) const; PIString methodEHFromAddr(const void * addr) const;
// / Direct connect // / Direct connect
static void piConnect(PIObject * src, const PIString & sig, PIObject * dest_o, void * dest, void * ev_h, void * e_h, int args, const char * loc); static PIObject::Connection piConnect(PIObject * src, const PIString & sig, PIObject * dest_o, void * dest, void * ev_h, void * e_h, int args, const char * loc);
static bool piConnectU(PIObject * src, const PIString & sig, PIObject * dest_o, void * dest, const PIString & hname, const char * loc, PIObject * performer = 0); static PIObject::Connection piConnectU(PIObject * src, const PIString & sig, PIObject * dest_o, void * dest, const PIString & hname, const char * loc, PIObject * performer = 0);
static bool piConnectLS(PIObject * src, const PIString & sig, std::function<void()> * f, const char * loc); static PIObject::Connection piConnectLS(PIObject * src, const PIString & sig, std::function<void()> * f, const char * loc);
template <typename INPUT, typename... TYPES> template <typename PIINPUT, typename... PITYPES>
static std::function<void()> * __newFunctor(void(*stat_handler)(void*,TYPES...), INPUT functor) { static std::function<void()> * __newFunctor(void(*stat_handler)(void*,PITYPES...), PIINPUT functor) {
return (std::function<void()>*)(new std::function<void(TYPES...)>(functor)); return (std::function<void()>*)(new std::function<void(PITYPES...)>(functor));
} }
// / Through names and mixed
static void piConnect(const PIString & src, const PIString & sig, void * dest, void * ev_h); //! Disconnect object from all connections with event name "sig", connected to destination object "dest" and handler "ev_h"
static void piConnect(PIObject * src, const PIString & sig, const PIString & dest, void * ev_h); void piDisconnect(const PIString & sig, PIObject * dest, void * ev_h) {piDisconnect(this, sig, dest, ev_h);}
static void piConnect(const PIString & src, const PIString & sig, const PIString & dest, void * ev_h);
//! Disconnect object from all connections with event name "sig", connected to destination object "dest"
void piDisconnect(const PIString & sig, PIObject * dest) {piDisconnect(this, sig, dest);}
//! Disconnect object from all connections with event name "sig"
void piDisconnect(const PIString & sig) {piDisconnect(this, sig);}
//! Disconnect object "src" from all connections with event name "sig", connected to destination object "dest" and handler "ev_h"
static void piDisconnect(PIObject * src, const PIString & sig, PIObject * dest, void * ev_h); static void piDisconnect(PIObject * src, const PIString & sig, PIObject * dest, void * ev_h);
//! Disconnect object "src" from all connections with event name "sig", connected to destination object "dest"
static void piDisconnect(PIObject * src, const PIString & sig, PIObject * dest); static void piDisconnect(PIObject * src, const PIString & sig, PIObject * dest);
//! Disconnect object "src" from all connections with event name "sig" //! Disconnect object "src" from all connections with event name "sig"
static void piDisconnect(PIObject * src, const PIString & sig); static void piDisconnect(PIObject * src, const PIString & sig);
//! Disconnect object "src" from all connections, i.e. all connections where object "src" is emitter
static void piDisconnect(PIObject * src);
// / Raise events // / Raise events
static void raiseEvent(PIObject * sender, const uint eventID) { static void raiseEvent(PIObject * sender, const uint eventID) {
for (int j = 0; j < sender->connections.size_s(); ++j) { for (int j = 0; j < sender->connections.size_s(); ++j) {
__Connection i(sender->connections[j]); Connection i(sender->connections[j]);
if (i.eventID != eventID) continue; if (i.eventID != eventID) continue;
if (i.functor) { if (i.functor) {
(*(i.functor))(); (*(i.functor))();
@@ -196,7 +251,7 @@ public:
template <typename T0> template <typename T0>
static void raiseEvent(PIObject * sender, const uint eventID, const T0 & v0 = T0()) { static void raiseEvent(PIObject * sender, const uint eventID, const T0 & v0 = T0()) {
for (int j = 0; j < sender->connections.size_s(); ++j) { for (int j = 0; j < sender->connections.size_s(); ++j) {
__Connection i(sender->connections[j]); Connection i(sender->connections[j]);
if (i.eventID != eventID) continue; if (i.eventID != eventID) continue;
if (i.functor) { if (i.functor) {
(*((std::function<void(T0)>*)i.functor))(v0); (*((std::function<void(T0)>*)i.functor))(v0);
@@ -227,7 +282,7 @@ public:
template <typename T0, typename T1> template <typename T0, typename T1>
static void raiseEvent(PIObject * sender, const uint eventID, const T0 & v0 = T0(), const T1 & v1 = T1()) { static void raiseEvent(PIObject * sender, const uint eventID, const T0 & v0 = T0(), const T1 & v1 = T1()) {
for (int j = 0; j < sender->connections.size_s(); ++j) { for (int j = 0; j < sender->connections.size_s(); ++j) {
__Connection i(sender->connections[j]); Connection i(sender->connections[j]);
if (i.eventID != eventID) continue; if (i.eventID != eventID) continue;
if (i.functor) { if (i.functor) {
(*((std::function<void(T0, T1)>*)i.functor))(v0, v1); (*((std::function<void(T0, T1)>*)i.functor))(v0, v1);
@@ -262,7 +317,7 @@ public:
template <typename T0, typename T1, typename T2> template <typename T0, typename T1, typename T2>
static void raiseEvent(PIObject * sender, const uint eventID, const T0 & v0 = T0(), const T1 & v1 = T1(), const T2 & v2 = T2()) { static void raiseEvent(PIObject * sender, const uint eventID, const T0 & v0 = T0(), const T1 & v1 = T1(), const T2 & v2 = T2()) {
for (int j = 0; j < sender->connections.size_s(); ++j) { for (int j = 0; j < sender->connections.size_s(); ++j) {
__Connection i(sender->connections[j]); Connection i(sender->connections[j]);
if (i.eventID != eventID) continue; if (i.eventID != eventID) continue;
if (i.functor) { if (i.functor) {
(*((std::function<void(T0, T1, T2)>*)i.functor))(v0, v1, v2); (*((std::function<void(T0, T1, T2)>*)i.functor))(v0, v1, v2);
@@ -299,7 +354,7 @@ public:
template <typename T0, typename T1, typename T2, typename T3> template <typename T0, typename T1, typename T2, typename T3>
static void raiseEvent(PIObject * sender, const uint eventID, const T0 & v0 = T0(), const T1 & v1 = T1(), const T2 & v2 = T2(), const T3 & v3 = T3()) { static void raiseEvent(PIObject * sender, const uint eventID, const T0 & v0 = T0(), const T1 & v1 = T1(), const T2 & v2 = T2(), const T3 & v3 = T3()) {
for (int j = 0; j < sender->connections.size_s(); ++j) { for (int j = 0; j < sender->connections.size_s(); ++j) {
__Connection i(sender->connections[j]); Connection i(sender->connections[j]);
if (i.eventID != eventID) continue; if (i.eventID != eventID) continue;
if (i.functor) { if (i.functor) {
(*((std::function<void(T0, T1, T2, T3)>*)i.functor))(v0, v1, v2, v3); (*((std::function<void(T0, T1, T2, T3)>*)i.functor))(v0, v1, v2, v3);
@@ -428,30 +483,6 @@ protected:
private: private:
struct __Connection {
__Connection(void * sl = 0, void * si = 0, const PIString & e = PIString(), PIObject * d_o = 0, void * d = 0, int ac = 0, PIObject * p = 0) {
slot = sl;
signal = si;
event = e;
eventID = e.hash();
dest_o = d_o;
dest = d;
args_count = ac;
performer = p;
functor = 0;
}
void destroy();
void * slot;
void * signal;
std::function<void()> * functor;
PIString event;
uint eventID;
PIObject * dest_o;
PIObject * performer;
void * dest;
int args_count;
};
struct __QueuedEvent { struct __QueuedEvent {
__QueuedEvent(void * sl = 0, void * d = 0, PIObject * d_o = 0, PIObject * s = 0, const PIVector<PIVariantSimple> & v = PIVector<PIVariantSimple>()) { __QueuedEvent(void * sl = 0, void * d = 0, PIObject * d_o = 0, PIObject * s = 0, const PIVector<PIVariantSimple> & v = PIVector<PIVariantSimple>()) {
slot = sl; slot = sl;
@@ -474,10 +505,7 @@ private:
static Deleter * instance(); static Deleter * instance();
void post(PIObject * o); void post(PIObject * o);
private: private:
void proc();
void deleteAll();
void deleteObject(PIObject * o); void deleteObject(PIObject * o);
std::atomic_bool stopping, started, posted;
PRIVATE_DECLARATION(PIP_EXPORT) PRIVATE_DECLARATION(PIP_EXPORT)
}; };
@@ -488,6 +516,8 @@ private:
PIVector<__MetaFunc> findEH(const PIString & name) const; PIVector<__MetaFunc> findEH(const PIString & name) const;
__MetaFunc methodEH(const void * addr) const; __MetaFunc methodEH(const void * addr) const;
void updateConnectors(); void updateConnectors();
void piDisconnectAll();
void postQueuedEvent(const __QueuedEvent & e); void postQueuedEvent(const __QueuedEvent & e);
void eventBegin() {in_event_cnt++;} void eventBegin() {in_event_cnt++;}
void eventEnd () {in_event_cnt--;} void eventEnd () {in_event_cnt--;}
@@ -500,7 +530,7 @@ private:
static void callAddrV(void * slot, void * obj, int args, const PIVector<PIVariantSimple> & vl); static void callAddrV(void * slot, void * obj, int args, const PIVector<PIVariantSimple> & vl);
PIVector<__Connection> connections; PIVector<Connection> connections;
PIMap<uint, PIPair<PIString, PIVariant> > properties_; PIMap<uint, PIPair<PIString, PIVariant> > properties_;
PISet<PIObject * > connectors; PISet<PIObject * > connectors;
PIVector<__QueuedEvent> events_queue; PIVector<__QueuedEvent> events_queue;
@@ -511,8 +541,9 @@ private:
}; };
#ifndef MICRO_PIP
PIP_EXPORT void dumpApplication(); PIP_EXPORT void dumpApplication();
PIP_EXPORT bool dumpApplicationToFile(const PIString & path); PIP_EXPORT bool dumpApplicationToFile(const PIString & path);
#endif
#endif // PIOBJECT_H #endif // PIOBJECT_H

View File

@@ -102,28 +102,36 @@
/// \relatesalso PIObject @brief connect event \"event\" from object \"src\" to event handler \"handler\". \"Event\" and \"handler\" must has equal argument lists. /// \relatesalso PIObject @brief connect event \"event\" from object \"src\" to event handler \"handler\". \"Event\" and \"handler\" must has equal argument lists.
/// Returns PIObject::Connection
#define CONNECTU(src, event, dest, handler) #define CONNECTU(src, event, dest, handler)
/// \relatesalso PIObject @brief connect event \"event\" from object \"src\" to event handler \"handler\". /// \relatesalso PIObject @brief connect event \"event\" from object \"src\" to event handler \"handler\".
/// Event handler will be executed by \"performer\". \"Event\" and \"handler\" must has equal argument lists. /// Event handler will be executed by \"performer\". \"Event\" and \"handler\" must has equal argument lists.
/// Returns PIObject::Connection
#define CONNECTU_QUEUED(src, event, dest, handler, performer) #define CONNECTU_QUEUED(src, event, dest, handler, performer)
/// \relatesalso PIObject @brief connect event \"event\" from object \"src\" to lambda-expression \"functor\". \"Event\" and \"functor\" must has equal argument lists. /// \relatesalso PIObject @brief connect event \"event\" from object \"src\" to lambda-expression \"functor\". \"Event\" and \"functor\" must has equal argument lists.
/// Returns PIObject::Connection
#define CONNECTL(src, event, functor) #define CONNECTL(src, event, functor)
/// \relatesalso PIObject @brief connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" with check of event and handler exists /// \relatesalso PIObject @brief connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" with check of event and handler exists
/// Returns PIObject::Connection
#define CONNECT0(ret, src, event, dest, handler) #define CONNECT0(ret, src, event, dest, handler)
/// \relatesalso PIObject @brief connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" with check of event and handler exists /// \relatesalso PIObject @brief connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" with check of event and handler exists
/// Returns PIObject::Connection
#define CONNECT1(ret, type0, src, event, dest, handler) #define CONNECT1(ret, type0, src, event, dest, handler)
/// \relatesalso PIObject @brief connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" with check of event and handler exists /// \relatesalso PIObject @brief connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" with check of event and handler exists
/// Returns PIObject::Connection
#define CONNECT2(ret, type0, type1, src, event, dest, handler) #define CONNECT2(ret, type0, type1, src, event, dest, handler)
/// \relatesalso PIObject @brief connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" with check of event and handler exists /// \relatesalso PIObject @brief connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" with check of event and handler exists
/// Returns PIObject::Connection
#define CONNECT3(ret, type0, type1, type2, src, event, dest, handler) #define CONNECT3(ret, type0, type1, type2, src, event, dest, handler)
/// \relatesalso PIObject @brief connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" with check of event and handler exists /// \relatesalso PIObject @brief connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" with check of event and handler exists.
/// Returns PIObject::Connection
#define CONNECT4(ret, type0, type1, type2, type3, src, event, dest, handler) #define CONNECT4(ret, type0, type1, type2, type3, src, event, dest, handler)
/// \relatesalso PIObject @brief CONNECT is synonym of CONNECT0 /// \relatesalso PIObject @brief CONNECT is synonym of CONNECT0

View File

@@ -19,7 +19,11 @@
#include "piincludes_p.h" #include "piincludes_p.h"
#include "pitime.h" #include "pitime.h"
#include "pisystemtests.h" #ifndef MICRO_PIP
# include "pisystemtests.h"
#elif defined(ARDUINO)
# include <Arduino.h>
#endif
#ifdef WINDOWS #ifdef WINDOWS
extern FILETIME __pi_ftjan1970; extern FILETIME __pi_ftjan1970;
long long __PIQueryPerformanceCounter() {LARGE_INTEGER li; QueryPerformanceCounter(&li); return li.QuadPart;} long long __PIQueryPerformanceCounter() {LARGE_INTEGER li; QueryPerformanceCounter(&li); return li.QuadPart;}
@@ -31,9 +35,8 @@
//# include <crt_externs.h> //# include <crt_externs.h>
extern clock_serv_t __pi_mac_clock; extern clock_serv_t __pi_mac_clock;
#endif #endif
#ifdef FREERTOS #ifdef MICRO_PIP
# include "freertos/FreeRTOS.h" # include <sys/time.h>
# include "freertos/task.h"
#endif #endif
/*! \class PISystemTime /*! \class PISystemTime
@@ -252,24 +255,29 @@ PISystemTime PISystemTime::current(bool precise_but_not_system) {
ullong lt = ullong(sft.dwHighDateTime) * 0x100000000U + ullong(sft.dwLowDateTime); ullong lt = ullong(sft.dwHighDateTime) * 0x100000000U + ullong(sft.dwLowDateTime);
return PISystemTime(lt / 10000000U, (lt % 10000000U) * 100U); return PISystemTime(lt / 10000000U, (lt % 10000000U) * 100U);
} }
#else #elif defined(MAC_OS)
# ifdef MAC_OS
mach_timespec_t t_cur; mach_timespec_t t_cur;
clock_get_time(__pi_mac_clock, &t_cur); clock_get_time(__pi_mac_clock, &t_cur);
# else #elif defined(MICRO_PIP)
# ifdef FREERTOS
timespec t_cur; timespec t_cur;
# ifdef ARDUINO
static const uint32_t offSetSinceEpoch_s = 1581897605UL;
uint32_t mt = millis();
t_cur.tv_sec = offSetSinceEpoch_s + (mt / 1000);
t_cur.tv_nsec = (mt - (mt / 1000)) * 1000000UL;
# else
timeval tv; timeval tv;
tv.tv_sec = 0; tv.tv_sec = 0;
tv.tv_usec = 0; tv.tv_usec = 0;
gettimeofday(&tv, NULL); gettimeofday(&tv, NULL);
t_cur.tv_sec = tv.tv_sec; t_cur.tv_sec = tv.tv_sec;
t_cur.tv_nsec = tv.tv_usec * 1000; t_cur.tv_nsec = tv.tv_usec * 1000;
# else # endif
#else
timespec t_cur; timespec t_cur;
clock_gettime(precise_but_not_system ? CLOCK_MONOTONIC : 0, &t_cur); clock_gettime(precise_but_not_system ? CLOCK_MONOTONIC : 0, &t_cur);
# endif #endif
# endif #ifndef WINDOWS
return PISystemTime(t_cur.tv_sec, t_cur.tv_nsec); return PISystemTime(t_cur.tv_sec, t_cur.tv_nsec);
#endif #endif
} }
@@ -407,22 +415,38 @@ PITimeMeasurer::PITimeMeasurer() {
double PITimeMeasurer::elapsed_n() const { double PITimeMeasurer::elapsed_n() const {
return (PISystemTime::current(true) - t_st).toNanoseconds() - PISystemTests::time_elapsed_ns; return (PISystemTime::current(true) - t_st).toNanoseconds()
#ifndef MICRO_PIP
- PISystemTests::time_elapsed_ns
#endif
;
} }
double PITimeMeasurer::elapsed_u() const { double PITimeMeasurer::elapsed_u() const {
return (PISystemTime::current(true) - t_st).toMicroseconds() - PISystemTests::time_elapsed_ns / 1.E+3; return (PISystemTime::current(true) - t_st).toMicroseconds()
#ifndef MICRO_PIP
- PISystemTests::time_elapsed_ns / 1.E+3
#endif
;
} }
double PITimeMeasurer::elapsed_m() const { double PITimeMeasurer::elapsed_m() const {
return (PISystemTime::current(true) - t_st).toMilliseconds() - PISystemTests::time_elapsed_ns / 1.E+6; return (PISystemTime::current(true) - t_st).toMilliseconds()
#ifndef MICRO_PIP
- PISystemTests::time_elapsed_ns / 1.E+6
#endif
;
} }
double PITimeMeasurer::elapsed_s() const { double PITimeMeasurer::elapsed_s() const {
return (PISystemTime::current(true) - t_st).toSeconds() - PISystemTests::time_elapsed_ns / 1.E+9; return (PISystemTime::current(true) - t_st).toSeconds()
#ifndef MICRO_PIP
- PISystemTests::time_elapsed_ns / 1.E+9
#endif
;
} }
@@ -469,13 +493,3 @@ PICout operator <<(PICout s, const PIDateTime & v) {
return s; return s;
} }
#ifdef WINDOWS
void msleep(int msecs) {Sleep(msecs);}
#else
# ifdef FREERTOS
void msleep(int msecs) {vTaskDelay(msecs / portTICK_PERIOD_MS);}
# else
void msleep(int msecs) {usleep(msecs * 1000);}
# endif
#endif

View File

@@ -29,8 +29,6 @@
#ifdef QNX #ifdef QNX
# include <time.h> # include <time.h>
#endif #endif
//! @brief Sleep for "msecs" milliseconds
PIP_EXPORT void msleep(int msecs);
/*! @brief Precise sleep for "usecs" microseconds /*! @brief Precise sleep for "usecs" microseconds
* \details This function consider \c "usleep" offset * \details This function consider \c "usleep" offset
@@ -48,6 +46,8 @@ inline void piMSleep(double msecs) {piUSleep(int(msecs * 1000.));} // on !Window
* \details This function exec \a piUSleep (msecs * 1000000). */ * \details This function exec \a piUSleep (msecs * 1000000). */
inline void piSleep(double secs) {piUSleep(int(secs * 1000000.));} // on !Windows consider constant "usleep" offset inline void piSleep(double secs) {piUSleep(int(secs * 1000000.));} // on !Windows consider constant "usleep" offset
//! Shortest available on current system sleep
inline void piMinSleep() {piMSleep(PIP_MIN_MSLEEP);}

View File

@@ -619,6 +619,16 @@ PIRectd PIVariant::toRect() const {
} }
/** @brief Returns variant content as rect
* \details In case of PILined type returns line value. \n
* In case of other types returns empty PILined. */
PILined PIVariant::toLine() const {
PIByteArray ba(_content);
if (_type == PIVariant::pivLine) {PILined r; ba >> r; return r;}
return PILined();
}
/** @brief Returns variant content as math vector /** @brief Returns variant content as math vector
* \details In case of PIMathVectord type returns rect value. \n * \details In case of PIMathVectord type returns rect value. \n
* In case of other types returns empty PIMathVectord. */ * In case of other types returns empty PIMathVectord. */

View File

@@ -234,11 +234,12 @@ public:
pivFile /** PIVariantTypes::File */ , pivFile /** PIVariantTypes::File */ ,
pivDir /** PIVariantTypes::Dir */ , pivDir /** PIVariantTypes::Dir */ ,
pivColor /** PIVariantTypes::Color */ , pivColor /** PIVariantTypes::Color */ ,
pivPoint /** PIPoint */ , pivPoint /** PIPoint<double> */ ,
pivRect /** PIRect */ , pivRect /** PIRect<double> */ ,
pivIODevice /** PIVariantTypes::IODevice */ , pivIODevice /** PIVariantTypes::IODevice */ ,
pivMathVector /** PIMathVectord */ , pivMathVector /** PIMathVector<double> */ ,
pivMathMatrix /** PIMathMatrixd */ , pivMathMatrix /** PIMathMatrix<double> */ ,
pivLine /** PILine<double> */ ,
pivCustom /** Custom */ = 0xFF pivCustom /** Custom */ = 0xFF
}; };
@@ -333,6 +334,9 @@ public:
//! Constructs variant from rect //! Constructs variant from rect
PIVariant(const PIRectd & v) {initType(v);} PIVariant(const PIRectd & v) {initType(v);}
//! Constructs variant from line
PIVariant(const PILined & v) {initType(v);}
//! Constructs variant from MathVector //! Constructs variant from MathVector
PIVariant(const PIMathVectord & v) {initType(v);} PIVariant(const PIMathVectord & v) {initType(v);}
@@ -424,6 +428,9 @@ public:
//! Set variant content and type to rect //! Set variant content and type to rect
void setValue(const PIRectd & v) {initType(v);} void setValue(const PIRectd & v) {initType(v);}
//! Set variant content and type to line
void setValue(const PILined & v) {initType(v);}
//! Set variant content and type to math vector //! Set variant content and type to math vector
void setValue(const PIMathVectord & v) {initType(v);} void setValue(const PIMathVectord & v) {initType(v);}
@@ -456,6 +463,7 @@ public:
PIVariantTypes::IODevice toIODevice() const; PIVariantTypes::IODevice toIODevice() const;
PIPointd toPoint() const; PIPointd toPoint() const;
PIRectd toRect() const; PIRectd toRect() const;
PILined toLine() const;
PIMathVectord toMathVector() const; PIMathVectord toMathVector() const;
PIMathMatrixd toMathMatrix() const; PIMathMatrixd toMathMatrix() const;
@@ -527,6 +535,8 @@ public:
//! Assign operator //! Assign operator
PIVariant & operator =(const PIRectd & v) {setValue(v); return *this;} PIVariant & operator =(const PIRectd & v) {setValue(v); return *this;}
//! Assign operator //! Assign operator
PIVariant & operator =(const PILined & v) {setValue(v); return *this;}
//! Assign operator
PIVariant & operator =(const PIMathVectord & v) {setValue(v); return *this;} PIVariant & operator =(const PIMathVectord & v) {setValue(v); return *this;}
//! Assign operator //! Assign operator
PIVariant & operator =(const PIMathMatrixd & v) {setValue(v); return *this;} PIVariant & operator =(const PIMathMatrixd & v) {setValue(v); return *this;}
@@ -661,6 +671,7 @@ template<> inline PIVariantTypes::Color PIVariant::value() const {return toColor
template<> inline PIVariantTypes::IODevice PIVariant::value() const {return toIODevice();} template<> inline PIVariantTypes::IODevice PIVariant::value() const {return toIODevice();}
template<> inline PIPointd PIVariant::value() const {return toPoint();} template<> inline PIPointd PIVariant::value() const {return toPoint();}
template<> inline PIRectd PIVariant::value() const {return toRect();} template<> inline PIRectd PIVariant::value() const {return toRect();}
template<> inline PILined PIVariant::value() const {return toLine();}
template<> inline PIVariant PIVariant::value() const {return *this;} template<> inline PIVariant PIVariant::value() const {return *this;}
template<> inline PIVariant PIVariant::fromValue(const bool & v) {return PIVariant(v);} template<> inline PIVariant PIVariant::fromValue(const bool & v) {return PIVariant(v);}
@@ -690,6 +701,7 @@ template<> inline PIVariant PIVariant::fromValue(const PIVariantTypes::Color & v
template<> inline PIVariant PIVariant::fromValue(const PIVariantTypes::IODevice & v) {return PIVariant(v);} template<> inline PIVariant PIVariant::fromValue(const PIVariantTypes::IODevice & v) {return PIVariant(v);}
template<> inline PIVariant PIVariant::fromValue(const PIPointd & v) {return PIVariant(v);} template<> inline PIVariant PIVariant::fromValue(const PIPointd & v) {return PIVariant(v);}
template<> inline PIVariant PIVariant::fromValue(const PIRectd & v) {return PIVariant(v);} template<> inline PIVariant PIVariant::fromValue(const PIRectd & v) {return PIVariant(v);}
template<> inline PIVariant PIVariant::fromValue(const PILined & v) {return PIVariant(v);}
template<> inline PIVariant PIVariant::fromValue(const PIMathVectord & v) {return PIVariant(v);} template<> inline PIVariant PIVariant::fromValue(const PIMathVectord & v) {return PIVariant(v);}
template<> inline PIVariant PIVariant::fromValue(const PIMathMatrixd & v) {return PIVariant(v);} template<> inline PIVariant PIVariant::fromValue(const PIMathMatrixd & v) {return PIVariant(v);}
template<> inline PIVariant PIVariant::fromValue(const PIVariant & v) {return PIVariant(v);} template<> inline PIVariant PIVariant::fromValue(const PIVariant & v) {return PIVariant(v);}
@@ -721,6 +733,7 @@ template<> inline PIVariant::Type PIVariant::getType<PIVariantTypes::Color>() {r
template<> inline PIVariant::Type PIVariant::getType<PIVariantTypes::IODevice>() {return PIVariant::pivIODevice;} template<> inline PIVariant::Type PIVariant::getType<PIVariantTypes::IODevice>() {return PIVariant::pivIODevice;}
template<> inline PIVariant::Type PIVariant::getType<PIPointd>() {return PIVariant::pivPoint;} template<> inline PIVariant::Type PIVariant::getType<PIPointd>() {return PIVariant::pivPoint;}
template<> inline PIVariant::Type PIVariant::getType<PIRectd>() {return PIVariant::pivRect;} template<> inline PIVariant::Type PIVariant::getType<PIRectd>() {return PIVariant::pivRect;}
template<> inline PIVariant::Type PIVariant::getType<PILined>() {return PIVariant::pivLine;}
template<> inline PIVariant::Type PIVariant::getType<PIMathVectord>() {return PIVariant::pivMathVector;} template<> inline PIVariant::Type PIVariant::getType<PIMathVectord>() {return PIVariant::pivMathVector;}
template<> inline PIVariant::Type PIVariant::getType<PIMathMatrixd>() {return PIVariant::pivMathMatrix;} template<> inline PIVariant::Type PIVariant::getType<PIMathMatrixd>() {return PIVariant::pivMathMatrix;}
@@ -751,6 +764,7 @@ REGISTER_NS_VARIANT(PIVariantTypes, Color)
REGISTER_NS_VARIANT(PIVariantTypes, IODevice) REGISTER_NS_VARIANT(PIVariantTypes, IODevice)
REGISTER_VARIANT(PIPointd) REGISTER_VARIANT(PIPointd)
REGISTER_VARIANT(PIRectd) REGISTER_VARIANT(PIRectd)
REGISTER_VARIANT(PILined)
REGISTER_VARIANT(PIMathVectord) REGISTER_VARIANT(PIMathVectord)
REGISTER_VARIANT(PIMathMatrixd) REGISTER_VARIANT(PIMathMatrixd)

View File

@@ -27,7 +27,7 @@
#include "pistring.h" #include "pistring.h"
#include <typeinfo> #include <typeinfo>
#ifdef PIP_FREERTOS #ifdef MICRO_PIP
#include "pivariant.h" #include "pivariant.h"
#endif #endif
@@ -48,7 +48,7 @@ template<typename T>
class __VariantFunctions__: public __VariantFunctionsBase__ { class __VariantFunctions__: public __VariantFunctionsBase__ {
public: public:
__VariantFunctionsBase__ * instance() final {static __VariantFunctions__<T> ret; return &ret;} __VariantFunctionsBase__ * instance() final {static __VariantFunctions__<T> ret; return &ret;}
#ifdef PIP_FREERTOS #ifdef MICRO_PIP
PIString typeName() const final {static PIString ret(PIVariant(T()).typeName()); return ret;} PIString typeName() const final {static PIString ret(PIVariant(T()).typeName()); return ret;}
#else #else
PIString typeName() const final {static PIString ret(typeid(T).name()); return ret;} PIString typeName() const final {static PIString ret(typeid(T).name()); return ret;}

View File

@@ -19,8 +19,9 @@
#include "pivarianttypes.h" #include "pivarianttypes.h"
#include "pipropertystorage.h" #include "pipropertystorage.h"
#include "piiodevice.h" #ifndef MICRO_PIP
# include "piiodevice.h"
#endif
int PIVariantTypes::Enum::selectedValue() const { int PIVariantTypes::Enum::selectedValue() const {
piForeachC (Enumerator & e, enum_list) piForeachC (Enumerator & e, enum_list)
@@ -83,9 +84,12 @@ PIStringList PIVariantTypes::Enum::names() const {
PIVariantTypes::IODevice::IODevice() { PIVariantTypes::IODevice::IODevice() {
#ifndef MICRO_PIP
mode = PIIODevice::ReadWrite; mode = PIIODevice::ReadWrite;
#else
mode = 0; // TODO: PIIODevice for MICRO PIP
#endif // MICRO_PIP
options = 0; options = 0;
} }
@@ -112,12 +116,14 @@ PIString PIVariantTypes::IODevice::toPICout() const {
if (mode & 2) {s << "w"; ++rwc;} if (mode & 2) {s << "w"; ++rwc;}
if (rwc == 1) s << "o"; if (rwc == 1) s << "o";
s << ", flags="; s << ", flags=";
#ifndef MICRO_PIP // TODO: PIIODevice for MICRO PIP
if (options != 0) { if (options != 0) {
if (((PIIODevice::DeviceOptions)options)[PIIODevice::BlockingRead]) if (((PIIODevice::DeviceOptions)options)[PIIODevice::BlockingRead])
s << " br"; s << " br";
if (((PIIODevice::DeviceOptions)options)[PIIODevice::BlockingWrite]) if (((PIIODevice::DeviceOptions)options)[PIIODevice::BlockingWrite])
s << " bw"; s << " bw";
} }
#endif // MICRO_PIP
PIPropertyStorage ps = get(); PIPropertyStorage ps = get();
piForeachC (PIPropertyStorage::Property & p, ps) { piForeachC (PIPropertyStorage::Property & p, ps) {
s << ", " << p.name << "=\"" << p.value.toString() << "\""; s << ", " << p.name << "=\"" << p.value.toString() << "\"";
@@ -128,7 +134,6 @@ PIString PIVariantTypes::IODevice::toPICout() const {
PIVariantTypes::Enum & PIVariantTypes::Enum::operator <<(const PIVariantTypes::Enumerator & v) { PIVariantTypes::Enum & PIVariantTypes::Enum::operator <<(const PIVariantTypes::Enumerator & v) {
enum_list << v; enum_list << v;
return *this; return *this;

View File

@@ -99,9 +99,6 @@ struct PIP_EXPORT Enum {
* @brief Make vector of Enum names * @brief Make vector of Enum names
*/ */
PIStringList names() const; PIStringList names() const;
PIString enum_name;
PIString selected;
PIVector<Enumerator> enum_list;
/** /**
* @brief Add PIVariantTypes::Enumerator to Enum * @brief Add PIVariantTypes::Enumerator to Enum
@@ -119,6 +116,15 @@ struct PIP_EXPORT Enum {
* @brief Add PIVariantTypes::Enumerator element for each name in vector * @brief Add PIVariantTypes::Enumerator element for each name in vector
*/ */
Enum & operator <<(const PIStringList & v); Enum & operator <<(const PIStringList & v);
/**
* @brief Return true if Enum is empty
*/
bool isEmpty() const {return enum_list.isEmpty();}
PIString enum_name;
PIString selected;
PIVector<Enumerator> enum_list;
}; };
struct PIP_EXPORT File { struct PIP_EXPORT File {

View File

@@ -58,6 +58,9 @@ public:
//! Generate hash from bytearray //! Generate hash from bytearray
static PIByteArray hash(const PIByteArray & data); static PIByteArray hash(const PIByteArray & data);
//! Generate hash from bytearray
static PIByteArray hash(const PIByteArray & data, const unsigned char * key, size_t keylen);
//! Returns hash size //! Returns hash size
static size_t sizeHash(); static size_t sizeHash();

View File

@@ -29,7 +29,7 @@ class PIPeer;
class PIIntrospection; class PIIntrospection;
class PIIntrospectionServer; class PIIntrospectionServer;
#ifdef PIP_INTROSPECTION #if defined(PIP_INTROSPECTION) && !defined(PIP_FORCE_NO_PIINTROSPECTION)
#define __PIINTROSPECTION_SINGLETON_H__(T) \ #define __PIINTROSPECTION_SINGLETON_H__(T) \
static PIIntrospection##T##Interface * instance(); static PIIntrospection##T##Interface * instance();

View File

@@ -17,11 +17,11 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#if defined(PIP_INTROSPECTION) && !defined(PIP_FORCE_NO_PIINTROSPECTION)
#include "piintrospection_containers.h" #include "piintrospection_containers.h"
#include "piintrospection_containers_p.h" #include "piintrospection_containers_p.h"
#ifdef PIP_INTROSPECTION
__PIINTROSPECTION_SINGLETON_CPP__(Containers) __PIINTROSPECTION_SINGLETON_CPP__(Containers)

View File

@@ -20,10 +20,10 @@
#ifndef PIINTROSPECTION_CONTAINERS_H #ifndef PIINTROSPECTION_CONTAINERS_H
#define PIINTROSPECTION_CONTAINERS_H #define PIINTROSPECTION_CONTAINERS_H
#if defined(PIP_INTROSPECTION) && !defined(PIP_FORCE_NO_PIINTROSPECTION)
#include "piintrospection_base.h" #include "piintrospection_base.h"
#if defined(PIP_INTROSPECTION) && !defined(PIP_FORCE_NO_PIINTROSPECTION)
class PIIntrospectionContainers; class PIIntrospectionContainers;
#define PIINTROSPECTION_CONTAINERS (PIIntrospectionContainersInterface::instance())//(PIIntrospectionContainersInterface::instance()) #define PIINTROSPECTION_CONTAINERS (PIIntrospectionContainersInterface::instance())//(PIIntrospectionContainersInterface::instance())

View File

@@ -17,7 +17,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifdef PIP_INTROSPECTION #if defined(PIP_INTROSPECTION) && !defined(PIP_FORCE_NO_PIINTROSPECTION)
#include "piintrospection_server.h" #include "piintrospection_server.h"
#include "piintrospection_server_p.h" #include "piintrospection_server_p.h"

View File

@@ -20,11 +20,10 @@
#ifndef PIINTROSPECTION_SERVER_H #ifndef PIINTROSPECTION_SERVER_H
#define PIINTROSPECTION_SERVER_H #define PIINTROSPECTION_SERVER_H
#if defined(PIP_INTROSPECTION) && !defined(PIP_FORCE_NO_PIINTROSPECTION)
#include "pipeer.h" #include "pipeer.h"
#if defined(PIP_INTROSPECTION) && !defined(PIP_FORCE_NO_PIINTROSPECTION)
class PIIntrospectionServer; class PIIntrospectionServer;
class PISystemMonitor; class PISystemMonitor;

View File

@@ -17,7 +17,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifdef PIP_INTROSPECTION #if defined(PIP_INTROSPECTION) && !defined(PIP_FORCE_NO_PIINTROSPECTION)
#include "piintrospection_threads.h" #include "piintrospection_threads.h"
#include "piintrospection_threads_p.h" #include "piintrospection_threads_p.h"

View File

@@ -20,11 +20,10 @@
#ifndef PIINTROSPECTION_THREADS_H #ifndef PIINTROSPECTION_THREADS_H
#define PIINTROSPECTION_THREADS_H #define PIINTROSPECTION_THREADS_H
#include "piintrospection_base.h"
#if defined(PIP_INTROSPECTION) && !defined(PIP_FORCE_NO_PIINTROSPECTION) #if defined(PIP_INTROSPECTION) && !defined(PIP_FORCE_NO_PIINTROSPECTION)
#include "piintrospection_base.h"
class PIIntrospectionThreads; class PIIntrospectionThreads;
#define PIINTROSPECTION_THREADS (PIIntrospectionThreadsInterface::instance()) #define PIINTROSPECTION_THREADS (PIIntrospectionThreadsInterface::instance())

View File

@@ -53,7 +53,7 @@ static const uchar binlog_sig[] = {'B','I','N','L','O','G'};
REGISTER_DEVICE(PIBinaryLog) REGISTER_DEVICE(PIBinaryLog)
PIBinaryLog::PIBinaryLog() { PIBinaryLog::PIBinaryLog() {
#ifdef FREERTOS #ifdef MICRO_PIP
setThreadedReadBufferSize(512); setThreadedReadBufferSize(512);
#else #else
setThreadedReadBufferSize(65536); setThreadedReadBufferSize(65536);
@@ -181,7 +181,7 @@ bool PIBinaryLog::threadedRead(uchar *readed, int size) {
pausemutex.lock(); pausemutex.lock();
if (is_pause) { if (is_pause) {
pausemutex.unlock(); pausemutex.unlock();
piMSleep(100); piMSleep(100); // TODO: rewrite with condvar
return false; return false;
} else if (pause_time > PISystemTime()) { } else if (pause_time > PISystemTime()) {
startlogtime += pause_time; startlogtime += pause_time;
@@ -204,22 +204,22 @@ bool PIBinaryLog::threadedRead(uchar *readed, int size) {
int dtc; int dtc;
if (is_started) { if (is_started) {
if (is_pause) { if (is_pause) {
piMSleep(100); piMSleep(100); // TODO: rewrite with condvar
return false; return false;
} }
if (delay > 0) { if (delay > 0) {
cdelay = delay * play_speed; cdelay = delay * play_speed;// TODO: rewrite with condvar
dtc = int(cdelay) /100; dtc = int(cdelay) / 100;// TODO: rewrite with condvar
if (play_speed <= 0.) dtc = 2; if (play_speed <= 0.) dtc = 2;
//piCout << play_speed << dtc; //piCout << play_speed << dtc;
for (int j=0; j<dtc; j++) { for (int j=0; j<dtc; j++) {
cdelay = delay * play_speed; cdelay = delay * play_speed;// TODO: rewrite with condvar
dtc = int(cdelay) /100; dtc = int(cdelay) / 100;// TODO: rewrite with condvar
piMSleep(100); piMSleep(100);// TODO: rewrite with condvar
if (play_speed <= 0.) {dtc = 2; j = 0;} if (play_speed <= 0.) {dtc = 2; j = 0;}
//piCout << " " << play_speed << dtc << j; //piCout << " " << play_speed << dtc << j;
} }
cdelay = cdelay - dtc*100; cdelay = cdelay - dtc*100;// TODO: rewrite with condvar
PISystemTime::fromMilliseconds(cdelay).sleep(); PISystemTime::fromMilliseconds(cdelay).sleep();
} }
} else is_started = true; } else is_started = true;
@@ -228,7 +228,7 @@ bool PIBinaryLog::threadedRead(uchar *readed, int size) {
case PlayStaticDelay: case PlayStaticDelay:
if (is_started) { if (is_started) {
if (is_pause) { if (is_pause) {
piMSleep(100); piMSleep(100);// TODO: rewrite with condvar
return false; return false;
} }
play_delay.sleep(); play_delay.sleep();
@@ -357,7 +357,9 @@ PIByteArray PIBinaryLog::readBinLog(int id, PISystemTime * time, int * readed_id
if (readed_id) *readed_id = br.id; if (readed_id) *readed_id = br.id;
return br.data; return br.data;
} }
logmutex.lock();
while (br.id != id && !isEnd()) br = readRecord(); while (br.id != id && !isEnd()) br = readRecord();
logmutex.unlock();
if (br.id == -1) { if (br.id == -1) {
piCoutObj << "End of BinLog file"; piCoutObj << "End of BinLog file";
fileEnd(); fileEnd();
@@ -579,6 +581,7 @@ void PIBinaryLog::parseLog(PIFile * f, PIBinaryLog::BinLogInfo * info, PIVector<
if (info) { if (info) {
BinLogIndex bl_ind; BinLogIndex bl_ind;
bl_ind.id = br.id; bl_ind.id = br.id;
bl_ind.data_size = br.size;
bl_ind.pos = f->pos() - br.size - hdr_size; bl_ind.pos = f->pos() - br.size - hdr_size;
bl_ind.timestamp = br.timestamp; bl_ind.timestamp = br.timestamp;
index->append(bl_ind); index->append(bl_ind);
@@ -665,9 +668,22 @@ bool PIBinaryLog::createIndex() {
} }
int PIBinaryLog::posForTime(const PISystemTime & time) {
int ci = -1;
for (uint i = 0; i < index.size(); i++) {
if (time <= index[i].timestamp && (filterID.contains(index[i].id) || filterID.isEmpty())) {
ci = i;
break;
}
}
return ci;
}
void PIBinaryLog::seekTo(int rindex) { void PIBinaryLog::seekTo(int rindex) {
// piCoutObj << "seekTo"; // piCoutObj << "seekTo";
logmutex.lock(); logmutex.lock();
pausemutex.lock();
if (rindex < index.size_s() && rindex >= 0) { if (rindex < index.size_s() && rindex >= 0) {
file.seek(index[rindex].pos); file.seek(index[rindex].pos);
moveIndex(index_pos.value(file.pos(), -1)); moveIndex(index_pos.value(file.pos(), -1));
@@ -679,18 +695,13 @@ void PIBinaryLog::seekTo(int rindex) {
} }
} }
// piCoutObj << "seekTo done"; // piCoutObj << "seekTo done";
pausemutex.unlock();
logmutex.unlock(); logmutex.unlock();
} }
bool PIBinaryLog::seek(const PISystemTime & time) { bool PIBinaryLog::seek(const PISystemTime & time) {
int ci = -1; int ci = posForTime(time);
for (uint i=0; i<index.size(); i++) {
if (time <= index[i].timestamp && (filterID.contains(index[i].id) || filterID.isEmpty())) {
ci = i;
break;
}
}
if (ci >= 0) { if (ci >= 0) {
seekTo(ci); seekTo(ci);
return true; return true;

View File

@@ -76,6 +76,7 @@ public:
//! @brief Struct contains position, ID and timestamp of record in file //! @brief Struct contains position, ID and timestamp of record in file
struct PIP_EXPORT BinLogIndex { struct PIP_EXPORT BinLogIndex {
int id; int id;
int data_size;
llong pos; llong pos;
PISystemTime timestamp; PISystemTime timestamp;
}; };
@@ -201,6 +202,9 @@ public:
//! Returns timestamp of last readed record //! Returns timestamp of last readed record
PISystemTime lastReadedTimestamp() const {return lastrecord.timestamp;} PISystemTime lastReadedTimestamp() const {return lastrecord.timestamp;}
//! Returns timestamp of log start
PISystemTime logStartTimestamp() const {return startlogtime;}
//!Set custom file header, you can get it back when read this binlog //!Set custom file header, you can get it back when read this binlog
void setHeader(const PIByteArray & header); void setHeader(const PIByteArray & header);
@@ -233,6 +237,9 @@ public:
//! Return if current binlog file is indexed //! Return if current binlog file is indexed
bool isIndexed() {return is_indexed;} bool isIndexed() {return is_indexed;}
//! Find nearest record of time \"time\". Returns -1 if not indexed or time less than first record
int posForTime(const PISystemTime & time);
//! Go to record #index //! Go to record #index
void seekTo(int rindex); void seekTo(int rindex);

View File

@@ -19,7 +19,7 @@
#include "pican.h" #include "pican.h"
#include "pipropertystorage.h" #include "pipropertystorage.h"
#include "piincludes_p.h" #include "piincludes_p.h"
#if !defined(WINDOWS) && !defined(MAC_OS) && !defined(FREERTOS) #if !defined(WINDOWS) && !defined(MAC_OS) && !defined(MICRO_PIP)
# define PIP_CAN # define PIP_CAN
#endif #endif
#ifdef PIP_CAN #ifdef PIP_CAN

View File

@@ -58,10 +58,10 @@
# include <sys/socket.h> # include <sys/socket.h>
# include <netdb.h> # include <netdb.h>
# include <net/if.h> # include <net/if.h>
# if !defined(ANDROID) && !defined(FREERTOS) # if !defined(ANDROID) && !defined(LWIP)
# include <ifaddrs.h> # include <ifaddrs.h>
# endif # endif
# ifdef FREERTOS # ifdef LWIP
# include <lwip/sockets.h> # include <lwip/sockets.h>
# endif # endif
# endif # endif
@@ -260,7 +260,7 @@ void PIEthernet::construct() {
setMulticastTTL(1); setMulticastTTL(1);
server_thread_.setData(this); server_thread_.setData(this);
server_thread_.setName("__S__server_thread"); server_thread_.setName("__S__server_thread");
#ifdef FREERTOS #ifdef MICRO_PIP
setThreadedReadBufferSize(512); setThreadedReadBufferSize(512);
#else #else
setThreadedReadBufferSize(65536); setThreadedReadBufferSize(65536);
@@ -473,7 +473,7 @@ bool PIEthernet::joinMulticastGroup(const PIString & group) {
} }
PIFlags<Parameters> params = parameters(); PIFlags<Parameters> params = parameters();
addr_r.set(path()); addr_r.set(path());
#ifndef FREERTOS #ifndef LWIP
struct ip_mreqn mreq; struct ip_mreqn mreq;
#else #else
struct ip_mreq mreq; struct ip_mreq mreq;
@@ -486,13 +486,13 @@ bool PIEthernet::joinMulticastGroup(const PIString & group) {
if (ci != 0) mreq.imr_ifindex = ci->index;*/ if (ci != 0) mreq.imr_ifindex = ci->index;*/
#endif #endif
if (params[PIEthernet::Broadcast]) if (params[PIEthernet::Broadcast])
#ifndef FREERTOS #ifndef LWIP
mreq.imr_address.s_addr = INADDR_ANY; mreq.imr_address.s_addr = INADDR_ANY;
#else #else
mreq.imr_interface.s_addr = INADDR_ANY; mreq.imr_interface.s_addr = INADDR_ANY;
#endif #endif
else else
#ifndef FREERTOS #ifndef LWIP
mreq.imr_address.s_addr = addr_r.ip(); mreq.imr_address.s_addr = addr_r.ip();
#else #else
mreq.imr_interface.s_addr = addr_r.ip(); mreq.imr_interface.s_addr = addr_r.ip();
@@ -520,20 +520,20 @@ bool PIEthernet::leaveMulticastGroup(const PIString & group) {
} }
PIFlags<Parameters> params = parameters(); PIFlags<Parameters> params = parameters();
addr_r.set(path()); addr_r.set(path());
#ifndef FREERTOS #ifndef LWIP
struct ip_mreqn mreq; struct ip_mreqn mreq;
#else #else
struct ip_mreq mreq; struct ip_mreq mreq;
#endif #endif
memset(&mreq, 0, sizeof(mreq)); memset(&mreq, 0, sizeof(mreq));
if (params[PIEthernet::Broadcast]) if (params[PIEthernet::Broadcast])
#ifndef FREERTOS #ifndef LWIP
mreq.imr_address.s_addr = INADDR_ANY; mreq.imr_address.s_addr = INADDR_ANY;
#else #else
mreq.imr_interface.s_addr = INADDR_ANY; mreq.imr_interface.s_addr = INADDR_ANY;
#endif #endif
else else
#ifndef FREERTOS #ifndef LWIP
mreq.imr_address.s_addr = addr_r.ip(); mreq.imr_address.s_addr = addr_r.ip();
#else #else
mreq.imr_interface.s_addr = addr_r.ip(); mreq.imr_interface.s_addr = addr_r.ip();
@@ -686,7 +686,7 @@ int PIEthernet::readDevice(void * read_to, int max_size) {
s = accept(sock, (sockaddr * )&client_addr, &slen); s = accept(sock, (sockaddr * )&client_addr, &slen);
if (s == -1) { if (s == -1) {
//piCoutObj << "Can`t accept new connection, " << ethErrorString(); //piCoutObj << "Can`t accept new connection, " << ethErrorString();
msleep(PIP_MIN_MSLEEP); piMinSleep();
return -1; return -1;
} }
rs = ethRecv(s, read_to, max_size); rs = ethRecv(s, read_to, max_size);
@@ -788,7 +788,7 @@ int PIEthernet::writeDevice(const void * data, int max_size) {
//piCoutObj << "connect SingleTCP" << ip_s << ":" << port_s << "..."; //piCoutObj << "connect SingleTCP" << ip_s << ":" << port_s << "...";
if (::connect(sock, (sockaddr * )&PRIVATE->addr_, sizeof(PRIVATE->addr_)) != 0) { if (::connect(sock, (sockaddr * )&PRIVATE->addr_, sizeof(PRIVATE->addr_)) != 0) {
//piCoutObj << "Can`t connect to " << ip_s << ":" << port_s << ", " << ethErrorString(); //piCoutObj << "Can`t connect to " << ip_s << ":" << port_s << ", " << ethErrorString();
msleep(PIP_MIN_MSLEEP); piMinSleep();
return -1; return -1;
} }
//piCoutObj << "ok, write SingleTCP" << int(data) << max_size << "bytes ..."; //piCoutObj << "ok, write SingleTCP" << int(data) << max_size << "bytes ...";
@@ -993,6 +993,7 @@ void PIEthernet::configureFromVariantDevice(const PIPropertyStorage & d) {
PIEthernet::InterfaceList PIEthernet::interfaces() { PIEthernet::InterfaceList PIEthernet::interfaces() {
//piCout << "PIEthernet::interfaces()";
PIEthernet::InterfaceList il; PIEthernet::InterfaceList il;
Interface ci; Interface ci;
ci.index = -1; ci.index = -1;
@@ -1039,12 +1040,20 @@ PIEthernet::InterfaceList PIEthernet::interfaces() {
} }
pAdapter = pAdapter->Next; pAdapter = pAdapter->Next;
} }
} else } else {
switch (ret) {
case ERROR_NO_DATA: break;
case ERROR_NOT_SUPPORTED:
piCout << "[PIEthernet] GetAdaptersInfo not supported";
break;
default:
piCout << "[PIEthernet] GetAdaptersInfo failed with error:" << ret; piCout << "[PIEthernet] GetAdaptersInfo failed with error:" << ret;
}
}
if (pAdapterInfo) if (pAdapterInfo)
HeapFree(GetProcessHeap(), 0, (pAdapterInfo)); HeapFree(GetProcessHeap(), 0, (pAdapterInfo));
#else #else
#ifdef FREERTOS #ifdef MICRO_PIP
#else #else
# ifdef ANDROID # ifdef ANDROID
struct ifconf ifc; struct ifconf ifc;
@@ -1156,7 +1165,7 @@ PIEthernet::InterfaceList PIEthernet::interfaces() {
PIEthernet::Address PIEthernet::interfaceAddress(const PIString & interface_) { PIEthernet::Address PIEthernet::interfaceAddress(const PIString & interface_) {
#if defined(WINDOWS) || defined(FREERTOS) #if defined(WINDOWS) || defined(MICRO_PIP)
piCout << "[PIEthernet] Not implemented, use \"PIEthernet::allAddresses\" or \"PIEthernet::interfaces\" instead"; piCout << "[PIEthernet] Not implemented, use \"PIEthernet::allAddresses\" or \"PIEthernet::interfaces\" instead";
return Address(); return Address();
#else #else

View File

@@ -148,7 +148,17 @@ PIFile::PIFile(const PIString & path, PIIODevice::DeviceMode mode): PIIODevice(p
bool PIFile::openTemporary(PIIODevice::DeviceMode mode) { bool PIFile::openTemporary(PIIODevice::DeviceMode mode) {
return open(PIString(tmpnam(0)), mode); PIString tp;
#ifdef WINDOWS
tp = PIDir::temporary().path() + PIDir::separator + "file" + PIString::fromNumber(randomi());
#else
char * rc = tmpnam(0);
if (!rc) return false;
tp = rc;
#endif
while (isExists(tp))
tp += PIString::fromNumber(randomi() % 10);
return open(tp, mode);
} }
@@ -701,7 +711,7 @@ PIFile::FileInfo PIFile::fileInfo(const PIString & path) {
ret.time_modification = PIDateTime::fromSystemTime(PISystemTime(fs.MTIME.tv_sec, fs.MTIME.tv_nsec)); ret.time_modification = PIDateTime::fromSystemTime(PISystemTime(fs.MTIME.tv_sec, fs.MTIME.tv_nsec));
# endif # endif
#endif #endif
#ifndef FREERTOS #ifndef MICRO_PIP
ret.perm_user = FileInfo::Permissions((mode & S_IRUSR) == S_IRUSR, (mode & S_IWUSR) == S_IWUSR, (mode & S_IXUSR) == S_IXUSR); ret.perm_user = FileInfo::Permissions((mode & S_IRUSR) == S_IRUSR, (mode & S_IWUSR) == S_IWUSR, (mode & S_IXUSR) == S_IXUSR);
ret.perm_group = FileInfo::Permissions((mode & S_IRGRP) == S_IRGRP, (mode & S_IWGRP) == S_IWGRP, (mode & S_IXGRP) == S_IXGRP); ret.perm_group = FileInfo::Permissions((mode & S_IRGRP) == S_IRGRP, (mode & S_IWGRP) == S_IWGRP, (mode & S_IXGRP) == S_IXGRP);
ret.perm_other = FileInfo::Permissions((mode & S_IROTH) == S_IROTH, (mode & S_IWOTH) == S_IWOTH, (mode & S_IXOTH) == S_IXOTH); ret.perm_other = FileInfo::Permissions((mode & S_IROTH) == S_IROTH, (mode & S_IWOTH) == S_IWOTH, (mode & S_IXOTH) == S_IXOTH);

View File

@@ -85,6 +85,7 @@ public:
}; };
//! Constructs a file with path "path" and open mode "mode" //! Constructs a file with path "path" and open mode "mode"
//! If "path" is not empty then open file
explicit PIFile(const PIString & path, DeviceMode mode = ReadWrite); explicit PIFile(const PIString & path, DeviceMode mode = ReadWrite);

View File

@@ -155,7 +155,7 @@ bool PIIODevice::setOption(PIIODevice::DeviceOption o, bool yes) {
bool stopThread(PIThread * t, bool hard) { bool stopThread(PIThread * t, bool hard) {
#ifdef FREERTOS #ifdef MICRO_PIP
t->stop(true); t->stop(true);
#else #else
if (hard) { if (hard) {
@@ -163,7 +163,7 @@ bool stopThread(PIThread * t, bool hard) {
return true; return true;
} else { } else {
t->stop(); t->stop();
if (t->waitForFinish(10000)) { if (!t->waitForFinish(10000)) {
t->terminate(); t->terminate();
return true; return true;
} }
@@ -222,7 +222,7 @@ void PIIODevice::_init() {
setOptions(0); setOptions(0);
setReopenEnabled(true); setReopenEnabled(true);
setReopenTimeout(1000); setReopenTimeout(1000);
#ifdef FREERTOS #ifdef MICRO_PIP
threaded_read_buffer_size = 512; threaded_read_buffer_size = 512;
//setThreadedReadBufferSize(512); //setThreadedReadBufferSize(512);
#else #else
@@ -239,7 +239,7 @@ void PIIODevice::check_start(void * data, int delim) {
//cout << "check " << tread_started_ << endl; //cout << "check " << tread_started_ << endl;
if (open()) { if (open()) {
thread_started_ = true; thread_started_ = true;
timer.stop(); timer.stop(false);
} }
} }
@@ -254,7 +254,7 @@ void PIIODevice::write_func() {
int ret = write(item.first); int ret = write(item.first);
threadedWriteEvent(item.second, ret); threadedWriteEvent(item.second, ret);
} }
msleep(PIP_MIN_MSLEEP); piMinSleep();
} }
} }
@@ -276,7 +276,7 @@ void PIIODevice::terminate() {
thread_started_ = false; thread_started_ = false;
if (!init_) return; if (!init_) return;
if (isRunning()) { if (isRunning()) {
#ifdef FREERTOS #ifdef MICRO_PIP
stop(true); stop(true);
#else #else
stop(); stop();
@@ -338,7 +338,7 @@ PIByteArray PIIODevice::readForTime(double timeout_ms) {
tm.reset(); tm.reset();
while (tm.elapsed_m() < timeout_ms) { while (tm.elapsed_m() < timeout_ms) {
ret = read(td, threaded_read_buffer_size); ret = read(td, threaded_read_buffer_size);
if (ret <= 0) msleep(PIP_MIN_MSLEEP); if (ret <= 0) piMinSleep();
else str.append(td, ret); else str.append(td, ret);
} }
delete[] td; delete[] td;

View File

@@ -24,7 +24,7 @@
#include "pipropertystorage.h" #include "pipropertystorage.h"
#include <errno.h> #include <errno.h>
#if defined(FREERTOS) #if defined(MICRO_PIP)
# define PISERIAL_NO_PINS # define PISERIAL_NO_PINS
#endif #endif
#if defined(PISERIAL_NO_PINS) || defined(WINDOWS) #if defined(PISERIAL_NO_PINS) || defined(WINDOWS)
@@ -289,6 +289,39 @@ bool PISerial::isRNG() const {return isBit(TIOCM_RNG, "RNG");}
bool PISerial::isDSR() const {return isBit(TIOCM_DSR, "DSR");} bool PISerial::isDSR() const {return isBit(TIOCM_DSR, "DSR");}
bool PISerial::setBreak(bool enabled) {
if (fd < 0) {
piCoutObj << "sendBreak error: \"" << path() << "\" is not opened!";
return false;
}
#ifdef WINDOWS
if (enabled) {
if (!SetCommBreak(PRIVATE->hCom)) {
piCoutObj << "setBreak error: " << errorString();
return false;
} else {
return true;
}
} else {
if (!ClearCommBreak(PRIVATE->hCom)) {
piCoutObj << "setBreak error: " << errorString();
return false;
} else {
return true;
}
}
#else
if (ioctl(fd, enabled ? TIOCSBRK : TIOCCBRK) < 0) {
piCoutObj << "setBreak error: " << errorString();
return false;
} else {
return true;
}
#endif
return false;
}
bool PISerial::setBit(int bit, bool on, const PIString & bname) { bool PISerial::setBit(int bit, bool on, const PIString & bname) {
if (fd < 0) { if (fd < 0) {
piCoutObj << "setBit" << bname << " error: \"" << path() << "\" is not opened!"; piCoutObj << "setBit" << bname << " error: \"" << path() << "\" is not opened!";
@@ -356,6 +389,9 @@ int PISerial::convertSpeed(PISerial::Speed speed) {
case S2400: return B2400; case S2400: return B2400;
case S4800: return B4800; case S4800: return B4800;
case S9600: return B9600; case S9600: return B9600;
#ifdef WINDOWS
case S14400: return B14400;
#endif
case S19200: return B19200; case S19200: return B19200;
case S38400: return B38400; case S38400: return B38400;
case S57600: return B57600; case S57600: return B57600;
@@ -398,7 +434,7 @@ bool PISerial::read(void * data, int size, double timeout_ms) {
while (all < size && tm_.elapsed_m() < timeout_ms) { while (all < size && tm_.elapsed_m() < timeout_ms) {
ret = readDevice(&((uchar * )data)[all], size - all); ret = readDevice(&((uchar * )data)[all], size - all);
if (ret > 0) all += ret; if (ret > 0) all += ret;
else msleep(PIP_MIN_MSLEEP); else piMinSleep();
} }
setOption(BlockingRead, br); setOption(BlockingRead, br);
received(data, all); received(data, all);
@@ -437,13 +473,13 @@ PIString PISerial::read(int size, double timeout_ms) {
if (size <= 0) { if (size <= 0) {
while (tm_.elapsed_m() < timeout_ms) { while (tm_.elapsed_m() < timeout_ms) {
ret = readDevice(td, 1024); ret = readDevice(td, 1024);
if (ret <= 0) msleep(PIP_MIN_MSLEEP); if (ret <= 0) piMinSleep();
else str << PIString((char*)td, ret); else str << PIString((char*)td, ret);
} }
} else { } else {
while (all < size && tm_.elapsed_m() < timeout_ms) { while (all < size && tm_.elapsed_m() < timeout_ms) {
ret = readDevice(td, size - all); ret = readDevice(td, size - all);
if (ret <= 0) msleep(PIP_MIN_MSLEEP); if (ret <= 0) piMinSleep();
else { else {
str << PIString((char*)td, ret); str << PIString((char*)td, ret);
all += ret; all += ret;
@@ -457,7 +493,7 @@ PIString PISerial::read(int size, double timeout_ms) {
str << PIString((char*)td, all); str << PIString((char*)td, all);
while (all < size) { while (all < size) {
ret = readDevice(td, size - all); ret = readDevice(td, size - all);
if (ret <= 0) msleep(PIP_MIN_MSLEEP); if (ret <= 0) piMinSleep();
else { else {
str << PIString((char*)td, ret); str << PIString((char*)td, ret);
all += ret; all += ret;
@@ -489,13 +525,13 @@ PIByteArray PISerial::readData(int size, double timeout_ms) {
if (size <= 0) { if (size <= 0) {
while (tm_.elapsed_m() < timeout_ms) { while (tm_.elapsed_m() < timeout_ms) {
ret = readDevice(td, 1024); ret = readDevice(td, 1024);
if (ret <= 0) msleep(PIP_MIN_MSLEEP); if (ret <= 0) piMinSleep();
else str.append(td, ret); else str.append(td, ret);
} }
} else { } else {
while (all < size && tm_.elapsed_m() < timeout_ms) { while (all < size && tm_.elapsed_m() < timeout_ms) {
ret = readDevice(td, size - all); ret = readDevice(td, size - all);
if (ret <= 0) msleep(PIP_MIN_MSLEEP); if (ret <= 0) piMinSleep();
else { else {
str.append(td, ret); str.append(td, ret);
all += ret; all += ret;
@@ -509,7 +545,7 @@ PIByteArray PISerial::readData(int size, double timeout_ms) {
str.append(td, all); str.append(td, all);
while (all < size) { while (all < size) {
ret = readDevice(td, size - all); ret = readDevice(td, size - all);
if (ret <= 0) msleep(PIP_MIN_MSLEEP); if (ret <= 0) piMinSleep();
else { else {
str.append(td, ret); str.append(td, ret);
all += ret; all += ret;
@@ -846,9 +882,13 @@ void PISerial::configureFromVariantDevice(const PIPropertyStorage & d) {
PIVector<int> PISerial::availableSpeeds() { PIVector<int> PISerial::availableSpeeds() {
PIVector<int> spds; PIVector<int> spds;
spds << 50 << 75 << 110 << 300 << 600 << 1200 << 2400 << 4800 << spds << 50 << 75 << 110 << 300 << 600 << 1200 << 2400 << 4800 <<
9600 << 19200 << 38400 << 57600 << 115200 << 230400 << 460800 << 9600 <<
500000 << 576000 << 921600 << 1000000 << 1152000 << 1500000 << #ifdef WINDOWS
2000000 << 2500000 << 3000000 << 3500000 << 4000000; 14400 <<
#endif
19200 << 38400 << 57600 << 115200 << 230400 <<
460800 << 500000 << 576000 << 921600 << 1000000 << 1152000 <<
1500000 << 2000000 << 2500000 << 3000000 << 3500000 << 4000000;
return spds; return spds;
} }

View File

@@ -52,6 +52,7 @@ public:
S2400 /*! 2400 baud */ = 2400, S2400 /*! 2400 baud */ = 2400,
S4800 /*! 4800 baud */ = 4800, S4800 /*! 4800 baud */ = 4800,
S9600 /*! 9600 baud */ = 9600, S9600 /*! 9600 baud */ = 9600,
S14400 /*! 14400 baud */ = 14400,
S19200 /*! 19200 baud */ = 19200, S19200 /*! 19200 baud */ = 19200,
S38400 /*! 38400 baud */ = 38400, S38400 /*! 38400 baud */ = 38400,
S57600 /*! 57600 baud */ = 57600, S57600 /*! 57600 baud */ = 57600,
@@ -159,6 +160,12 @@ public:
bool isRNG() const; bool isRNG() const;
bool isDSR() const; bool isDSR() const;
//! Switch transmission line in break if enabled.
//! i.e. sends a continuous stream of zero bits.
//! If successful, returns true; otherwise returns false.
//! The serial port has to be open before trying to send a break duration; otherwise returns false
bool setBreak(bool enabled);
void setVTime(int t) {vtime = t; applySettings();} void setVTime(int t) {vtime = t; applySettings();}
//! Returns device name //! Returns device name

View File

@@ -42,7 +42,7 @@ REGISTER_DEVICE(PISPI)
PISPI::PISPI(const PIString & path, uint speed, PIIODevice::DeviceMode mode) : PIIODevice(path, mode) { PISPI::PISPI(const PIString & path, uint speed, PIIODevice::DeviceMode mode) : PIIODevice(path, mode) {
#ifdef FREERTOS #ifdef MICRO_PIP
setThreadedReadBufferSize(512); setThreadedReadBufferSize(512);
#else #else
setThreadedReadBufferSize(1024); setThreadedReadBufferSize(1024);

View File

@@ -37,7 +37,7 @@ PIBaseTransfer::PIBaseTransfer(): crc(standardCRC_16()), diag(false) {
diag.setName("PIBaseTransfer"); diag.setName("PIBaseTransfer");
diag.start(50); diag.start(50);
packets_count = 10; packets_count = 10;
#ifdef FREERTOS #ifdef MICRO_PIP
setPacketSize(512); setPacketSize(512);
#else #else
setPacketSize(4096); setPacketSize(4096);
@@ -346,7 +346,7 @@ bool PIBaseTransfer::send_process() {
if (chk == 0) return finish_send(true); if (chk == 0) return finish_send(true);
if (chk != prev_chk) rtm.reset(); if (chk != prev_chk) rtm.reset();
else if (rtm.elapsed_m() < 100) { else if (rtm.elapsed_m() < 100) {
piMSleep(PIP_MIN_MSLEEP); piMinSleep();
continue; continue;
} }
if (is_pause) { if (is_pause) {
@@ -507,7 +507,7 @@ bool PIBaseTransfer::getStartRequest() {
return true; return true;
} }
mutex_session.unlock(); mutex_session.unlock();
piMSleep(PIP_MIN_MSLEEP); piMinSleep();
} }
return false; return false;
} }

View File

@@ -94,7 +94,7 @@ void PIPacketExtractor::construct() {
ret_func_header = ret_func_footer = 0; ret_func_header = ret_func_footer = 0;
setPayloadSize(0); setPayloadSize(0);
setTimeout(100); setTimeout(100);
#ifdef FREERTOS #ifdef MICRO_PIP
setBufferSize(512); setBufferSize(512);
#else #else
setBufferSize(65536); setBufferSize(65536);

View File

@@ -36,22 +36,6 @@ public:
//! Contructs packer and try to assign \"dev\" //! Contructs packer and try to assign \"dev\"
PIStreamPacker(PIIODevice * dev = 0); PIStreamPacker(PIIODevice * dev = 0);
//! Progress info
struct PIP_IO_UTILS_EXPORT Progress {
Progress();
//! Is send/receive in progress
bool active;
//! Overall send/receive packet size
int bytes_all;
//! Current send/receive size
int bytes_current;
//! Current send/receive progress from 0 to 1
double progress;
};
//! Set maximum size of single packet //! Set maximum size of single packet
void setMaxPacketSize(int max_size) {max_packet_size = max_size;} void setMaxPacketSize(int max_size) {max_packet_size = max_size;}
@@ -83,6 +67,8 @@ public:
bool cryptSizeEnabled() const {return crypt_size;} bool cryptSizeEnabled() const {return crypt_size;}
void setCryptSizeEnabled(bool on); void setCryptSizeEnabled(bool on);
void clear();
//! Prepare data for send and raise \a sendRequest() events //! Prepare data for send and raise \a sendRequest() events
void send(const PIByteArray & data); void send(const PIByteArray & data);
@@ -97,12 +83,6 @@ public:
//! and \a sendRequest() event to \"dev\" \a PIIODevice::write() handler //! and \a sendRequest() event to \"dev\" \a PIIODevice::write() handler
void assignDevice(PIIODevice * dev); void assignDevice(PIIODevice * dev);
//! Returns \a Progress info about sending
Progress progressSend() const;
//! Returns \a Progress info about receiving
Progress progressReceive() const;
EVENT1(packetReceiveEvent, PIByteArray &, data) EVENT1(packetReceiveEvent, PIByteArray &, data)
EVENT1(sendRequest, PIByteArray, data) EVENT1(sendRequest, PIByteArray, data)
@@ -139,7 +119,6 @@ private:
int packet_size, crypt_frag_size; int packet_size, crypt_frag_size;
ushort packet_sign; ushort packet_sign;
int max_packet_size, size_crypted_size; int max_packet_size, size_crypted_size;
Progress prog_s, prog_r;
mutable PIMutex prog_s_mutex, prog_r_mutex; mutable PIMutex prog_s_mutex, prog_r_mutex;
}; };

View File

@@ -19,6 +19,7 @@
#include "pifft.h" #include "pifft.h"
#ifndef MICRO_PIP
PIFFT_double::PIFFT_double() { PIFFT_double::PIFFT_double() {
} }
@@ -1883,3 +1884,5 @@ void PIFFT_float::ftbase_ffttwcalc(PIVector<float> * a, int aoffset, int n1, int
} }
} }
} }
#endif // MICRO_PIP

View File

@@ -23,9 +23,12 @@
#ifndef PIFFT_H #ifndef PIFFT_H
#define PIFFT_H #define PIFFT_H
#include "pip_fftw_export.h"
#include "pimathcomplex.h" #include "pimathcomplex.h"
#ifndef MICRO_PIP
#include "pip_fftw_export.h"
class PIP_EXPORT PIFFT_double class PIP_EXPORT PIFFT_double
{ {
public: public:
@@ -194,4 +197,6 @@ typedef PIFFTW<ldouble> PIFFTWld;
#endif #endif
#endif // MICRO_PIP
#endif // PIFFT_H #endif // PIFFT_H

View File

@@ -1,10 +1,25 @@
/*! @file pigeometry.h /*! \file pigeometry.h
* @brief Geometry base class * \ingroup Math
* \brief
* \~english Geometry base classes
* \~russian Базовые геометрические классы
* \~\details
* \~english
* Add \a PIPoint, \a PILine and \a PIRect classes.
* \~russian
* Содержит классы: \a PIPoint, \a PILine и \a PIRect.
* * \~\authors
* \~english
* Ivan Pelipenko peri4ko@yandex.ru;
* Andrey Bychkov work.a.b@yandex.ru;
* \~russian
* Иван Пелипенко peri4ko@yandex.ru;
* Андрей Бычков work.a.b@yandex.ru;
*/ */
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Geometry Geometry base classes
Ivan Pelipenko peri4ko@yandex.ru Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU Lesser General Public License as published by
@@ -19,130 +34,11 @@
You should have received a copy of the GNU Lesser General Public License You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef PIGEOMETRY_H #ifndef PIGEOMETRY_H
#define PIGEOMETRY_H #define PIGEOMETRY_H
#include "pimathbase.h" #include "pipoint.h"
#include "piline.h"
template<typename Type> #include "pirect.h"
class PIP_EXPORT PIPoint {
static_assert(std::is_arithmetic<Type>::value, "Type must be arithmetic");
public:
Type x;
Type y;
PIPoint() {x = y = Type();}
PIPoint(Type x_, Type y_) {set(x_, y_);}
PIPoint<Type> & set(Type x_, Type y_) {x = x_; y = y_; return *this;}
PIPoint<Type> & move(Type x_, Type y_) {x += x_; y += y_; return *this;}
PIPoint<Type> & move(const PIPoint<Type> & p) {x += p.x; y += p.y; return *this;}
double angleRad() const {return atan2(y, x);}
int angleDeg() const {return round(atan2(y, x) * rad2deg);}
PIPoint<Type> toPolar(bool isDeg = false) const {return PIPoint<Type>(sqrt(x*x + y*y), isDeg ? angleDeg() : angleRad());}
static PIPoint<Type> fromPolar(const PIPoint<Type> & p) {return PIPoint<Type>(p.y * cos(p.x), p.y * sin(p.x));}
PIPoint<Type> operator +(const PIPoint<Type> & p) {return PIPoint<Type>(x + p.x, y + p.y);}
PIPoint<Type> operator +(const Type & p) {return PIPoint<Type>(x + p, y + p);}
PIPoint<Type> operator -(const PIPoint<Type> & p) {return PIPoint<Type>(x - p.x, y - p.y);}
PIPoint<Type> operator -(const Type & p) {return PIPoint<Type>(x - p, y - p);}
PIPoint<Type> operator -() {return PIPoint<Type>(-x, -y);}
PIPoint<Type> operator *(const Type & d) {return PIPoint<Type>(x * d, y * d);}
PIPoint<Type> operator /(const Type & d) {return PIPoint<Type>(x / d, y / d);}
bool operator ==(const PIPoint<Type> & p) const {return (x == p.x && y == p.y);}
bool operator !=(const PIPoint<Type> & p) const {return (x != p.x || y != p.y);}
};
template<typename Type>
PICout operator <<(PICout & s, const PIPoint<Type> & v) {s.setControl(0, true); s << "Point{" << v.x << ", " << v.y << "}"; s.restoreControl(); return s;}
typedef PIPoint<int> PIPointi;
typedef PIPoint<uint> PIPointu;
typedef PIPoint<float> PIPointf;
typedef PIPoint<double> PIPointd;
template<typename Type>
class PIP_EXPORT PIRect {
static_assert(std::is_arithmetic<Type>::value, "Type must be arithmetic");
public:
Type x0;
Type y0;
Type x1;
Type y1;
PIRect() {x0 = y0 = x1 = y1 = Type();}
PIRect(Type x, Type y, Type w, Type h) {set(x, y, w, h);}
PIRect(const PIPoint<Type> & tl, const PIPoint<Type> & br) {set(tl.x, tl.y, br.x, br.y);}
PIRect(const PIPoint<Type> & p0, const PIPoint<Type> & p1, const PIPoint<Type> & p2) {set(piMin<Type>(p0.x, p1.x, p2.x), piMin<Type>(p0.y, p1.y, p2.y),
piMax<Type>(p0.x, p1.x, p2.x), piMax<Type>(p0.y, p1.y, p2.y));}
PIRect<Type> & set(Type x, Type y, Type w, Type h) {x0 = x; y0 = y; x1 = x + w; y1 = y + h; return *this;}
bool pointIn(Type x, Type y) const {return (x <= x1 && x >= x0 && y <= y1 && y >= y0);}
bool pointIn(const PIPoint<Type> & p) const {return pointIn(p.x, p.y);}
bool isEmpty() const {return (x1 - x0 == 0 && y1 - y0 == 0);}
PIRect<Type> & translate(Type x, Type y) {x0 += x; x1 += x; y0 += y; y1 += y; return *this;}
PIRect<Type> & translate(const PIPoint<Type> & p) {x0 += p.x; x1 += p.x; y0 += p.y; y1 += p.y; return *this;}
PIRect<Type> translated(Type x, Type y) {PIRect<Type> r(*this); r.translate(x, y); return r;}
PIRect<Type> translated(const PIPoint<Type> & p) {PIRect<Type> r(*this); r.translate(p); return r;}
PIRect<Type> & scale(Type x, Type y) {setWidth(width() * x); setHeight(height() * y); return *this;}
PIRect<Type> & scale(const PIPoint<Type> & p) {setWidth(width() * p.x); setHeight(height() * p.y); return *this;}
PIRect<Type> scaled(Type x, Type y) {PIRect<Type> r(*this); r.scale(x, y); return r;}
PIRect<Type> scaled(const PIPoint<Type> & p) {PIRect<Type> r(*this); r.scale(p); return r;}
PIRect<Type> & normalize() {if (x0 > x1) piSwap<Type>(x0, x1); if (y0 > y1) piSwap<Type>(y0, y1); return *this;}
PIRect<Type> normalized() {PIRect<Type> r(*this); r.normalize(); return r;}
PIRect<Type> & unite(const PIRect<Type> & r) {x0 = piMin<Type>(x0, r.x0); y0 = piMin<Type>(y0, r.y0); x1 = piMax<Type>(x1, r.x1); y1 = piMax<Type>(y1, r.y1); return *this;}
PIRect<Type> united(const PIRect<Type> & rect) {PIRect<Type> r(*this); r.unite(rect); return r;}
PIRect<Type> & intersect(const PIRect<Type> & r) {x0 = piMax<Type>(x0, r.x0); y0 = piMax<Type>(y0, r.y0); x1 = piMin<Type>(x1, r.x1); y1 = piMin<Type>(y1, r.y1); if (x0 > x1 || y0 > y1) x0 = x1 = y0 = y1 = Type(0); return *this;}
PIRect<Type> intersected(const PIRect<Type> & rect) {PIRect<Type> r(*this); r.intersect(rect); return r;}
Type top() const {return y0;}
Type left() const {return x0;}
Type right() const {return x1;}
Type bottom() const {return y1;}
Type width() const {return x1 - x0;}
Type height() const {return y1 - y0;}
PIPoint<Type> topLeft() {return PIPoint<Type>(x0, y0);}
PIPoint<Type> topRigth() {return PIPoint<Type>(x1, y0);}
PIPoint<Type> bottomLeft() {return PIPoint<Type>(x0, y1);}
PIPoint<Type> bottomRight() {return PIPoint<Type>(x1, y1);}
void setTop(Type v) {y0 = v;}
void setLeft(Type v) {x0 = v;}
void setRigth(Type v) {x1 = v;}
void setBottom(Type v) {y1 = v;}
void setWidth(Type v) {x1 = x0 + v;}
void setHeight(Type v) {y1 = y0 + v;}
PIRect<Type> operator -() {return PIRect<Type>(-x0, -y0, -width(), -height());}
void operator +=(Type x) {translate(x, x);}
void operator +=(const PIPoint<Type> & p) {translate(p);}
void operator -=(Type x) {translate(-x, -x);}
void operator -=(const PIPoint<Type> & p) {translate(-p);}
void operator *=(Type p) {x0 *= p; x1 *= p; y0 *= p; y1 *= p;}
void operator /=(Type p) {x0 /= p; x1 /= p; y0 /= p; y1 /= p;}
void operator |=(const PIRect<Type> & r) {unite(r);}
void operator &=(const PIRect<Type> & r) {intersect(r);}
PIRect<Type> operator +(const PIPoint<Type> & p) {return PIRect<Type>(*this).translated(p);}
PIRect<Type> operator -(const PIPoint<Type> & p) {return PIRect<Type>(*this).translated(-p);}
PIRect<Type> operator |(const PIRect<Type> & r) {return PIRect<Type>(*this).united(r);}
PIRect<Type> operator &(const PIRect<Type> & r) {return PIRect<Type>(*this).intersected(r);}
bool operator ==(const PIRect<Type> & r) const {return (x0 == r.x0 && y0 == r.y0 && x1 == r.x1 && y1 == r.y10);}
bool operator !=(const PIRect<Type> & r) const {return (x0 != r.x0 || y0 != r.y0 || x1 != r.x1 || y1 != r.y10);}
};
template<typename Type>
PICout operator <<(PICout & s, const PIRect<Type> & v) {s.setControl(0, true); s << "Rect{" << v.x0 << ", " << v.y0 << "; " << v.x1 - v.x0 << ", " << v.y1 - v.y0 << "}"; s.restoreControl(); return s;}
typedef PIRect<int> PIRecti;
typedef PIRect<uint> PIRectu;
typedef PIRect<float> PIRectf;
typedef PIRect<double> PIRectd;
#endif // PIGEOMETRY_H #endif // PIGEOMETRY_H

179
libs/main/math/piline.h Normal file
View File

@@ -0,0 +1,179 @@
/*! \file pirect.h
* \ingroup Math
* \brief
* \~english Two-dimensional line class
* \~russian Класс отрезка двумерной линии
* * \~\authors
* \~english
* Ivan Pelipenko peri4ko@yandex.ru;
* Andrey Bychkov work.a.b@yandex.ru;
* \~russian
* Иван Пелипенко peri4ko@yandex.ru;
* Андрей Бычков work.a.b@yandex.ru;
*/
/*
PIP - Platform Independent Primitives
Two-dimensional line class
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@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
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PILINE_H
#define PILINE_H
#include "pipoint.h"
/*! \brief
* \~english Two-dimensional line class
* \~russian Класс отрезка двумерной линии
* \~\details
* \~russian
* Этот класс описывает линию на плоскости в прямоугольной системе координат
*/
template<typename Type>
class PIP_EXPORT PILine {
static_assert(std::is_arithmetic<Type>::value, "Type must be arithmetic");
public:
PIPoint<Type> p0;
PIPoint<Type> p1;
//!
PILine() {}
//!
PILine(const PIPoint<Type> & p0_, const PIPoint<Type> & p1_) {
p0 = p0_;
p1 = p1_;
}
//!
PILine(Type x0, Type y0, Type x1, Type y1) {
p0.set(x0, y0);
p1.set(x1, y1);
}
//!
PILine<Type> & set(const PIPoint<Type> & p0_, const PIPoint<Type> & p1_) {
p0 = p0_;
p1 = p1_;
return *this;
}
//!
PILine<Type> & set(Type x0, Type y0, Type x1, Type y1) {
p0.set(x0, y0);
p1.set(x1, y1);
return *this;
}
//!
bool isEmpty() const {
return (p0 == p1);
}
//!
Type width() const {return piAbs<Type>(p1.x - p0.x);}
//!
Type height() const {return piAbs<Type>(p1.y - p0.y);}
//!
PILine<Type> & translate(Type x, Type y) {
p0.translate(x, y);
p1.translate(x, y);
return *this;
}
//!
PILine<Type> & translate(const PIPoint<Type> & p) {
p0.translate(p);
p1.translate(p);
return *this;
}
//!
PILine<Type> translated(Type x, Type y) const {
PILine<Type> l(*this);
l.translate(x, y);
return l;
}
//!
PILine<Type> translated(const PIPoint<Type> & p) const {
PILine<Type> l(*this);
l.translate(p);
return l;
}
//!
PILine<Type> & move(Type x, Type y) {return translate(x, y);}
//!
PILine<Type> & move(const PIPoint<Type> & p) {return translate(p);}
//!
PILine<Type> moved(Type x, Type y) const {
PILine<Type> l(*this);
l.translate(x, y);
return l;
}
//!
PILine<Type> moved(const PIPoint<Type> & p) const {
PILine<Type> l(*this);
l.translate(p);
return l;
}
//!
void operator +=(Type x) {translate(x, x);}
//!
void operator +=(const PIPoint<Type> & p) {translate(p);}
//!
void operator -=(Type x) {translate(-x, -x);}
//!
void operator -=(const PIPoint<Type> & p) {translate(-p);}
//!
PILine<Type> operator +(const PIPoint<Type> & p) {return translated(p);}
//!
PILine<Type> operator -(const PIPoint<Type> & p) {return translated(-p);}
//!
bool operator ==(const PILine<Type> & r) const {return (p0 == r.p0 && p1 == r.p1);}
//!
bool operator !=(const PILine<Type> & r) const {return (p1 != r.p1 || p1 != r.p1);}
};
template<typename Type>
PICout operator <<(PICout & s, const PILine<Type> & v) {
s.setControl(0, true);
s << "Line{" << v.p0 << ", " << v.p1 << "}";
s.restoreControl();
return s;
}
typedef PILine<int> PILinei;
typedef PILine<uint> PILineu;
typedef PILine<float> PILinef;
typedef PILine<double> PILined;
#endif // PILINE_H

View File

@@ -471,5 +471,5 @@ double randomn(double dv, double sv) {
double randomd() { double randomd() {
return (double) randomi() / RAND_MAX * 2. - 1.; return (double) rand() / RAND_MAX * 2. - 1.;
} }

View File

@@ -1,10 +1,20 @@
/*! @file pimathbase.h /*! \file pimathbase.h
* @brief Basic mathematical functions and defines * \defgroup Math
* \brief
* \~english Basic mathematical functions and defines
* \~russian Базовые математические функции и дефайны
* \~\authors
* \~english
* Ivan Pelipenko peri4ko@yandex.ru;
* Andrey Bychkov work.a.b@yandex.ru;
* \~russian
* Иван Пелипенко peri4ko@yandex.ru;
* Андрей Бычков work.a.b@yandex.ru;
*/ */
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Basic mathematical functions and defines Basic mathematical functions and defines
Ivan Pelipenko peri4ko@yandex.ru Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU Lesser General Public License as published by

164
libs/main/math/pipoint.h Normal file
View File

@@ -0,0 +1,164 @@
//! \file pipoint.h
//! \ingroup Math
//! \brief
//! \~english Two-dimensional point class
//! \~russian Класс двумерной точки
//! \~\authors
//! \~english
//! Ivan Pelipenko peri4ko@yandex.ru;
//! Andrey Bychkov work.a.b@yandex.ru;
//! \~russian
//! Иван Пелипенко peri4ko@yandex.ru;
//! Андрей Бычков work.a.b@yandex.ru;
/*
PIP - Platform Independent Primitives
Two-dimensional point class
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@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
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PIPOINT_H
#define PIPOINT_H
#include "pimathbase.h"
//! \brief
//! \~english Two-dimensional point class
//! \~russian Класс двумерной точки
template<typename Type>
class PIP_EXPORT PIPoint {
static_assert(std::is_arithmetic<Type>::value, "Type must be arithmetic");
public:
Type x;
Type y;
//!
PIPoint() {x = y = Type();}
//!
PIPoint(Type x_, Type y_) {set(x_, y_);}
//!
PIPoint<Type> & set(Type x_, Type y_) {
x = x_;
y = y_;
return *this;
}
//!
PIPoint<Type> & set(const PIPoint<Type> & p) {
x = p.x;
y = p.y;
return *this;
}
//!
PIPoint<Type> & translate(Type x_, Type y_) {
x += x_;
y += y_;
return *this;
}
//!
PIPoint<Type> & translate(const PIPoint<Type> & p) {
x += p.x;
y += p.y;
return *this;
}
//!
PIPoint<Type> translated(Type x_, Type y_) const {
PIPoint<Type> rp(*this);
rp.translate(x_, y_);
return rp;
}
//!
PIPoint<Type> translated(const PIPoint<Type> & p) const {
PIPoint<Type> rp(*this);
rp.translate(p);
return rp;
}
//!
PIPoint<Type> & move(Type x_, Type y_) {return translate(x_, y_);}
//!
PIPoint<Type> & move(const PIPoint<Type> & p) {return translate(p);}
//!
PIPoint<Type> moved(Type x_, Type y_) const {
PIPoint<Type> rp(*this);
rp.translate(x_, y_);
return rp;
}
//!
PIPoint<Type> moved(const PIPoint<Type> & p) const {
PIPoint<Type> rp(*this);
rp.translate(p);
return rp;
}
//!
double angleRad() const {return atan2(y, x);}
//!
double angleDeg() const {return toDeg(atan2(y, x));}
//!
PIPoint<Type> toPolar(bool isDeg = false) const {return PIPoint<Type>(sqrt(x*x + y*y), isDeg ? angleDeg() : angleRad());}
//!
static PIPoint<Type> fromPolar(const PIPoint<Type> & p) {return PIPoint<Type>(p.y * cos(p.x), p.y * sin(p.x));}
//!
void operator +=(const PIPoint<Type> & p) {translate(p);}
//!
PIPoint<Type> operator +(const PIPoint<Type> & p) {return PIPoint<Type>(x + p.x, y + p.y);}
//!
PIPoint<Type> operator +(const Type & p) {return PIPoint<Type>(x + p, y + p);}
//!
PIPoint<Type> operator -(const PIPoint<Type> & p) {return PIPoint<Type>(x - p.x, y - p.y);}
//!
PIPoint<Type> operator -(const Type & p) {return PIPoint<Type>(x - p, y - p);}
//!
PIPoint<Type> operator -() {return PIPoint<Type>(-x, -y);}
//!
bool operator ==(const PIPoint<Type> & p) const {return (x == p.x && y == p.y);}
//!
bool operator !=(const PIPoint<Type> & p) const {return (x != p.x || y != p.y);}
};
template<typename Type>
PICout operator <<(PICout & s, const PIPoint<Type> & v) {
s.setControl(0, true);
s << "Point{" << v.x << ", " << v.y << "}";
s.restoreControl();
return s;
}
typedef PIPoint<int> PIPointi;
typedef PIPoint<uint> PIPointu;
typedef PIPoint<float> PIPointf;
typedef PIPoint<double> PIPointd;
#endif // PIPOINT_H

363
libs/main/math/pirect.h Normal file
View File

@@ -0,0 +1,363 @@
//! \file pirect.h
//! \ingroup Math
//! \brief
//! \~english Rect class
//! \~russian Класс прямоугольника
//! \~\authors
//! \~english
//! Ivan Pelipenko peri4ko@yandex.ru;
//! Andrey Bychkov work.a.b@yandex.ru;
//! \~russian
//! Иван Пелипенко peri4ko@yandex.ru;
//! Андрей Бычков work.a.b@yandex.ru;
/*
PIP - Platform Independent Primitives
Rect class
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@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
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PIRECT_H
#define PIRECT_H
#include "pipoint.h"
//! \brief
//! \~english Rect class
//! \~russian Класс прямоугольника
//! \~\details
//! \~russian
//! Этот класс описывает прямоугольник на плоскости в прямоугольной системе координат
template<typename Type>
class PIP_EXPORT PIRect {
static_assert(std::is_arithmetic<Type>::value, "Type must be arithmetic");
public:
//!
PIRect() {}
//! \brief
//! \~russian Конструктор прямоугольника из координат левого нижнего угла и размеров ширины и высоты
PIRect(Type left_, Type bottom_, Type width_, Type height_) {
set(left_, bottom_, width_, height_);
normalize();
}
//! \brief
//! \~russian Конструктор прямоугольника из координат левого нижнего угла и правого верхнего угла
PIRect(const PIPoint<Type> & bottom_left, const PIPoint<Type> & top_right) {
bl = bottom_left;
tr = top_right;
normalize();
}
// PIRect(const PIPoint<Type> & p0, const PIPoint<Type> & p1, const PIPoint<Type> & p2) {
// set(piMin<Type>(p0.x, p1.x, p2.x), piMin<Type>(p0.y, p1.y, p2.y),
// piMax<Type>(p0.x, p1.x, p2.x), piMax<Type>(p0.y, p1.y, p2.y));
// }
//!
PIRect<Type> & set(Type left_, Type bottom_, Type width_, Type height_) {
bl = PIPoint<Type>(left_, bottom_);
tr = PIPoint<Type>(left_ + width_, bottom_ + height_);
return normalize();
}
//!
PIRect<Type> & set(const PIPoint<Type> & top_left, const PIPoint<Type> & bottom_right) {
bl = top_left;
tr = bottom_right;
return normalize();
}
//! \brief
//! \~russian Возвращает true если точка с указанными координатами принадлежит прямоугольнику
bool pointIn(Type x, Type y) const {
return (x <= bl.x && x >= tr.x && y <= bl.y && y >= tr.y);
}
//! \brief
//! \~russian Возвращает true если точка с указанными координатами принадлежит прямоугольнику
bool pointIn(const PIPoint<Type> & p) const {
return pointIn(p.x, p.y);
}
//!
bool isEmpty() const {
return (width() == 0 && height() == 0);
}
//!
PIRect<Type> & translate(Type x, Type y) {
bl.translate(x, y);
tr.translate(x, y);
return *this;
}
//!
PIRect<Type> & translate(const PIPoint<Type> & p) {
bl.translate(p);
tr.translate(p);
return *this;
}
//!
PIRect<Type> translated(Type x, Type y) const {
PIRect<Type> r(*this);
r.translate(x, y);
return r;
}
//!
PIRect<Type> translated(const PIPoint<Type> & p) const {
PIRect<Type> r(*this);
r.translate(p);
return r;
}
//!
PIRect<Type> & move(Type x, Type y) {return translate(x, y);}
//!
PIRect<Type> & move(const PIPoint<Type> & p) {return translate(p);}
//!
PIRect<Type> moved(Type x, Type y) const {
PIRect<Type> r(*this);
r.translate(x, y);
return r;
}
//!
PIRect<Type> moved(const PIPoint<Type> & p) const {
PIRect<Type> r(*this);
r.translate(p);
return r;
}
//!
PIRect<Type> & scale(Type x, Type y) {
setWidth(width() * x);
setHeight(height() * y);
return normalize();
}
//!
PIRect<Type> & scale(Type s) {return scale(s, s);}
//!
PIRect<Type> & scale(const PIPoint<Type> & p) {return scale(p.x, p.y);}
//!
PIRect<Type> scaled(Type x, Type y) const {
PIRect<Type> r(*this);
r.scale(x, y);
return r;
}
//!
PIRect<Type> scaled(Type s) const {
PIRect<Type> r(*this);
r.scale(s);
return r;
}
//!
PIRect<Type> scaled(const PIPoint<Type> & p) const {
PIRect<Type> r(*this);
r.scale(p);
return r;
}
//!
PIRect<Type> & normalize() {
if (bl.x > tr.x) piSwap<Type>(bl.x, tr.x);
if (bl.y > tr.y) piSwap<Type>(bl.y, tr.y);
return *this;
}
//!
PIRect<Type> normalized() const {
PIRect<Type> r(*this);
r.normalize();
return r;
}
//!
PIRect<Type> & unite(const PIRect<Type> & r) {
bl.x = piMax<Type>(bl.x, r.left());
bl.y = piMax<Type>(bl.y, r.bottom());
tr.x = piMin<Type>(tr.x, r.right());
tr.y = piMin<Type>(tr.y, r.top());
return normalize();
}
//!
PIRect<Type> united(const PIRect<Type> & rect) const {
PIRect<Type> r(*this);
r.unite(rect);
return r;
}
//!
PIRect<Type> & intersect(const PIRect<Type> & r) {
bl.x = piMax<Type>(bl.x, r.left());
bl.y = piMax<Type>(bl.y, r.bottom());
tr.x = piMin<Type>(tr.x, r.right());
tr.y = piMin<Type>(tr.y, r.top());
if (bl.x > tr.x || bl.y > tr.y) bl = tr = PIPoint<Type>();
return *this;
}
//!
PIRect<Type> intersected(const PIRect<Type> & rect) const {
PIRect<Type> r(*this);
r.intersect(rect);
return r;
}
//!
Type top() const {return tr.y;}
//!
Type left() const {return bl.x;}
//!
Type right() const {return tr.x;}
//!
Type bottom() const {return bl.y;}
//!
Type width() const {return tr.x - bl.x;}
//!
Type height() const {return tr.y - bl.y;}
//!
PIPoint<Type> topLeft() const {return PIPoint<Type>(bl.x, tr.y);}
//!
PIPoint<Type> topRigth() const {return tr;}
//!
PIPoint<Type> bottomLeft() const {return bl;}
//!
PIPoint<Type> bottomRight() const {return PIPoint<Type>(tr.x, bl.y);}
//!
PIPoint<Type> center() const {return bl.moved(width()/2, height()/2);}
//!
void setTop(Type v) {tr.y = v; normalize();}
//!
void setLeft(Type v) {bl.x = v; normalize();}
//!
void setRigth(Type v) {tr.x = v; normalize();}
//!
void setBottom(Type v) {bl.y = v; normalize();}
//!
void setWidth(Type v) {setTop(bl.x + v);}
//!
void setHeight(Type v) {setRigth(bl.y + v);}
//!
void setTopLeft(const PIPoint<Type> & p) {setLeft(p.x); setTop(p.y);}
//!
void setBottomRight(const PIPoint<Type> & p) {setRigth(p.x); setBottom(p.y);}
//!
void setBottomLeft(const PIPoint<Type> & p) {bl = p; normalize();}
//!
void setTopRigth(const PIPoint<Type> & p) {tr = p; normalize();}
//!
void setCenter(const PIPoint<Type> & p) {
Type w = width();
Type h = height();
bl = p.translated(-w/2, -h/2);
tr = PIPoint<Type>(bl.x + w, bl.y + h);
}
//!
void setSize(Type w, Type h) {
tr = PIPoint<Type>(bl.x + w, bl.y + h);
normalize();
}
//!
void operator +=(Type x) {translate(x, x);}
//!
void operator +=(const PIPoint<Type> & p) {translate(p);}
//!
void operator -=(Type x) {translate(-x, -x);}
//!
void operator -=(const PIPoint<Type> & p) {translate(-p);}
//!
void operator |=(const PIRect<Type> & r) {unite(r);}
//!
void operator &=(const PIRect<Type> & r) {intersect(r);}
//!
PIRect<Type> operator +(const PIPoint<Type> & p) {return translated(p);}
//!
PIRect<Type> operator -(const PIPoint<Type> & p) {return translated(-p);}
//!
PIRect<Type> operator |(const PIRect<Type> & r) {return united(r);}
//!
PIRect<Type> operator &(const PIRect<Type> & r) {return intersected(r);}
//!
bool operator ==(const PIRect<Type> & r) const {return (bl == r.bl && tr == r.tr);}
//!
bool operator !=(const PIRect<Type> & r) const {return (bl != r.bl || tr != r.tr);}
private:
PIPoint<Type> bl;
PIPoint<Type> tr;
};
template<typename Type>
PICout operator <<(PICout & s, const PIRect<Type> & v) {
s.setControl(0, true);
s << "Rect{" << v.bottomLeft() << ":" << v.width() << "x" << v.height() << "}";
s.restoreControl();
return s;
}
typedef PIRect<int> PIRecti;
typedef PIRect<uint> PIRectu;
typedef PIRect<float> PIRectf;
typedef PIRect<double> PIRectd;
#endif // PIRECT_H

View File

@@ -51,13 +51,16 @@
#ifdef PIP_FREERTOS #ifdef PIP_FREERTOS
# define FREERTOS # define FREERTOS
#endif #endif
#if defined(FREERTOS) || defined(PLATFORMIO)
# define MICRO_PIP
#endif
#ifndef WINDOWS #ifndef WINDOWS
# ifndef QNX # ifndef QNX
# ifndef FREE_BSD # ifndef FREE_BSD
# ifndef MAC_OS # ifndef MAC_OS
# ifndef ANDROID # ifndef ANDROID
# ifndef BLACKBERRY # ifndef BLACKBERRY
# ifndef FREERTOS # ifndef MICRO_PIP
# define LINUX # define LINUX
# endif # endif
# endif # endif
@@ -84,6 +87,10 @@
# define CC_OTHER # define CC_OTHER
#endif #endif
#ifdef __AVR__
# define CC_AVR_GCC
#endif
#ifdef WINDOWS #ifdef WINDOWS
# ifdef CC_GCC # ifdef CC_GCC
# define typeof __typeof # define typeof __typeof

View File

@@ -17,7 +17,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef PIP_FREERTOS #ifndef MICRO_PIP
#include "pilibrary.h" #include "pilibrary.h"
#include "piincludes_p.h" #include "piincludes_p.h"
@@ -110,4 +110,4 @@ void PILibrary::getLastError() {
#endif #endif
} }
#endif // PIP_FREERTOS #endif // MICRO_PIP

View File

@@ -23,7 +23,7 @@
#ifndef PILIBRARY_H #ifndef PILIBRARY_H
#define PILIBRARY_H #define PILIBRARY_H
#ifndef PIP_FREERTOS #ifndef MICRO_PIP
#include "pistring.h" #include "pistring.h"
@@ -50,5 +50,5 @@ private:
}; };
#endif // PIP_FREERTOS #endif // MICRO_PIP
#endif // PILIBRARY_H #endif // PILIBRARY_H

View File

@@ -17,7 +17,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef PIP_FREERTOS #ifndef MICRO_PIP
#include "piplugin.h" #include "piplugin.h"
#include "pifile.h" #include "pifile.h"
@@ -408,4 +408,4 @@ PIString PIPluginLoader::libExtension() {
} }
#endif // PIP_FREERTOS #endif // MICRO_PIP

View File

@@ -23,7 +23,7 @@
#ifndef PIPLUGIN_H #ifndef PIPLUGIN_H
#define PIPLUGIN_H #define PIPLUGIN_H
#ifndef PIP_FREERTOS #ifndef MICRO_PIP
#include "pilibrary.h" #include "pilibrary.h"
#include "pistringlist.h" #include "pistringlist.h"
@@ -212,5 +212,5 @@ private:
}; };
#endif // PIP_FREERTOS #endif // MICRO_PIP
#endif // PIPLUGIN_H #endif // PIPLUGIN_H

View File

@@ -17,7 +17,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef PIP_FREERTOS #ifndef MICRO_PIP
#include "piincludes_p.h" #include "piincludes_p.h"
#include "piprocess.h" #include "piprocess.h"
@@ -66,7 +66,7 @@ void PIProcess::exec_() {
startOnce(); startOnce();
//cout << "exec wait" << endl; //cout << "exec wait" << endl;
while (!is_exec) while (!is_exec)
msleep(PIP_MIN_MSLEEP); piMinSleep();
//cout << "exec end" << endl; //cout << "exec end" << endl;
} }
@@ -172,7 +172,7 @@ void PIProcess::startProc(bool detached) {
if (execve(str.data(), a, e) < 0) if (execve(str.data(), a, e) < 0)
piCoutObj << "\"execve" << str << args << "\" error :" << errorString(); piCoutObj << "\"execve" << str << args << "\" error :" << errorString();
} else { } else {
msleep(PIP_MIN_MSLEEP); piMinSleep;
//cout << "wait" << endl; //cout << "wait" << endl;
if (!detached) { if (!detached) {
wait(&exit_code); wait(&exit_code);
@@ -290,5 +290,5 @@ PIString PIProcess::getEnvironmentVariable(const PIString & variable) {
return PIString(); return PIString();
} }
#endif // PIP_FREERTOS #endif // MICRO_PIP

View File

@@ -23,7 +23,7 @@
#ifndef PIPROCESS_H #ifndef PIPROCESS_H
#define PIPROCESS_H #define PIPROCESS_H
#ifndef PIP_FREERTOS #ifndef MICRO_PIP
#include "pithread.h" #include "pithread.h"
#include "pifile.h" #include "pifile.h"
@@ -104,5 +104,5 @@ private:
}; };
#endif // PIP_FREERTOS #endif // MICRO_PIP
#endif // PIPROCESS_H #endif // PIPROCESS_H

View File

@@ -259,7 +259,7 @@ uint PISystemInfo::machineID() {
if (ret == 0) { if (ret == 0) {
CRC_32 crc = standardCRC_32(); CRC_32 crc = standardCRC_32();
ret = crc.calculate(machineKey().toByteArray()); ret = crc.calculate(machineKey().toByteArray());
piCout << "machineID \"" << machineKey() << "\" =" << PICoutManipulators::Hex << ret; //piCout << "machineID \"" << machineKey() << "\" =" << PICoutManipulators::Hex << ret;
} }
return ret; return ret;
} }

View File

@@ -59,7 +59,7 @@ PISystemMonitor::ThreadStatsFixed::ThreadStatsFixed() {
} }
#ifndef FREERTOS #ifndef MICRO_PIP
PRIVATE_DEFINITION_START(PISystemMonitor) PRIVATE_DEFINITION_START(PISystemMonitor)
#ifndef WINDOWS #ifndef WINDOWS
# ifdef MAC_OS # ifdef MAC_OS
@@ -83,7 +83,7 @@ PRIVATE_DEFINITION_END(PISystemMonitor)
PISystemMonitor::PISystemMonitor(): PIThread() { PISystemMonitor::PISystemMonitor(): PIThread() {
pID_ = cycle = 0; pID_ = cycle = 0;
cpu_count = PISystemInfo::instance()->processorsCount; cpu_count = PISystemInfo::instance()->processorsCount;
#ifndef FREERTOS #ifndef MICRO_PIP
#ifndef WINDOWS #ifndef WINDOWS
# ifdef QNX # ifdef QNX
page_size = 4096; page_size = 4096;
@@ -104,7 +104,7 @@ PISystemMonitor::~PISystemMonitor() {
} }
#ifndef FREERTOS #ifndef MICRO_PIP
bool PISystemMonitor::startOnProcess(int pID, int interval_ms) { bool PISystemMonitor::startOnProcess(int pID, int interval_ms) {
stop(); stop();
pID_ = pID; pID_ = pID;
@@ -134,7 +134,7 @@ bool PISystemMonitor::startOnProcess(int pID, int interval_ms) {
bool PISystemMonitor::startOnSelf(int interval_ms) { bool PISystemMonitor::startOnSelf(int interval_ms) {
#ifndef FREERTOS #ifndef MICRO_PIP
bool ret = startOnProcess(PIProcess::currentPID(), interval_ms); bool ret = startOnProcess(PIProcess::currentPID(), interval_ms);
cycle = -1; cycle = -1;
#else #else
@@ -145,9 +145,9 @@ bool PISystemMonitor::startOnSelf(int interval_ms) {
PIVector<PISystemMonitor::ThreadStats> PISystemMonitor::threadsStatistic() const { PIVector<PISystemMonitor::ThreadStats> PISystemMonitor::threadsStatistic() const {
mutex_.lock(); lock();
PIVector<PISystemMonitor::ThreadStats> ret = cur_ts; PIVector<PISystemMonitor::ThreadStats> ret = cur_ts;
mutex_.unlock(); unlock();
return ret; return ret;
} }
@@ -196,7 +196,7 @@ void PISystemMonitor::run() {
//piCout << tbid.keys().toType<uint>(); //piCout << tbid.keys().toType<uint>();
ProcessStats tstat; ProcessStats tstat;
tstat.ID = pID_; tstat.ID = pID_;
#ifdef FREERTOS #ifdef MICRO_PIP
piForeach (PIThread * t, tv) piForeach (PIThread * t, tv)
if (t->isPIObject()) if (t->isPIObject())
gatherThread(t->tid()); gatherThread(t->tid());
@@ -341,9 +341,9 @@ void PISystemMonitor::run() {
//piCout << ts_new.cpu_load_user; //piCout << ts_new.cpu_load_user;
} }
last_tm = cur_tm; last_tm = cur_tm;
mutex_.lock(); lock();
cur_ts = cur_tm.values(); cur_ts = cur_tm.values();
mutex_.unlock(); unlock();
tstat.ram_total = totalRAM(); tstat.ram_total = totalRAM();
tstat.ram_used = usedRAM(); tstat.ram_used = usedRAM();
tstat.ram_free = freeRAM(); tstat.ram_free = freeRAM();
@@ -357,7 +357,7 @@ void PISystemMonitor::run() {
void PISystemMonitor::gatherThread(llong id) { void PISystemMonitor::gatherThread(llong id) {
PISystemMonitor::ThreadStats ts; PISystemMonitor::ThreadStats ts;
ts.id = id; ts.id = id;
#ifdef FREERTOS #ifdef MICRO_PIP
ts.name = tbid.value(id, "<PIThread>"); ts.name = tbid.value(id, "<PIThread>");
#else #else
ts.name = tbid.value(id, "<non-PIThread>"); ts.name = tbid.value(id, "<non-PIThread>");

View File

@@ -79,7 +79,7 @@ public:
PIString name; PIString name;
}; };
#ifndef FREERTOS #ifndef MICRO_PIP
bool startOnProcess(int pID, int interval_ms = 1000); bool startOnProcess(int pID, int interval_ms = 1000);
#endif #endif
bool startOnSelf(int interval_ms = 1000); bool startOnSelf(int interval_ms = 1000);
@@ -106,7 +106,7 @@ private:
PIMap<llong, PIString> tbid; PIMap<llong, PIString> tbid;
mutable PIMutex stat_mutex; mutable PIMutex stat_mutex;
int pID_, page_size, cpu_count, cycle; int pID_, page_size, cpu_count, cycle;
#ifndef FREERTOS #ifndef MICRO_PIP
PRIVATE_DECLARATION(PIP_EXPORT) PRIVATE_DECLARATION(PIP_EXPORT)
#endif #endif

View File

@@ -19,7 +19,7 @@
#include "pisystemtests.h" #include "pisystemtests.h"
#ifndef PIP_FREERTOS #ifndef MICRO_PIP
# include "piconfig.h" # include "piconfig.h"
#endif #endif
@@ -35,7 +35,7 @@ namespace PISystemTests {
PISystemTests::PISystemTestReader::PISystemTestReader() { PISystemTests::PISystemTestReader::PISystemTestReader() {
#if !defined(WINDOWS) && !defined(FREERTOS) #if !defined(WINDOWS) && !defined(MICRO_PIP)
PIConfig conf(PIStringAscii("/etc/pip.conf"), PIIODevice::ReadOnly); PIConfig conf(PIStringAscii("/etc/pip.conf"), PIIODevice::ReadOnly);
time_resolution_ns = conf.getValue(PIStringAscii("time_resolution_ns"), 1).toLong(); time_resolution_ns = conf.getValue(PIStringAscii("time_resolution_ns"), 1).toLong();
time_elapsed_ns = conf.getValue(PIStringAscii("time_elapsed_ns"), 0).toLong(); time_elapsed_ns = conf.getValue(PIStringAscii("time_elapsed_ns"), 0).toLong();

View File

@@ -17,38 +17,47 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "piconditionvar.h" #include "piplatform.h"
#include "pithread.h"
#include "pitime.h"
#ifdef WINDOWS #ifdef WINDOWS
# undef _WIN32_WINNT # undef _WIN32_WINNT
# define _WIN32_WINNT 0x0600 # define _WIN32_WINNT 0x0600
#endif
#include "piconditionvar.h"
#include "pithread.h"
#include "pitime.h"
#include "piincludes_p.h"
#ifdef WINDOWS
# include <synchapi.h> # include <synchapi.h>
# include <windef.h> # include <windef.h>
# include <winbase.h> # include <winbase.h>
#endif #endif
#ifdef FREERTOS
# include <event_groups.h>
#endif
PRIVATE_DEFINITION_START(PIConditionVariable) PRIVATE_DEFINITION_START(PIConditionVariable)
#ifdef WINDOWS #if defined(WINDOWS)
CONDITION_VARIABLE nativeHandle; CONDITION_VARIABLE
#elif defined(FREERTOS)
EventGroupHandle_t
#else #else
pthread_cond_t nativeHandle; pthread_cond_t
#endif #endif
bool isDestroying; nativeHandle;
PRIVATE_DEFINITION_END(PIConditionVariable) PRIVATE_DEFINITION_END(PIConditionVariable)
PIConditionVariable::PIConditionVariable() { PIConditionVariable::PIConditionVariable() {
#ifdef WINDOWS #if defined(WINDOWS)
InitializeConditionVariable(&PRIVATE->nativeHandle); InitializeConditionVariable(&PRIVATE->nativeHandle);
#elif defined(FREERTOS)
PRIVATE->nativeHandle = xEventGroupCreate();
#else #else
PRIVATE->isDestroying = false;
pthread_condattr_t condattr; pthread_condattr_t condattr;
pthread_condattr_init(&condattr); pthread_condattr_init(&condattr);
# ifndef MAC_OS # if !defined(MAC_OS)
pthread_condattr_setclock(&condattr, CLOCK_MONOTONIC); pthread_condattr_setclock(&condattr, CLOCK_MONOTONIC);
# endif # endif
memset(&(PRIVATE->nativeHandle), 0, sizeof(PRIVATE->nativeHandle)); memset(&(PRIVATE->nativeHandle), 0, sizeof(PRIVATE->nativeHandle));
@@ -58,7 +67,9 @@ PIConditionVariable::PIConditionVariable() {
PIConditionVariable::~PIConditionVariable() { PIConditionVariable::~PIConditionVariable() {
#ifdef WINDOWS #if defined(WINDOWS)
#elif defined(FREERTOS)
vEventGroupDelete(PRIVATE->nativeHandle);
#else #else
pthread_cond_destroy(&PRIVATE->nativeHandle); pthread_cond_destroy(&PRIVATE->nativeHandle);
#endif #endif
@@ -66,8 +77,11 @@ PIConditionVariable::~PIConditionVariable() {
void PIConditionVariable::wait(PIMutex& lk) { void PIConditionVariable::wait(PIMutex& lk) {
#ifdef WINDOWS #if defined(WINDOWS)
SleepConditionVariableCS(&PRIVATE->nativeHandle, (PCRITICAL_SECTION)lk.handle(), INFINITE); SleepConditionVariableCS(&PRIVATE->nativeHandle, (PCRITICAL_SECTION)lk.handle(), INFINITE);
#elif defined(FREERTOS)
xEventGroupClearBits(PRIVATE->nativeHandle, 1);
xEventGroupWaitBits(PRIVATE->nativeHandle, 1, pdTRUE, pdTRUE, portMAX_DELAY);
#else #else
pthread_cond_wait(&PRIVATE->nativeHandle, (pthread_mutex_t*)lk.handle()); pthread_cond_wait(&PRIVATE->nativeHandle, (pthread_mutex_t*)lk.handle());
#endif #endif
@@ -79,20 +93,27 @@ void PIConditionVariable::wait(PIMutex& lk, const std::function<bool()>& conditi
while (true) { while (true) {
isCondition = condition(); isCondition = condition();
if (isCondition) break; if (isCondition) break;
#ifdef WINDOWS #if defined(WINDOWS)
SleepConditionVariableCS(&PRIVATE->nativeHandle, (PCRITICAL_SECTION)lk.handle(), INFINITE); SleepConditionVariableCS(&PRIVATE->nativeHandle, (PCRITICAL_SECTION)lk.handle(), INFINITE);
#elif defined(FREERTOS)
xEventGroupClearBits(PRIVATE->nativeHandle, 1);
xEventGroupWaitBits(PRIVATE->nativeHandle, 1, pdTRUE, pdTRUE, portMAX_DELAY);
#else #else
pthread_cond_wait(&PRIVATE->nativeHandle, (pthread_mutex_t*)lk.handle()); pthread_cond_wait(&PRIVATE->nativeHandle, (pthread_mutex_t*)lk.handle());
#endif #endif
if (PRIVATE->isDestroying) return;
} }
} }
bool PIConditionVariable::waitFor(PIMutex &lk, int timeoutMs) { bool PIConditionVariable::waitFor(PIMutex &lk, int timeoutMs) {
bool isNotTimeout; bool isNotTimeout;
#ifdef WINDOWS #if defined(WINDOWS)
isNotTimeout = SleepConditionVariableCS(&PRIVATE->nativeHandle, (PCRITICAL_SECTION)lk.handle(), timeoutMs) != 0; isNotTimeout = SleepConditionVariableCS(&PRIVATE->nativeHandle, (PCRITICAL_SECTION)lk.handle(), timeoutMs) != 0;
#elif defined(FREERTOS)
xEventGroupClearBits(PRIVATE->nativeHandle, 1);
EventBits_t uxBits;
uxBits = xEventGroupWaitBits(PRIVATE->nativeHandle, 1, pdTRUE, pdTRUE, timeoutMs / portTICK_PERIOD_MS);
isNotTimeout = (uxBits & 1) != 0;
#else #else
timespec expire_ts; timespec expire_ts;
PISystemTime st = PISystemTime::current(true); PISystemTime st = PISystemTime::current(true);
@@ -100,42 +121,50 @@ bool PIConditionVariable::waitFor(PIMutex &lk, int timeoutMs) {
st.toTimespec(&expire_ts); st.toTimespec(&expire_ts);
isNotTimeout = pthread_cond_timedwait(&PRIVATE->nativeHandle, (pthread_mutex_t*)lk.handle(), &expire_ts) == 0; isNotTimeout = pthread_cond_timedwait(&PRIVATE->nativeHandle, (pthread_mutex_t*)lk.handle(), &expire_ts) == 0;
#endif #endif
if (PRIVATE->isDestroying) return false;
return isNotTimeout; return isNotTimeout;
} }
bool PIConditionVariable::waitFor(PIMutex& lk, int timeoutMs, const std::function<bool()> &condition) { bool PIConditionVariable::waitFor(PIMutex& lk, int timeoutMs, const std::function<bool()> &condition) {
bool isCondition; bool isCondition;
#ifdef WINDOWS #if defined(WINDOWS) || defined(FREERTOS)
PITimeMeasurer measurer; PITimeMeasurer measurer;
#else #else
timespec expire_ts; timespec expire_ts;
PISystemTime st = PISystemTime::current(true); PISystemTime st = PISystemTime::current(true);
st.addMilliseconds(timeoutMs); st.addMilliseconds(timeoutMs);
st.toTimespec(&expire_ts); st.toTimespec(&expire_ts);
#endif
#ifdef FREERTOS
xEventGroupClearBits(PRIVATE->nativeHandle, 1);
#endif #endif
while (true) { while (true) {
isCondition = condition(); isCondition = condition();
if (isCondition) break; if (isCondition) break;
#ifdef WINDOWS bool isTimeout;
bool isTimeout = SleepConditionVariableCS( #if defined(WINDOWS)
isTimeout = SleepConditionVariableCS(
&PRIVATE->nativeHandle, &PRIVATE->nativeHandle,
(PCRITICAL_SECTION)lk.handle(), (PCRITICAL_SECTION)lk.handle(),
timeoutMs - (int)measurer.elapsed_m()) == 0; timeoutMs - (int)measurer.elapsed_m()) == 0;
#elif defined(FREERTOS)
EventBits_t uxBits;
uxBits = xEventGroupWaitBits(PRIVATE->nativeHandle, 1, pdTRUE, pdTRUE, (timeoutMs - (int)measurer.elapsed_m()) / portTICK_PERIOD_MS);
isTimeout = (uxBits & 1) == 0;
#else #else
bool isTimeout = pthread_cond_timedwait(&PRIVATE->nativeHandle, (pthread_mutex_t*)lk.handle(), &expire_ts) != 0; isTimeout = pthread_cond_timedwait(&PRIVATE->nativeHandle, (pthread_mutex_t*)lk.handle(), &expire_ts) != 0;
#endif #endif
if (isTimeout) return false; if (isTimeout) return false;
if (PRIVATE->isDestroying) return false;
} }
return true; return true;
} }
void PIConditionVariable::notifyOne() { void PIConditionVariable::notifyOne() {
#ifdef WINDOWS #if defined(WINDOWS)
WakeConditionVariable(&PRIVATE->nativeHandle); WakeConditionVariable(&PRIVATE->nativeHandle);
#elif defined(FREERTOS)
xEventGroupSetBits(PRIVATE->nativeHandle, 1);
#else #else
pthread_cond_signal(&PRIVATE->nativeHandle); pthread_cond_signal(&PRIVATE->nativeHandle);
#endif #endif
@@ -143,8 +172,10 @@ void PIConditionVariable::notifyOne() {
void PIConditionVariable::notifyAll() { void PIConditionVariable::notifyAll() {
#ifdef WINDOWS #if defined(WINDOWS)
WakeAllConditionVariable(&PRIVATE->nativeHandle); WakeAllConditionVariable(&PRIVATE->nativeHandle);
#elif defined(FREERTOS)
xEventGroupSetBits(PRIVATE->nativeHandle, 1);
#else #else
pthread_cond_broadcast(&PRIVATE->nativeHandle); pthread_cond_broadcast(&PRIVATE->nativeHandle);
#endif #endif

View File

@@ -162,7 +162,7 @@ private:
return; return;
} }
if (ret > 0) { if (ret > 0) {
piMSleep(PIP_MIN_MSLEEP); piMinSleep();
return; return;
} }
diag_.received(1); diag_.received(1);

View File

@@ -36,8 +36,10 @@
#include "pimutex.h" #include "pimutex.h"
#include "piincludes_p.h" #include "piincludes_p.h"
#ifdef WINDOWS #if defined(WINDOWS)
# include <synchapi.h> # include <synchapi.h>
#elif defined(FREERTOS)
# include <semphr.h>
#else #else
# include <pthread.h> # include <pthread.h>
#endif #endif
@@ -45,8 +47,10 @@
PRIVATE_DEFINITION_START(PIMutex) PRIVATE_DEFINITION_START(PIMutex)
#ifdef WINDOWS #if defined(WINDOWS)
CRITICAL_SECTION CRITICAL_SECTION
#elif defined(FREERTOS)
SemaphoreHandle_t
#else #else
pthread_mutex_t pthread_mutex_t
#endif #endif
@@ -65,8 +69,10 @@ PIMutex::~PIMutex() {
void PIMutex::lock() { void PIMutex::lock() {
#ifdef WINDOWS #if defined(WINDOWS)
EnterCriticalSection(&(PRIVATE->mutex)); EnterCriticalSection(&(PRIVATE->mutex));
#elif defined(FREERTOS)
xSemaphoreTake(PRIVATE->mutex, portMAX_DELAY);
#else #else
pthread_mutex_lock(&(PRIVATE->mutex)); pthread_mutex_lock(&(PRIVATE->mutex));
#endif #endif
@@ -74,8 +80,10 @@ void PIMutex::lock() {
void PIMutex::unlock() { void PIMutex::unlock() {
#ifdef WINDOWS #if defined(WINDOWS)
LeaveCriticalSection(&(PRIVATE->mutex)); LeaveCriticalSection(&(PRIVATE->mutex));
#elif defined(FREERTOS)
xSemaphoreGive(PRIVATE->mutex);
#else #else
pthread_mutex_unlock(&(PRIVATE->mutex)); pthread_mutex_unlock(&(PRIVATE->mutex));
#endif #endif
@@ -84,8 +92,10 @@ void PIMutex::unlock() {
bool PIMutex::tryLock() { bool PIMutex::tryLock() {
bool ret = bool ret =
#ifdef WINDOWS #if defined(WINDOWS)
(TryEnterCriticalSection(&(PRIVATE->mutex)) != 0); (TryEnterCriticalSection(&(PRIVATE->mutex)) != 0);
#elif defined(FREERTOS)
xSemaphoreTake(PRIVATE->mutex, 0);
#else #else
(pthread_mutex_trylock(&(PRIVATE->mutex)) == 0); (pthread_mutex_trylock(&(PRIVATE->mutex)) == 0);
#endif #endif
@@ -94,13 +104,19 @@ bool PIMutex::tryLock() {
void * PIMutex::handle() { void * PIMutex::handle() {
#ifdef FREERTOS
return PRIVATE->mutex;
#else
return (void*)&(PRIVATE->mutex); return (void*)&(PRIVATE->mutex);
#endif
} }
void PIMutex::init() { void PIMutex::init() {
#ifdef WINDOWS #if defined(WINDOWS)
InitializeCriticalSection(&(PRIVATE->mutex)); InitializeCriticalSection(&(PRIVATE->mutex));
#elif defined(FREERTOS)
PRIVATE->mutex = xSemaphoreCreateMutex();
#else #else
pthread_mutexattr_t attr; pthread_mutexattr_t attr;
memset(&attr, 0, sizeof(attr)); memset(&attr, 0, sizeof(attr));
@@ -114,8 +130,10 @@ void PIMutex::init() {
void PIMutex::destroy() { void PIMutex::destroy() {
#ifdef WINDOWS #if defined(WINDOWS)
DeleteCriticalSection(&(PRIVATE->mutex)); DeleteCriticalSection(&(PRIVATE->mutex));
#elif defined(FREERTOS)
vSemaphoreDelete(PRIVATE->mutex);
#else #else
pthread_mutex_destroy(&(PRIVATE->mutex)); pthread_mutex_destroy(&(PRIVATE->mutex));
#endif #endif

View File

@@ -24,7 +24,6 @@
#define PIMUTEX_H #define PIMUTEX_H
#include "piinit.h" #include "piinit.h"
#include <mutex>
class PIP_EXPORT PIMutex class PIP_EXPORT PIMutex

View File

@@ -25,6 +25,8 @@
#include "pithread.h" #include "pithread.h"
#include "piqueue.h" #include "piqueue.h"
#include "piconditionvar.h"
template <typename Tin, typename Tout> template <typename Tin, typename Tout>
class PIPipelineThread : public PIThread class PIPipelineThread : public PIThread
@@ -35,10 +37,10 @@ public:
cnt = 0; cnt = 0;
max_size = 0; max_size = 0;
wait_next_pipe = false; wait_next_pipe = false;
next_overload = false;
} }
~PIPipelineThread() { ~PIPipelineThread() {
stop(); stop();
cv.notifyAll();
if (!waitForFinish(1000)) { if (!waitForFinish(1000)) {
piCoutObj << "terminating self thread"; piCoutObj << "terminating self thread";
terminate(); terminate();
@@ -46,21 +48,27 @@ public:
} }
template <typename T> template <typename T>
void connectTo(PIPipelineThread<Tout, T> * next) { void connectTo(PIPipelineThread<Tout, T> * next) {
CONNECT2(void, Tout, bool *, this, calculated, next, enqueue) CONNECT3(void, Tout, bool, bool *, this, calculated, next, enqueue)
} }
EVENT2(calculated, const Tout &, v, bool *, overload) EVENT3(calculated, const Tout &, v, bool, wait, bool *, overload)
void enqueue(const Tin &v) {enqueue(v, 0);} EVENT_HANDLER3(void, enqueue, const Tin &, v, bool, wait, bool *, overload) {
EVENT_HANDLER2(void, enqueue, const Tin &, v, bool *, overload) {
mutex.lock(); mutex.lock();
//piCoutObj << "enque" << overload; //piCoutObj << "enque" << overload;
if (wait && max_size != 0) {
mutex_wait.lock();
while (in.size() >= max_size) cv_wait.wait(mutex_wait);
mutex_wait.unlock();
}
if (max_size == 0 || in.size() < max_size) { if (max_size == 0 || in.size() < max_size) {
in.enqueue(v); in.enqueue(v);
cv.notifyAll();
if (overload) *overload = false; if (overload) *overload = false;
} else { } else {
if (overload) *overload = true; if (overload) *overload = true;
} }
mutex.unlock(); mutex.unlock();
} }
void enqueue(const Tin &v, bool wait = false) {enqueue(v, wait, nullptr);}
const ullong * counterPtr() const {return &cnt;} const ullong * counterPtr() const {return &cnt;}
ullong counter() const {return cnt;} ullong counter() const {return cnt;}
bool isEmpty() { bool isEmpty() {
@@ -79,15 +87,18 @@ public:
} }
void clear() { void clear() {
mutex.lock(); mutex.lock();
mutex_wait.lock();
in.clear(); in.clear();
next_overload = false; cv_wait.notifyAll();
mutex_wait.unlock();
mutex.unlock(); mutex.unlock();
} }
void stopCalc(int wait_delay = 100) { void stopCalc(int wait_delay = 100) {
if (isRunning()) { if (isRunning()) {
stop(); stop();
cv.notifyAll();
if (!waitForFinish(wait_delay)) { if (!waitForFinish(wait_delay)) {
mutex_l.unlock(); mutex_last.unlock();
mutex.unlock(); mutex.unlock();
terminate(); terminate();
} }
@@ -95,18 +106,14 @@ public:
} }
Tout getLast() { Tout getLast() {
Tout ret; Tout ret;
mutex_l.lock(); mutex_last.lock();
ret = last; ret = last;
mutex_l.unlock(); mutex_last.unlock();
return ret; return ret;
} }
uint maxQueSize() { uint maxQueSize() {
uint ret; return max_size;
mutex.lock();
ret = max_size;
mutex.unlock();
return ret;
} }
void setMaxQueSize(uint count) { void setMaxQueSize(uint count) {
@@ -127,39 +134,35 @@ protected:
private: private:
void begin() {cnt = 0;} void begin() {cnt = 0;}
void run() { void run() {
//piCoutObj << "run ...";
mutex.lock(); mutex.lock();
if (in.isEmpty()) { while (in.isEmpty()) {
cv.wait(mutex);
if (terminating) {
mutex.unlock(); mutex.unlock();
piMSleep(10);
//piCoutObj << "run in empty";
return; return;
} }
if (next_overload && wait_next_pipe) { }
mutex.unlock(); mutex_wait.lock();
//piCoutObj << "wait" << &next_overload;
calculated(last, &next_overload);
piMSleep(10);
} else {
Tin t = in.dequeue(); Tin t = in.dequeue();
mutex.unlock(); mutex.unlock();
cv_wait.notifyAll();
mutex_wait.unlock();
bool ok = true; bool ok = true;
Tout r = calc(t, ok); Tout r = calc(t, ok);
if (ok) { if (ok) {
mutex_l.lock(); mutex_last.lock();
last = r; last = r;
mutex_l.unlock(); mutex_last.unlock();
cnt++; cnt++;
//piCoutObj << "calc ok" << &next_overload; //piCoutObj << "calc ok";
calculated(r, &next_overload); calculated(r, wait_next_pipe);
}
} }
//piCoutObj << "run ok"; //piCoutObj << "run ok";
} }
PIMutex mutex; PIMutex mutex, mutex_wait;
PIMutex mutex_l; PIConditionVariable cv, cv_wait;
PIMutex mutex_last;
bool wait_next_pipe; bool wait_next_pipe;
bool next_overload;
ullong cnt; ullong cnt;
PIQueue<Tin> in; PIQueue<Tin> in;
Tout last; Tout last;

View File

@@ -19,27 +19,40 @@
#include "piincludes_p.h" #include "piincludes_p.h"
#include "pithread.h" #include "pithread.h"
#include "pisystemtests.h"
#include "piintrospection_threads.h" #include "piintrospection_threads.h"
#ifndef MICRO_PIP
# include "pisystemtests.h"
#endif
#include <signal.h> #include <signal.h>
#ifdef WINDOWS #if defined(WINDOWS)
# define __THREAD_FUNC_RET__ uint __stdcall # define __THREAD_FUNC_RET__ uint __stdcall
#elif defined(FREERTOS)
# define __THREAD_FUNC_RET__ void
#else #else
# define __THREAD_FUNC_RET__ void* # define __THREAD_FUNC_RET__ void*
#endif #endif
#ifndef FREERTOS
# define __THREAD_FUNC_END__ 0
#else
# define __THREAD_FUNC_END__
#endif
#if defined(LINUX) #if defined(LINUX)
# include <sys/syscall.h> # include <sys/syscall.h>
# define gettid() syscall(SYS_gettid) # define gettid() syscall(SYS_gettid)
#endif #endif
#if defined(MAC_OS) || defined(BLACKBERRY) || defined(FREERTOS) #if defined(MAC_OS) || defined(BLACKBERRY)
# include <pthread.h> # include <pthread.h>
#endif #endif
__THREAD_FUNC_RET__ thread_function(void * t) {((PIThread*)t)->__thread_func__(); return 0;} __THREAD_FUNC_RET__ thread_function(void * t) {((PIThread*)t)->__thread_func__(); return __THREAD_FUNC_END__;}
__THREAD_FUNC_RET__ thread_function_once(void * t) {((PIThread*)t)->__thread_func_once__(); return 0;} __THREAD_FUNC_RET__ thread_function_once(void * t) {((PIThread*)t)->__thread_func_once__(); return __THREAD_FUNC_END__;}
#define REGISTER_THREAD(t) __PIThreadCollection::instance()->registerThread(t)
#define UNREGISTER_THREAD(t) __PIThreadCollection::instance()->unregisterThread(t)
#ifndef MICRO_PIP
# define REGISTER_THREAD(t) __PIThreadCollection::instance()->registerThread(t)
# define UNREGISTER_THREAD(t) __PIThreadCollection::instance()->unregisterThread(t)
#else
# define REGISTER_THREAD(t)
# define UNREGISTER_THREAD(t)
#endif
/*! \class PIThread /*! \class PIThread
* @brief Thread class * @brief Thread class
@@ -63,7 +76,7 @@ event started();
while (isRunning()) { while (isRunning()) {
run(); run();
ThreadFunc(); ThreadFunc();
msleep(timer_delay); piMSleep(timer_delay);
} }
event stopped(); event stopped();
end(); end();
@@ -90,6 +103,7 @@ end();
* *
*/ */
#ifndef MICRO_PIP
__PIThreadCollection *__PIThreadCollection::instance() { __PIThreadCollection *__PIThreadCollection::instance() {
return __PIThreadCollection_Initializer__::__instance__; return __PIThreadCollection_Initializer__::__instance__;
@@ -158,15 +172,17 @@ __PIThreadCollection_Initializer__::~__PIThreadCollection_Initializer__() {
} }
} }
#endif // MICRO_PIP
PRIVATE_DEFINITION_START(PIThread) PRIVATE_DEFINITION_START(PIThread)
#ifndef WINDOWS #if defined(WINDOWS)
void * thread;
#elif defined(FREERTOS)
TaskHandle_t thread;
#else
pthread_t thread; pthread_t thread;
sched_param sparam; sched_param sparam;
#else
void * thread;
#endif #endif
PRIVATE_DEFINITION_END(PIThread) PRIVATE_DEFINITION_END(PIThread)
@@ -267,7 +283,7 @@ void PIThread::terminate() {
terminating = running_ = false; terminating = running_ = false;
tid_ = -1; tid_ = -1;
//PICout(PICoutManipulators::DefaultControls) << "terminate" << PRIVATE->thread; //PICout(PICoutManipulators::DefaultControls) << "terminate" << PRIVATE->thread;
#ifndef WINDOWS # ifndef WINDOWS
# ifdef ANDROID # ifdef ANDROID
pthread_kill(PRIVATE->thread, SIGTERM); pthread_kill(PRIVATE->thread, SIGTERM);
# else # else
@@ -276,13 +292,13 @@ void PIThread::terminate() {
pthread_cancel(PRIVATE->thread); pthread_cancel(PRIVATE->thread);
//pthread_join(PRIVATE->thread, &ret); //pthread_join(PRIVATE->thread, &ret);
# endif # endif
#else # else
TerminateThread(PRIVATE->thread, 0); TerminateThread(PRIVATE->thread, 0);
CloseHandle(PRIVATE->thread); CloseHandle(PRIVATE->thread);
#endif # endif
PRIVATE->thread = 0; PRIVATE->thread = 0;
end(); end();
#endif #endif //FREERTOS
PIINTROSPECTION_THREAD_STOP(this); PIINTROSPECTION_THREAD_STOP(this);
//PICout(PICoutManipulators::DefaultControls) << "thread" << this << "terminate ok" << running_; //PICout(PICoutManipulators::DefaultControls) << "thread" << this << "terminate ok" << running_;
} }
@@ -290,27 +306,31 @@ void PIThread::terminate() {
int PIThread::priority2System(PIThread::Priority p) { int PIThread::priority2System(PIThread::Priority p) {
switch (p) { switch (p) {
# ifdef QNX #if defined(QNX)
case piLowerst: return 8; case piLowerst: return 8;
case piLow: return 9; case piLow: return 9;
case piNormal: return 10; case piNormal: return 10;
case piHigh: return 11; case piHigh: return 11;
case piHighest: return 12; case piHighest: return 12;
# else #elif defined(WINDOWS)
# ifdef WINDOWS
case piLowerst: return -2; case piLowerst: return -2;
case piLow: return -1; case piLow: return -1;
case piNormal: return 0; case piNormal: return 0;
case piHigh: return 1; case piHigh: return 1;
case piHighest: return 2; case piHighest: return 2;
# else #elif defined(FREERTOS)
case piLowerst: return 2;
case piLow: return 3;
case piNormal: return 4;
case piHigh: return 5;
case piHighest: return 6;
#else
case piLowerst: return 2; case piLowerst: return 2;
case piLow: return 1; case piLow: return 1;
case piNormal: return 0; case piNormal: return 0;
case piHigh: return -1; case piHigh: return -1;
case piHighest: return -2; case piHighest: return -2;
# endif #endif
# endif
default: return 0; default: return 0;
} }
return 0; return 0;
@@ -320,34 +340,44 @@ int PIThread::priority2System(PIThread::Priority p) {
bool PIThread::_startThread(void * func) { bool PIThread::_startThread(void * func) {
terminating = false; terminating = false;
running_ = true; running_ = true;
#ifndef WINDOWS #if !defined(WINDOWS) && !defined(FREERTOS)
pthread_attr_t attr; pthread_attr_t attr;
pthread_attr_init(&attr); pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
int ret = pthread_create(&PRIVATE->thread, &attr, (void*(*)(void*))func, this); int ret = pthread_create(&PRIVATE->thread, &attr, (__THREAD_FUNC_RET__(*)(void*))func, this);
//PICout(PICoutManipulators::DefaultControls) << "pthread_create" << PRIVATE->thread; //PICout(PICoutManipulators::DefaultControls) << "pthread_create" << PRIVATE->thread;
pthread_attr_destroy(&attr); pthread_attr_destroy(&attr);
if (ret == 0) { if (ret == 0) {
# ifdef MAC_OS # ifdef MAC_OS
pthread_setname_np(((PIString&)name().elided(15, 0.4f).resize(15, '\0')).dataAscii()); pthread_setname_np(((PIString&)name().elided(15, 0.4f).resize(15, PIChar('\0'))).dataAscii());
pthread_threadid_np(PRIVATE->thread, (__uint64_t*)&tid_); pthread_threadid_np(PRIVATE->thread, (__uint64_t*)&tid_);
# else # else
# ifdef FREERTOS pthread_setname_np(PRIVATE->thread, ((PIString&)name().elided(15, 0.4f).resize(15, PIChar('\0'))).dataAscii());
tid_ = PRIVATE->thread;
# else
pthread_setname_np(PRIVATE->thread, ((PIString&)name().elided(15, 0.4f).resize(15, '\0')).dataAscii());
# endif # endif
# endif #endif
#else #ifdef WINDOWS
if (PRIVATE->thread) CloseHandle(PRIVATE->thread); if (PRIVATE->thread) CloseHandle(PRIVATE->thread);
# ifdef CC_GCC # ifdef CC_GCC
PRIVATE->thread = (void *)_beginthreadex(0, 0, (unsigned(__stdcall*)(void*))func, this, 0, 0); PRIVATE->thread = (void *)_beginthreadex(0, 0, (__THREAD_FUNC_RET__(*)(void*))func, this, 0, 0);
# else # else
PRIVATE->thread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)func, this, 0, 0); PRIVATE->thread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)func, this, 0, 0);
# endif # endif
if (PRIVATE->thread != 0) { if (PRIVATE->thread != 0) {
#endif #endif
#ifdef FREERTOS
if (xTaskCreate(
(__THREAD_FUNC_RET__(*)(void*))func,
((PIString&)name().elided(15, 0.4f).resize(15, PIChar('\0'))).dataAscii(), // 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;
#endif
#ifndef FREERTOS
setPriority(priority_); setPriority(priority_);
#endif
return true; return true;
} else { } else {
running_ = false; running_ = false;
@@ -360,10 +390,12 @@ bool PIThread::_startThread(void * func) {
void PIThread::setPriority(PIThread::Priority prior) { void PIThread::setPriority(PIThread::Priority prior) {
#ifndef FREERTOS // FreeRTOS can't change priority runtime
priority_ = prior; priority_ = prior;
# ifndef WINDOWS
if (!running_ || (PRIVATE->thread == 0)) return; if (!running_ || (PRIVATE->thread == 0)) return;
#ifdef FREERTOS
vTaskPrioritySet(PRIVATE->thread, priority2System(priority_));
#else
# ifndef WINDOWS
//PICout(PICoutManipulators::DefaultControls) << "setPriority" << PRIVATE->thread; //PICout(PICoutManipulators::DefaultControls) << "setPriority" << PRIVATE->thread;
policy_ = 0; policy_ = 0;
memset(&(PRIVATE->sparam), 0, sizeof(PRIVATE->sparam)); memset(&(PRIVATE->sparam), 0, sizeof(PRIVATE->sparam));
@@ -402,7 +434,7 @@ bool PIThread::waitForFinish(int timeout_msecs) {
if (!running_) return true; if (!running_) return true;
if (timeout_msecs < 0) { if (timeout_msecs < 0) {
while (running_) { while (running_) {
msleep(PIP_MIN_MSLEEP); piMinSleep();
#ifdef WINDOWS #ifdef WINDOWS
if (!isExists(PRIVATE->thread)) { if (!isExists(PRIVATE->thread)) {
unlock(); unlock();
@@ -414,7 +446,7 @@ bool PIThread::waitForFinish(int timeout_msecs) {
} }
tmf_.reset(); tmf_.reset();
while (running_ && tmf_.elapsed_m() < timeout_msecs) { while (running_ && tmf_.elapsed_m() < timeout_msecs) {
msleep(PIP_MIN_MSLEEP); piMinSleep();
#ifdef WINDOWS #ifdef WINDOWS
if (!isExists(PRIVATE->thread)) { if (!isExists(PRIVATE->thread)) {
unlock(); unlock();
@@ -430,12 +462,12 @@ bool PIThread::waitForStart(int timeout_msecs) {
if (running_) return true; if (running_) return true;
if (timeout_msecs < 0) { if (timeout_msecs < 0) {
while (!running_) while (!running_)
msleep(PIP_MIN_MSLEEP); piMinSleep();
return true; return true;
} }
tms_.reset(); tms_.reset();
while (!running_ && tms_.elapsed_m() < timeout_msecs) while (!running_ && tms_.elapsed_m() < timeout_msecs)
msleep(PIP_MIN_MSLEEP); piMinSleep();
return tms_.elapsed_m() < timeout_msecs; return tms_.elapsed_m() < timeout_msecs;
} }
@@ -456,9 +488,9 @@ void PIThread::_beginThread() {
PIINTROSPECTION_THREAD_START(this); PIINTROSPECTION_THREAD_START(this);
REGISTER_THREAD(this); REGISTER_THREAD(this);
running_ = true; running_ = true;
if (lockRun) mutex_.lock(); if (lockRun) thread_mutex.lock();
begin(); begin();
if (lockRun) mutex_.unlock(); if (lockRun) thread_mutex.unlock();
started(); started();
} }
@@ -466,7 +498,7 @@ void PIThread::_beginThread() {
void PIThread::_runThread() { void PIThread::_runThread() {
PIINTROSPECTION_THREAD_RUN(this); PIINTROSPECTION_THREAD_RUN(this);
//PICout(PICoutManipulators::DefaultControls) << "thread" << this << "lock" << "..."; //PICout(PICoutManipulators::DefaultControls) << "thread" << this << "lock" << "...";
if (lockRun) mutex_.lock(); if (lockRun) thread_mutex.lock();
//PICout(PICoutManipulators::DefaultControls) << "thread" << this << "lock" << "ok"; //PICout(PICoutManipulators::DefaultControls) << "thread" << this << "lock" << "ok";
//PICout(PICoutManipulators::DefaultControls) << "thread" << this << "run" << "..."; //PICout(PICoutManipulators::DefaultControls) << "thread" << this << "run" << "...";
#ifdef PIP_INTROSPECTION #ifdef PIP_INTROSPECTION
@@ -482,7 +514,7 @@ void PIThread::_runThread() {
if (ret_func != 0) ret_func(data_); if (ret_func != 0) ret_func(data_);
//PICout(PICoutManipulators::DefaultControls) << "thread" << this << "ret_func" << "ok"; //PICout(PICoutManipulators::DefaultControls) << "thread" << this << "ret_func" << "ok";
//PICout(PICoutManipulators::DefaultControls) << "thread" << this << "unlock" << "..."; //PICout(PICoutManipulators::DefaultControls) << "thread" << this << "unlock" << "...";
if (lockRun) mutex_.unlock(); if (lockRun) thread_mutex.unlock();
//PICout(PICoutManipulators::DefaultControls) << "thread" << this << "unlock" << "ok"; //PICout(PICoutManipulators::DefaultControls) << "thread" << this << "unlock" << "ok";
} }
@@ -491,11 +523,11 @@ void PIThread::_endThread() {
//PICout(PICoutManipulators::DefaultControls) << "thread" << this << "stop" << "..."; //PICout(PICoutManipulators::DefaultControls) << "thread" << this << "stop" << "...";
stopped(); stopped();
//PICout(PICoutManipulators::DefaultControls) << "thread" << this << "stop" << "ok"; //PICout(PICoutManipulators::DefaultControls) << "thread" << this << "stop" << "ok";
if (lockRun) mutex_.lock(); if (lockRun) thread_mutex.lock();
//PICout(PICoutManipulators::DefaultControls) << "thread" << this << "end" << "..."; //PICout(PICoutManipulators::DefaultControls) << "thread" << this << "end" << "...";
end(); end();
//PICout(PICoutManipulators::DefaultControls) << "thread" << this << "stop" << "ok"; //PICout(PICoutManipulators::DefaultControls) << "thread" << this << "stop" << "ok";
if (lockRun) mutex_.unlock(); if (lockRun) thread_mutex.unlock();
terminating = running_ = false; terminating = running_ = false;
tid_ = -1; tid_ = -1;
//PICout(PICoutManipulators::DefaultControls) << "thread" << this << "exit"; //PICout(PICoutManipulators::DefaultControls) << "thread" << this << "exit";
@@ -503,18 +535,18 @@ void PIThread::_endThread() {
//PICout(PICoutManipulators::DefaultControls) << "pthread_exit" << (__privateinitializer__.p)->thread; //PICout(PICoutManipulators::DefaultControls) << "pthread_exit" << (__privateinitializer__.p)->thread;
UNREGISTER_THREAD(this); UNREGISTER_THREAD(this);
PIINTROSPECTION_THREAD_STOP(this); PIINTROSPECTION_THREAD_STOP(this);
#ifndef WINDOWS #if defined(WINDOWS)
pthread_detach(PRIVATE->thread);
PRIVATE->thread = 0;
#endif
#ifndef WINDOWS
pthread_exit(0);
#else
# ifdef CC_GCC # ifdef CC_GCC
_endthreadex(0); _endthreadex(0);
# else # else
ExitThread(0); ExitThread(0);
# endif # endif
#elif defined(FREERTOS)
PRIVATE->thread = 0;
#else
pthread_detach(PRIVATE->thread);
PRIVATE->thread = 0;
pthread_exit(0);
#endif #endif
} }
@@ -554,12 +586,14 @@ void PIThread::__thread_func_once__() {
void PIThread::runOnce(PIObject * object, const char * handler, const PIString & name) { void PIThread::runOnce(PIObject * object, const char * handler, const PIString & name) {
PIThread * t = new PIThread(); PIThread * t = new PIThread();
t->setName(name); t->setName(name);
if (!PIObject::piConnectU(t, PIStringAscii("started"), object, object, PIStringAscii(handler), "PIThread::runOnce")) { if (!PIObject::piConnectU(t, PIStringAscii("started"), object, object, PIStringAscii(handler), "PIThread::runOnce").isValid()) {
delete t; delete t;
return; return;
} }
#ifndef MICRO_PIP
__PIThreadCollection::instance()->startedAuto(t); __PIThreadCollection::instance()->startedAuto(t);
CONNECTU(t, stopped, __PIThreadCollection::instance(), stoppedAuto); CONNECTU(t, stopped, __PIThreadCollection::instance(), stoppedAuto);
#endif
t->startOnce(); t->startOnce();
} }
@@ -568,8 +602,10 @@ void PIThread::runOnce(std::function<void ()> func, const PIString & name) {
PIThread * t = new PIThread(); PIThread * t = new PIThread();
t->setName(name); t->setName(name);
t->setSlot(func); t->setSlot(func);
#ifndef MICRO_PIP
__PIThreadCollection::instance()->startedAuto(t); __PIThreadCollection::instance()->startedAuto(t);
CONNECTU(t, stopped, __PIThreadCollection::instance(), stoppedAuto); CONNECTU(t, stopped, __PIThreadCollection::instance(), stoppedAuto);
#endif
t->startOnce(); t->startOnce();
} }

View File

@@ -30,6 +30,8 @@
#include "piobject.h" #include "piobject.h"
class PIThread; class PIThread;
#ifndef MICRO_PIP
class PIIntrospectionThreads; class PIIntrospectionThreads;
class PIP_EXPORT __PIThreadCollection: public PIObject { class PIP_EXPORT __PIThreadCollection: public PIObject {
@@ -58,14 +60,16 @@ public:
}; };
static __PIThreadCollection_Initializer__ __PIThreadCollection_initializer__; static __PIThreadCollection_Initializer__ __PIThreadCollection_initializer__;
#endif // MICRO_PIP
typedef std::function<void(void *)> ThreadFunc; typedef std::function<void(void *)> ThreadFunc;
class PIP_EXPORT PIThread: public PIObject class PIP_EXPORT PIThread: public PIObject
{ {
PIOBJECT_SUBCLASS(PIThread, PIObject) PIOBJECT_SUBCLASS(PIThread, PIObject)
#ifndef MICRO_PIP
friend class PIIntrospectionThreads; friend class PIIntrospectionThreads;
#endif
public: public:
NO_COPY_CLASS(PIThread) NO_COPY_CLASS(PIThread)
@@ -131,11 +135,15 @@ public:
//! @brief Set necessity of lock every \a run with internal mutex //! @brief Set necessity of lock every \a run with internal mutex
void needLockRun(bool need) {lockRun = need;} void needLockRun(bool need) {lockRun = need;}
EVENT_HANDLER0(void, lock) {mutex_.lock();}
EVENT_HANDLER0(void, unlock) {mutex_.unlock();} //! @brief Lock internal mutex
EVENT_HANDLER0(void, lock) const {thread_mutex.lock();}
//! @brief Unlock internal mutex
EVENT_HANDLER0(void, unlock) const {thread_mutex.unlock();}
//! @brief Returns internal mutex //! @brief Returns internal mutex
PIMutex & mutex() {return mutex_;} PIMutex & mutex() const {return thread_mutex;}
//! @brief Returns thread ID //! @brief Returns thread ID
llong tid() const {return tid_;} llong tid() const {return tid_;}
@@ -239,7 +247,7 @@ protected:
int delay_, policy_; int delay_, policy_;
llong tid_; llong tid_;
void * data_; void * data_;
mutable PIMutex mutex_; mutable PIMutex thread_mutex;
PITimeMeasurer tmf_, tms_, tmr_; PITimeMeasurer tmf_, tms_, tmr_;
PIThread::Priority priority_; PIThread::Priority priority_;
ThreadFunc ret_func; ThreadFunc ret_func;

View File

@@ -26,7 +26,9 @@
#include "pitimer.h" #include "pitimer.h"
#include "pipipelinethread.h" #include "pipipelinethread.h"
#include "pigrabberbase.h" #include "pigrabberbase.h"
#include "pithreadpoolexecutor.h"
#include "piconditionvar.h" #include "piconditionvar.h"
#include "pithreadpoolexecutor.h"
#include "pithreadpoolloop.h"
#include "pithreadnotifier.h"
#endif // PITHREADMODULE_H #endif // PITHREADMODULE_H

View File

@@ -0,0 +1,39 @@
/*
PIP - Platform Independent Primitives
Class for simply notify and wait in different threads
Andrey Bychkov work.a.b@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
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "pithreadnotifier.h"
PIThreadNotifier::PIThreadNotifier() : cnt(0) {}
void PIThreadNotifier::wait() {
m.lock();
while (cnt == 0) v.wait(m);
cnt--;
m.unlock();
}
void PIThreadNotifier::notifyOnce() {
m.lock();
cnt++;
v.notifyAll();
m.unlock();
}

View File

@@ -0,0 +1,52 @@
/*! @file pithreadnotifier.h
* @brief Class for simply notify and wait in different threads
*/
/*
PIP - Platform Independent Primitives
Class for simply notify and wait in different threads
Andrey Bychkov work.a.b@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
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PITHREADNOTIFIER_H
#define PITHREADNOTIFIER_H
#include "piconditionvar.h"
class PIP_EXPORT PIThreadNotifier {
public:
PIThreadNotifier();
//! Start waiting, return if other thread call \a notifyOnce().
//! If \a notifyOnce() has been called before, then returns immediately.
//! If notifyOnce() has been called "n" times, then returns immediately "n" times,
//! but only if wait in one thread.
//! If many threads waiting, then If notifyOnce() has been called "n" times,
//! All threads total returns "n" times in random sequence.
void wait();
//! Notify one waiting thread, wich waiting on \a wait() function.
//! If many threads waiting, then notify randomly one.
//! If call this "n" times, then notify any waiting threads totally "n" times.
void notifyOnce();
private:
ullong cnt;
PIMutex m;
PIConditionVariable v;
};
#endif // PITHREADNOTIFIER_H

View File

@@ -0,0 +1,130 @@
/*
PIP - Platform Independent Primitives
Thread pool loop
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
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "pithreadpoolloop.h"
#include "pisysteminfo.h"
#include "pithread.h"
/*! \class PIThreadPoolLoop
* @brief Thread class
* \details This class allow you parallelize loop.
*
* \section PIThreadPoolLoop_sec0 Usage
* This class designed to replace "for(;;)" statement in very simple way.
* In constructor several threads created, then by "setFunction()" method
* you should pass body of your loop, and then call "start()" or "exec()".
* Every thread take loop counter and execute your function until all
* counter range is passed.
*
* Example:
\code{.cpp}
PIVector<int> data(10, [](int i)->int{return i;});
piCout << data; // {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
PIThreadPoolLoop pool;
pool.exec(0, data.size(), [&](int i){ // parallel analogue "for (int i = 0; i < data.size(); i++)"
data[i] = data[i] + 10;
});
piCout << data; // {10, 11, 12, 13, 14, 15, 16, 17, 18, 19}
\endcode
*
* Equivalent to:
\code{.cpp}
PIVector<int> data(10, [](int i)->int{return i;});
piCout << data; // {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
pool.setFunction([&](int i){
data[i] = data[i] + 10;
});
pool.exec(0, data.size());
piCout << data; // {10, 11, 12, 13, 14, 15, 16, 17, 18, 19}
\endcode
*
* \section PIThreadPoolLoop_sec1 Important
* Due to multithreading it`s very important to protect output data of loop body, use mutex.
* Also remember that execution order is undefined and you shouldn`t use global variables in
* your function. Use local variables and lambda capture.
*
*/
PIThreadPoolLoop::PIThreadPoolLoop(int thread_cnt) {
if (thread_cnt <= 0)
thread_cnt = piMaxi(1, PISystemInfo::instance()->processorsCount);
piForTimes (thread_cnt) {
auto * t = new PIThread();
threads << t;
}
//piCout << "PIThreadPoolLoop" << proc_cnt << "threads";
}
PIThreadPoolLoop::~PIThreadPoolLoop() {
for (auto * t: threads) {
t->stop(false);
if (!t->waitForFinish(100))
t->terminate();
delete t;
}
}
void PIThreadPoolLoop::setFunction(std::function<void (int)> f) {
func = f;
}
void PIThreadPoolLoop::start(int index_start, int index_count) {
counter = index_start;
int end = index_start + index_count;
for (auto * t: threads)
t->start([this,end,t](){
while (1) {
int cc = counter.fetch_add(1);
if (cc >= end) {
t->stop(false);
return;
}
func(cc);
}
});
}
void PIThreadPoolLoop::exec(int index_start, int index_count) {
start(index_start, index_count);
wait();
}
void PIThreadPoolLoop::exec(int index_start, int index_count, std::function<void (int)> f) {
setFunction(f);
exec(index_start, index_count);
}
void PIThreadPoolLoop::wait() {
for (auto * t: threads)
t->waitForFinish();
}

View File

@@ -0,0 +1,69 @@
/*! @file pithreadpoolloop.h
* @brief Thread pool loop
*
* This file declare thread class and some wait functions
*/
/*
PIP - Platform Independent Primitives
Thread pool loop
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
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PITHREADPOOLLOOP_H
#define PITHREADPOOLLOOP_H
#include "pivector.h"
class PIThread;
class PIP_EXPORT PIThreadPoolLoop {
public:
//! Contructs thread pool with threads count "thread_cnt".
//! If "thread_cnt" = -1 then system processors count used
PIThreadPoolLoop(int thread_cnt = -1);
virtual ~PIThreadPoolLoop();
//! Set threads function to "f" with format [](int){...}
void setFunction(std::function<void(int)> f);
//! Wait for all threads stop
void wait();
//! Start functions execution with integer argument range
//! from "index_start" to "index_start + index_count - 1"
void start(int index_start, int index_count);
//! Start functions execution with integer argument range
//! from "index_start" to "index_start + index_count - 1"
//! and wait for finish
void exec(int index_start, int index_count);
//! Start functions "f" execution with integer argument range
//! from "index_start" to "index_start + index_count - 1"
//! and wait for finish
void exec(int index_start, int index_count, std::function<void(int)> f);
private:
PIVector<PIThread * > threads;
std::function<void(int)> func;
std::atomic_int counter;
};
#endif

View File

@@ -648,11 +648,11 @@ bool PITimer::stop(bool wait) {
bool PITimer::waitForFinish(int timeout_msecs) { bool PITimer::waitForFinish(int timeout_msecs) {
if (timeout_msecs < 0) { if (timeout_msecs < 0) {
while (isRunning()) while (isRunning())
msleep(PIP_MIN_MSLEEP); piMinSleep();
return true; return true;
} }
PITimeMeasurer tm; PITimeMeasurer tm;
while (isRunning() && tm.elapsed_m() < timeout_msecs) while (isRunning() && tm.elapsed_m() < timeout_msecs)
msleep(PIP_MIN_MSLEEP); piMinSleep();
return tm.elapsed_m() < timeout_msecs; return tm.elapsed_m() < timeout_msecs;
} }

View File

@@ -2,63 +2,30 @@
int main(int argc, char * argv[]) { int main(int argc, char * argv[]) {
PICLI cli(argc, argv); PIThreadNotifier n;
PITimer tm; int cnt1 = 0;
cli.addArgument("connect", true); int cnt2 = 0;
cli.addArgument("name", true); int cnt3 = 0;
PICloudClient c("127.0.0.1:10101"); PIThread t1([&n, &cnt1](){n.wait(); cnt1++; piMSleep(1);}, true);
// c.setReopenEnabled(true); PIThread t2([&n, &cnt2](){n.wait(); cnt2++; piMSleep(2);}, true);
PICloudServer s("127.0.0.1:10101"); piCout << "created";
PIVector<PICloudServer::Client *> clients; piMSleep(10);
CONNECTL(&tm, tickEvent, ([&](void *, int){ piCout << "unlock" << cnt1 << cnt2 << cnt3;
if (c.isConnected()) { n.notifyOnce(); cnt3++;
PIString str = "ping"; piMSleep(10);
piCout << "[Client] send:" << str; piCout << "unlock" << cnt1 << cnt2 << cnt3;
c.write(str.toByteArray()); n.notifyOnce(); cnt3++;
} piMSleep(10);
if (s.isRunning()) { piCout << "run" << cnt1 << cnt2 << cnt3;
for (auto cl : clients) { PIThread t3([&n, &cnt3](){n.notifyOnce(); cnt3++; piMSleep(1);}, true);
if (cl->isOpened()) { piMSleep(20);
PIString str = "ping_S"; t3.stop();
piCout << "[Server] send to" << cl << ":" << str; piMSleep(100);
cl->write(str.toByteArray()); piCout << "exit" << cnt1 << cnt2 << cnt3;
} PIByteArray ba = PIByteArray::fromHex("00aabbcc");
} PIByteArray ba2 = ba.getRange(1, 2);
} piCout << ba2.toHex();
})); // m.unlock();
CONNECTL(&c, threadedReadEvent, ([&](uchar * readed, int size){ // piMSleep(10);
PIByteArray ba(readed, size);
PIString str = PIString(ba);
piCout << "[Client] data:" << str;
if (str == "ping_S") c.write(PIString("pong_S").toByteArray());
}));
CONNECTL(&s, newConnection, ([&](PICloudServer::Client * cl){
piCout << "[Server] new client:" << cl;
clients << cl;
CONNECTL(cl, threadedReadEvent, ([&c, &s, cl](uchar * readed, int size){
PIByteArray ba(readed, size);
PIString str = PIString(ba);
piCout << "[Server] data from" << cl << ":" << str;
if (str == "ping") cl->write(PIString("pong").toByteArray());
}));
CONNECTL(cl, closed, ([&clients, cl](){
cl->stop();
clients.removeAll(cl);
cl->deleteLater();
}));
cl->startThreadedRead();
}));
if (cli.hasArgument("name")) s.setServerName(cli.argumentValue("name"));
if (cli.hasArgument("connect")) {
c.setServerName(cli.argumentValue("connect"));
c.startThreadedRead();
} else {
s.startThreadedRead();
}
tm.start(1000);
PIKbdListener ls;
ls.enableExitCapture(PIKbdListener::F10);
ls.start();
WAIT_FOR_EXIT
return 0; return 0;
} }

Some files were not shown because too many files have changed in this diff Show More