merged concurrent to main library
removed PIConditionLock, use PIMutex instead
This commit is contained in:
@@ -66,7 +66,6 @@ set(PIP_SRC_USB "lib/usb")
|
|||||||
set(PIP_SRC_FFTW "lib/fftw")
|
set(PIP_SRC_FFTW "lib/fftw")
|
||||||
set(PIP_SRC_OPENCL "lib/opencl")
|
set(PIP_SRC_OPENCL "lib/opencl")
|
||||||
set(PIP_SRC_IO_UTILS "lib/io_utils")
|
set(PIP_SRC_IO_UTILS "lib/io_utils")
|
||||||
set(PIP_SRC_CONCURRENT "lib/concurrent")
|
|
||||||
set(PIP_SRC_CLOUD "lib/cloud")
|
set(PIP_SRC_CLOUD "lib/cloud")
|
||||||
set(PIP_SRC_LUA "lib/lua")
|
set(PIP_SRC_LUA "lib/lua")
|
||||||
set(PIP_SRC_DIRS ${PIP_SRC_MAIN}
|
set(PIP_SRC_DIRS ${PIP_SRC_MAIN}
|
||||||
@@ -77,8 +76,8 @@ set(PIP_SRC_DIRS ${PIP_SRC_MAIN}
|
|||||||
${PIP_SRC_FFTW}
|
${PIP_SRC_FFTW}
|
||||||
${PIP_SRC_OPENCL}
|
${PIP_SRC_OPENCL}
|
||||||
${PIP_SRC_IO_UTILS}
|
${PIP_SRC_IO_UTILS}
|
||||||
${PIP_SRC_CONCURRENT}
|
|
||||||
${PIP_SRC_CLOUD}
|
${PIP_SRC_CLOUD}
|
||||||
|
${PIP_SRC_LUA}
|
||||||
)
|
)
|
||||||
set(PIP_LIBS_TARGETS pip)
|
set(PIP_LIBS_TARGETS pip)
|
||||||
set(LIBS_MAIN)
|
set(LIBS_MAIN)
|
||||||
@@ -192,7 +191,7 @@ get_filename_component(C_COMPILER "${CMAKE_C_COMPILER}" NAME)
|
|||||||
# Sources
|
# Sources
|
||||||
|
|
||||||
# Main lib
|
# Main lib
|
||||||
set(PIP_FOLDERS "." "core" "containers" "thread" "system" "io_devices" "io_utils" "console" "math" "code" "geo" "resources" "opencl" "crypt" "introspection" "concurrent" "cloud" "lua")
|
set(PIP_FOLDERS "." "core" "containers" "thread" "system" "io_devices" "io_utils" "console" "math" "code" "geo" "resources" "opencl" "crypt" "introspection" "cloud" "lua")
|
||||||
include_directories("${PIP_SRC_MAIN}")
|
include_directories("${PIP_SRC_MAIN}")
|
||||||
set(PIP_MAIN_FOLDERS)
|
set(PIP_MAIN_FOLDERS)
|
||||||
foreach(F ${PIP_FOLDERS})
|
foreach(F ${PIP_FOLDERS})
|
||||||
@@ -221,17 +220,17 @@ gather_src("${PIP_SRC_OPENCL}" CPP_LIB_OPENCL HDRS PHDRS)
|
|||||||
# IO Utils lib
|
# IO Utils lib
|
||||||
gather_src("${PIP_SRC_IO_UTILS}" CPP_LIB_IO_UTILS HDRS PHDRS)
|
gather_src("${PIP_SRC_IO_UTILS}" CPP_LIB_IO_UTILS HDRS PHDRS)
|
||||||
|
|
||||||
# Concurrent lib
|
|
||||||
gather_src("${PIP_SRC_CONCURRENT}" CPP_LIB_CONCURRENT HDRS PHDRS)
|
|
||||||
|
|
||||||
gather_src("${PIP_CONCURRENT_TEST}" CPP_CONCURRENT_TEST HDRS PHDRS)
|
|
||||||
|
|
||||||
# Cloud lib
|
# Cloud lib
|
||||||
gather_src("${PIP_SRC_CLOUD}" CPP_LIB_CLOUD HDRS PHDRS)
|
gather_src("${PIP_SRC_CLOUD}" CPP_LIB_CLOUD HDRS PHDRS)
|
||||||
|
|
||||||
# LUA lib
|
# LUA lib
|
||||||
gather_src("${PIP_SRC_LUA}" CPP_LIB_LUA HDRS PHDRS)
|
gather_src("${PIP_SRC_LUA}" CPP_LIB_LUA HDRS PHDRS)
|
||||||
|
|
||||||
|
if (TESTS)
|
||||||
|
# Concurrent lib tests
|
||||||
|
gather_src("${PIP_CONCURRENT_TEST}" CPP_CONCURRENT_TEST HDRS PHDRS)
|
||||||
|
endif()
|
||||||
|
|
||||||
if(PIP_FREERTOS)
|
if(PIP_FREERTOS)
|
||||||
add_definitions(-DPIP_FREERTOS)
|
add_definitions(-DPIP_FREERTOS)
|
||||||
set(ICU OFF)
|
set(ICU OFF)
|
||||||
@@ -580,24 +579,10 @@ if (NOT CROSSTOOLS)
|
|||||||
list(APPEND PIP_LIBS_TARGETS pip_io_utils)
|
list(APPEND PIP_LIBS_TARGETS pip_io_utils)
|
||||||
|
|
||||||
|
|
||||||
# Concurrent module
|
|
||||||
set(CONCURRENT_LIBS pip)
|
|
||||||
import_version(pip_concurrent pip)
|
|
||||||
set_deploy_property(pip_concurrent ${PIP_LIB_TYPE}
|
|
||||||
LABEL "PIP concurrent support"
|
|
||||||
FULLNAME "${_PIP_DOMAIN}.pip_concurrent"
|
|
||||||
COMPANY "${_PIP_COMPANY}"
|
|
||||||
INFO "Platform-Independent Primitives")
|
|
||||||
make_rc(pip_concurrent _RC)
|
|
||||||
add_library(pip_concurrent ${PIP_LIB_TYPE} ${CPP_LIB_CONCURRENT} ${_RC})
|
|
||||||
target_link_libraries(pip_concurrent ${CONCURRENT_LIBS})
|
|
||||||
set_property(TARGET pip_concurrent PROPERTY CXX_STANDARD 11)
|
|
||||||
list(APPEND PIP_LIBS_TARGETS pip_concurrent)
|
|
||||||
|
|
||||||
# Enable build tests for concurrent module
|
# Enable build tests for concurrent module
|
||||||
if(PIP_CONCURRENT_TEST)
|
if(PIP_CONCURRENT_TEST)
|
||||||
add_executable(pip_concurrent_test ${CPP_CONCURRENT_TEST})
|
add_executable(pip_concurrent_test ${CPP_CONCURRENT_TEST})
|
||||||
target_link_libraries(pip_concurrent_test gtest_main gmock_main pip_concurrent)
|
target_link_libraries(pip_concurrent_test pip gtest_main gmock_main)
|
||||||
add_test(NAME pip_concurrent_test COMMAND tests)
|
add_test(NAME pip_concurrent_test COMMAND tests)
|
||||||
add_custom_target(pip_concurrent_test_perform ALL COMMAND pip_concurrent_test)
|
add_custom_target(pip_concurrent_test_perform ALL COMMAND pip_concurrent_test)
|
||||||
endif()
|
endif()
|
||||||
@@ -813,7 +798,6 @@ message(" Compress : ${PIP_COMPRESS}")
|
|||||||
message(" FFTW : ${PIP_FFTW}")
|
message(" FFTW : ${PIP_FFTW}")
|
||||||
message(" OpenCL : ${PIP_OPENCL}")
|
message(" OpenCL : ${PIP_OPENCL}")
|
||||||
message(" IOUtils : ${PIP_IOUTILS}")
|
message(" IOUtils : ${PIP_IOUTILS}")
|
||||||
message(" Concurrent: yes")
|
|
||||||
message(" Cloud : ${PIP_CLOUD}")
|
message(" Cloud : ${PIP_CLOUD}")
|
||||||
message(" Lua : ${PIP_LUA}")
|
message(" Lua : ${PIP_LUA}")
|
||||||
message("")
|
message("")
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ Also create imported targets:
|
|||||||
* PIP::FFTW
|
* PIP::FFTW
|
||||||
* PIP::OpenCL
|
* PIP::OpenCL
|
||||||
* PIP::IOUtils
|
* PIP::IOUtils
|
||||||
* PIP::Concurrent
|
|
||||||
* PIP::Cloud
|
* PIP::Cloud
|
||||||
* PIP::Lua
|
* PIP::Lua
|
||||||
|
|
||||||
@@ -67,7 +66,6 @@ find_library(PIP_FFTW_LIBRARY pip_fftw${_pip_suffix} HINTS ${_PIP_LIBDIR})
|
|||||||
find_library(PIP_COMPRESS_LIBRARY pip_compress${_pip_suffix} HINTS ${_PIP_LIBDIR})
|
find_library(PIP_COMPRESS_LIBRARY pip_compress${_pip_suffix} HINTS ${_PIP_LIBDIR})
|
||||||
find_library(PIP_OPENCL_LIBRARY pip_opencl${_pip_suffix} HINTS ${_PIP_LIBDIR})
|
find_library(PIP_OPENCL_LIBRARY pip_opencl${_pip_suffix} HINTS ${_PIP_LIBDIR})
|
||||||
find_library(PIP_IO_UTILS_LIBRARY pip_io_utils${_pip_suffix} HINTS ${_PIP_LIBDIR})
|
find_library(PIP_IO_UTILS_LIBRARY pip_io_utils${_pip_suffix} HINTS ${_PIP_LIBDIR})
|
||||||
find_library(PIP_CONCURRENT_LIBRARY pip_concurrent${_pip_suffix} HINTS ${_PIP_LIBDIR})
|
|
||||||
find_library(PIP_CLOUD_LIBRARY pip_cloud HINTS${_pip_suffix} ${_PIP_LIBDIR})
|
find_library(PIP_CLOUD_LIBRARY pip_cloud HINTS${_pip_suffix} ${_PIP_LIBDIR})
|
||||||
find_library(PIP_LUA_LIBRARY pip_lua HINTS${_pip_suffix} ${_PIP_LIBDIR})
|
find_library(PIP_LUA_LIBRARY pip_lua HINTS${_pip_suffix} ${_PIP_LIBDIR})
|
||||||
find_file(PIP_H_INCLUDE "pip.h" HINTS ${_PIP_INCDIR} $ENV{SMSDK_DIR}/include/pip)
|
find_file(PIP_H_INCLUDE "pip.h" HINTS ${_PIP_INCDIR} $ENV{SMSDK_DIR}/include/pip)
|
||||||
@@ -134,15 +132,14 @@ if(PIP_FIND_VERSION VERSION_GREATER PIP_VERSION)
|
|||||||
message(FATAL_ERROR "PIP version ${PIP_VERSION} is available, but ${PIP_FIND_VERSION} requested!")
|
message(FATAL_ERROR "PIP version ${PIP_VERSION} is available, but ${PIP_FIND_VERSION} requested!")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(__modules "USB;Crypt;Console;FFTW;Compress;IOUtils;Concurrent;Cloud;Lua")
|
set(__modules "USB;Crypt;Console;FFTW;Compress;IOUtils;Cloud;Lua")
|
||||||
set(__module_USB "${PIP_USB_LIBRARY}" )
|
set(__module_USB "${PIP_USB_LIBRARY}" )
|
||||||
set(__module_Console "${PIP_CONSOLE_LIBRARY}" )
|
set(__module_Console "${PIP_CONSOLE_LIBRARY}" )
|
||||||
set(__module_Crypt "${PIP_CRYPT_LIBRARY}" )
|
set(__module_Crypt "${PIP_CRYPT_LIBRARY}" )
|
||||||
set(__module_FFTW "${PIP_FFTW_LIBRARY}" )
|
set(__module_FFTW "${PIP_FFTW_LIBRARY}" )
|
||||||
set(__module_Compress "${PIP_COMPRESS_LIBRARY}" )
|
set(__module_Compress "${PIP_COMPRESS_LIBRARY}" )
|
||||||
set(__module_OpenCL "${PIP_OPENCL_LIBRARY}" )
|
set(__module_OpenCL "${PIP_OPENCL_LIBRARY}" )
|
||||||
set(__module_IOUtils "${PIP_IO_UTILS_LIBRARY}" )
|
set(__module_IOUtils "${PIP_IO_UTILS_LIBRARY}" )
|
||||||
set(__module_Concurrent "${PIP_CONCURRENT_LIBRARY}")
|
|
||||||
set(__module_Cloud "${PIP_CLOUD_LIBRARY}" )
|
set(__module_Cloud "${PIP_CLOUD_LIBRARY}" )
|
||||||
set(__module_Lua "${PIP_LUA_LIBRARY}" )
|
set(__module_Lua "${PIP_LUA_LIBRARY}" )
|
||||||
if((NOT TARGET PIP) AND PIP_LIBRARY)
|
if((NOT TARGET PIP) AND PIP_LIBRARY)
|
||||||
|
|||||||
@@ -1,95 +0,0 @@
|
|||||||
/*
|
|
||||||
PIP - Platform Independent Primitives
|
|
||||||
|
|
||||||
Stephan Fomenko
|
|
||||||
|
|
||||||
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 "piconditionlock.h"
|
|
||||||
#ifdef WINDOWS
|
|
||||||
# include <synchapi.h>
|
|
||||||
#else
|
|
||||||
# include <pthread.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
PRIVATE_DEFINITION_START(PIConditionLock)
|
|
||||||
#ifdef WINDOWS
|
|
||||||
CRITICAL_SECTION
|
|
||||||
#else
|
|
||||||
pthread_mutex_t
|
|
||||||
#endif
|
|
||||||
nativeHandle;
|
|
||||||
PRIVATE_DEFINITION_END(PIConditionLock)
|
|
||||||
|
|
||||||
|
|
||||||
PIConditionLock::PIConditionLock() {
|
|
||||||
#ifdef WINDOWS
|
|
||||||
InitializeCriticalSection(&PRIVATE->nativeHandle);
|
|
||||||
#else
|
|
||||||
pthread_mutexattr_t attr;
|
|
||||||
memset(&attr, 0, sizeof(attr));
|
|
||||||
pthread_mutexattr_init(&attr);
|
|
||||||
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
|
|
||||||
memset(&(PRIVATE->nativeHandle), 0, sizeof(PRIVATE->nativeHandle));
|
|
||||||
pthread_mutex_init(&(PRIVATE->nativeHandle), &attr);
|
|
||||||
pthread_mutexattr_destroy(&attr);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
PIConditionLock::~PIConditionLock() {
|
|
||||||
#ifdef WINDOWS
|
|
||||||
DeleteCriticalSection(&PRIVATE->nativeHandle);
|
|
||||||
#else
|
|
||||||
pthread_mutex_destroy(&(PRIVATE->nativeHandle));
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void PIConditionLock::lock() {
|
|
||||||
#ifdef WINDOWS
|
|
||||||
EnterCriticalSection(&PRIVATE->nativeHandle);
|
|
||||||
#else
|
|
||||||
pthread_mutex_lock(&(PRIVATE->nativeHandle));
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void PIConditionLock::unlock() {
|
|
||||||
#ifdef WINDOWS
|
|
||||||
LeaveCriticalSection(&PRIVATE->nativeHandle);
|
|
||||||
#else
|
|
||||||
pthread_mutex_unlock(&(PRIVATE->nativeHandle));
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void *PIConditionLock::handle() {
|
|
||||||
#ifdef WINDOWS
|
|
||||||
return &PRIVATE->nativeHandle;
|
|
||||||
#else
|
|
||||||
return &PRIVATE->nativeHandle;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool PIConditionLock::tryLock() {
|
|
||||||
#ifdef WINDOWS
|
|
||||||
return TryEnterCriticalSection(&PRIVATE->nativeHandle) != 0;
|
|
||||||
#else
|
|
||||||
return (pthread_mutex_trylock(&(PRIVATE->nativeHandle)) == 0);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
@@ -8,24 +8,24 @@ public:
|
|||||||
bool isTrueCondition = false;
|
bool isTrueCondition = false;
|
||||||
int timeout = -1;
|
int timeout = -1;
|
||||||
|
|
||||||
void wait(PIConditionLock& lk) override {
|
void wait(PIMutex& lk) override {
|
||||||
isWaitCalled = true;
|
isWaitCalled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void wait(PIConditionLock& lk, const std::function<bool()>& condition) override {
|
void wait(PIMutex& lk, const std::function<bool()>& condition) override {
|
||||||
isWaitCalled = true;
|
isWaitCalled = true;
|
||||||
lk.lock();
|
lk.lock();
|
||||||
isTrueCondition = condition();
|
isTrueCondition = condition();
|
||||||
lk.unlock();
|
lk.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool waitFor(PIConditionLock& lk, int timeoutMs) override {
|
bool waitFor(PIMutex& lk, int timeoutMs) override {
|
||||||
isWaitForCalled = true;
|
isWaitForCalled = true;
|
||||||
timeout = timeoutMs;
|
timeout = timeoutMs;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool waitFor(PIConditionLock& lk, int timeoutMs, const std::function<bool()>& condition) override {
|
bool waitFor(PIMutex& lk, int timeoutMs, const std::function<bool()>& condition) override {
|
||||||
isWaitForCalled = true;
|
isWaitForCalled = true;
|
||||||
lk.lock();
|
lk.lock();
|
||||||
isTrueCondition = condition();
|
isTrueCondition = condition();
|
||||||
|
|||||||
@@ -2,12 +2,12 @@
|
|||||||
#include "gmock/gmock.h"
|
#include "gmock/gmock.h"
|
||||||
|
|
||||||
#include "piconditionvar.h"
|
#include "piconditionvar.h"
|
||||||
#include <pithread.h>
|
#include "pithread.h"
|
||||||
#include "testutil.h"
|
#include "testutil.h"
|
||||||
|
|
||||||
class ConditionLock : public ::testing::Test, public TestUtil {
|
class ConditionLock : public ::testing::Test, public TestUtil {
|
||||||
public:
|
public:
|
||||||
PIConditionLock* m = new PIConditionLock();
|
PIMutex* m = new PIMutex();
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST_F(ConditionLock, lock_is_protect) {
|
TEST_F(ConditionLock, lock_is_protect) {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
class ConditionVariable : public ::testing::Test, public TestUtil {
|
class ConditionVariable : public ::testing::Test, public TestUtil {
|
||||||
public:
|
public:
|
||||||
PIConditionLock m;
|
PIMutex m;
|
||||||
PIConditionVariable* variable;
|
PIConditionVariable* variable;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
#include "executor.h"
|
#include "pithreadpoolexecutor.h"
|
||||||
#include "pimutex.h"
|
#include "pimutex.h"
|
||||||
|
|
||||||
const int WAIT_THREAD_TIME_MS = 30;
|
const int WAIT_THREAD_TIME_MS = 30;
|
||||||
|
|||||||
@@ -1,1168 +0,0 @@
|
|||||||
/*
|
|
||||||
PIP - Platform Independent Primitives
|
|
||||||
Console output/input
|
|
||||||
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 "piconsole.h"
|
|
||||||
#include "piincludes_p.h"
|
|
||||||
#include "pipeer.h"
|
|
||||||
#include "pidiagnostics.h"
|
|
||||||
#include "pisystemmonitor.h"
|
|
||||||
#ifndef WINDOWS
|
|
||||||
# include <sys/ioctl.h>
|
|
||||||
# include <fcntl.h>
|
|
||||||
# include <termios.h>
|
|
||||||
#else
|
|
||||||
# include <wincon.h>
|
|
||||||
# define COMMON_LVB_UNDERSCORE 0x8000
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/** \class PIConsole
|
|
||||||
* \brief Console output class
|
|
||||||
* \details
|
|
||||||
* \section PIConsole_sec0 Synopsis
|
|
||||||
* This class provides output to console with automatic alignment and update.
|
|
||||||
* It supports tabs, keyboard listening, formats and colors.
|
|
||||||
*
|
|
||||||
* \section PIConsole_sec1 Layout
|
|
||||||
* %PIConsole works with variable pointers. You should add your variables with
|
|
||||||
* functions \a addVariable() which receives label name, pointer to variable
|
|
||||||
* and optional column and format. Columns count is dynamically increased if
|
|
||||||
* new column used. E.g. if you add variable to empty tab to column 3, columns
|
|
||||||
* count will be increased to 3, but two firsts columns will be empty. Each column
|
|
||||||
* filled from top to bottom, but you can add just string with function
|
|
||||||
* \a addString() or add empty line with function \a addEmptyLine(). Layout scheme:
|
|
||||||
* \image html piconsole_layout.png
|
|
||||||
*
|
|
||||||
* \section PIConsole_sec2 Keyboard usage
|
|
||||||
* %PIConsole should to be single in application. %PIConsole aggregate PIKbdListener
|
|
||||||
* which grab keyboard and automatic switch tabs by theirs bind keys. If there is no
|
|
||||||
* tab binded to pressed key external function "slot" will be called
|
|
||||||
*
|
|
||||||
**/
|
|
||||||
|
|
||||||
|
|
||||||
PRIVATE_DEFINITION_START(PIConsole)
|
|
||||||
#ifdef WINDOWS
|
|
||||||
void getWinCurCoord() {GetConsoleScreenBufferInfo(hOut, &csbi); ccoord = csbi.dwCursorPosition;}
|
|
||||||
COORD & getWinCoord(int dx = 0, int dy = 0) {getWinCurCoord(); ccoord.X += dx; ccoord.Y += dy; return ccoord;}
|
|
||||||
void * hOut;
|
|
||||||
CONSOLE_SCREEN_BUFFER_INFO sbi, csbi;
|
|
||||||
CONSOLE_CURSOR_INFO curinfo;
|
|
||||||
COORD ccoord, ulcoord;
|
|
||||||
WORD dattr;
|
|
||||||
DWORD smode, written;
|
|
||||||
#endif
|
|
||||||
PRIVATE_DEFINITION_END(PIConsole)
|
|
||||||
|
|
||||||
|
|
||||||
PIConsole::PIConsole(bool startNow, PIKbdListener::KBFunc slot): PIThread() {
|
|
||||||
setName("console");
|
|
||||||
setPriority(piLow);
|
|
||||||
needLockRun(true);
|
|
||||||
ret_func = slot;
|
|
||||||
num_format = systime_format = 0;
|
|
||||||
vid = 0;
|
|
||||||
cur_tab = width = height = pwidth = pheight = max_y = 0;
|
|
||||||
def_align = Nothing;
|
|
||||||
tabs.reserve(16);
|
|
||||||
#ifdef WINDOWS
|
|
||||||
PRIVATE->ulcoord.X = 0;
|
|
||||||
PRIVATE->hOut = GetStdHandle(STD_OUTPUT_HANDLE);
|
|
||||||
GetConsoleScreenBufferInfo(PRIVATE->hOut, &PRIVATE->sbi);
|
|
||||||
PRIVATE->dattr = PRIVATE->sbi.wAttributes;
|
|
||||||
width = PRIVATE->sbi.srWindow.Right - PRIVATE->sbi.srWindow.Left;
|
|
||||||
height = PRIVATE->sbi.srWindow.Bottom - PRIVATE->sbi.srWindow.Top;
|
|
||||||
PRIVATE->ulcoord.Y = PRIVATE->sbi.srWindow.Top;
|
|
||||||
GetConsoleMode(PRIVATE->hOut, &PRIVATE->smode);
|
|
||||||
GetConsoleCursorInfo(PRIVATE->hOut, &PRIVATE->curinfo);
|
|
||||||
#else
|
|
||||||
# ifdef FREERTOS
|
|
||||||
width = 80;
|
|
||||||
height = 24;
|
|
||||||
# else
|
|
||||||
winsize ws;
|
|
||||||
ioctl(0, TIOCGWINSZ, &ws);
|
|
||||||
width = ws.ws_col;
|
|
||||||
height = ws.ws_row;
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
addTab("main");
|
|
||||||
listener = new PIKbdListener(key_event, this);
|
|
||||||
peer_timer = new PITimer();
|
|
||||||
peer_timer->setName("__S__.PIConsole.peer_timer");
|
|
||||||
peer = 0;
|
|
||||||
server_mode = pause_ = false;
|
|
||||||
state = Disconnected;
|
|
||||||
peer_timer->addDelimiter(20);
|
|
||||||
peer_timer->setName("__S__PIConsole::peer_timer");
|
|
||||||
CONNECT2(void, void * , int, peer_timer, tickEvent, this, peerTimer);
|
|
||||||
if (startNow) start();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
PIConsole::~PIConsole() {
|
|
||||||
stopPeer();
|
|
||||||
if (isRunning())
|
|
||||||
stop();
|
|
||||||
clearTabs(false);
|
|
||||||
delete listener;
|
|
||||||
delete peer_timer;
|
|
||||||
#ifdef WINDOWS
|
|
||||||
SetConsoleMode(PRIVATE->hOut, PRIVATE->smode);
|
|
||||||
SetConsoleTextAttribute(PRIVATE->hOut, PRIVATE->dattr);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int PIConsole::addTab(const PIString & name, char bind_key) {
|
|
||||||
if (isRunning()) lock();
|
|
||||||
tabs.push_back(Tab(name, bind_key));
|
|
||||||
cur_tab = tabs.size() - 1;
|
|
||||||
if (isRunning()) unlock();
|
|
||||||
return tabs.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void PIConsole::removeTab(uint index) {
|
|
||||||
if (index >= tabs.size()) return;
|
|
||||||
if (isRunning()) lock();
|
|
||||||
tabs.remove(index);
|
|
||||||
if (cur_tab >= tabs.size()) cur_tab = tabs.size() - 1;
|
|
||||||
if (isRunning()) unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void PIConsole::removeTab(const PIString & name) {
|
|
||||||
uint index = tabs.size() + 1;
|
|
||||||
for (uint i = 0; i < tabs.size(); ++i) {
|
|
||||||
if (tabs[i].name == name) {
|
|
||||||
index = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
removeTab(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void PIConsole::clearTab(uint index) {
|
|
||||||
if (index >= tabs.size()) return;
|
|
||||||
lock();
|
|
||||||
tabs[index].columns.clear();
|
|
||||||
if (cur_tab == index) {
|
|
||||||
clearScreen();
|
|
||||||
fillLabels();
|
|
||||||
}
|
|
||||||
if (cur_tab >= tabs.size()) cur_tab = tabs.size() - 1;
|
|
||||||
unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void PIConsole::clearTab(const PIString & name) {
|
|
||||||
uint index = tabs.size() + 1;
|
|
||||||
for (uint i = 0; i < tabs.size(); ++i) {
|
|
||||||
if (tabs[i].name == name) {
|
|
||||||
index = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
clearTab(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void PIConsole::update() {
|
|
||||||
lock();
|
|
||||||
fillLabels();
|
|
||||||
unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool PIConsole::setTab(uint index) {
|
|
||||||
if (index >= tabs.size())
|
|
||||||
return false;
|
|
||||||
if (!isRunning()) {
|
|
||||||
cur_tab = index;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
lock();
|
|
||||||
PICout::__mutex__().lock();
|
|
||||||
cur_tab = index;
|
|
||||||
clearScreen();
|
|
||||||
fillLabels();
|
|
||||||
PICout::__mutex__().unlock();
|
|
||||||
unlock();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool PIConsole::setTab(const PIString & name) {
|
|
||||||
uint index = tabs.size() + 1;
|
|
||||||
for (uint i = 0; i < tabs.size(); ++i) {
|
|
||||||
if (tabs[i].name == name) {
|
|
||||||
index = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return setTab(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool PIConsole::setTabBindKey(uint index, char bind_key) {
|
|
||||||
if (index >= tabs.size())
|
|
||||||
return false;
|
|
||||||
tabs[index].key = bind_key;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool PIConsole::setTabBindKey(const PIString & name, char bind_key) {
|
|
||||||
uint index =tabs.size() + 1;
|
|
||||||
for (uint i = 0; i < tabs.size(); ++i) {
|
|
||||||
if (tabs[i].name == name) {
|
|
||||||
index = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return setTabBindKey(index, bind_key);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void PIConsole::key_event(PIKbdListener::KeyEvent key, void * t) {
|
|
||||||
PIConsole * p = (PIConsole * )t;
|
|
||||||
int ct = p->cur_tab;
|
|
||||||
if (key.key == PIKbdListener::LeftArrow) {
|
|
||||||
do {
|
|
||||||
ct--;
|
|
||||||
if (ct < 0) return;
|
|
||||||
} while (p->tabs[ct].key == 0);
|
|
||||||
p->setTab(ct);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (key.key == PIKbdListener::RightArrow) {
|
|
||||||
do {
|
|
||||||
ct++;
|
|
||||||
if (ct >= p->tabs.size_s()) return;
|
|
||||||
} while (p->tabs[ct].key == 0);
|
|
||||||
p->setTab(ct);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (uint i = 0; i < p->tabsCount(); ++i) {
|
|
||||||
if (p->tabs[i].key == key.key) {
|
|
||||||
p->setTab(i);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (p->ret_func != 0) p->ret_func(key, t);
|
|
||||||
p->keyPressed(key, t);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int PIConsole::couts(const PIString & v) {
|
|
||||||
return printf("%s", v.data());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int PIConsole::couts(const char * v) {
|
|
||||||
return printf("%s", v);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void PIConsole::clearVariables(bool clearScreen) {
|
|
||||||
if (isRunning()) lock();
|
|
||||||
if (clearScreen && isRunning()) {
|
|
||||||
toUpperLeft();
|
|
||||||
clearScreenLower();
|
|
||||||
}
|
|
||||||
columns().clear();
|
|
||||||
if (isRunning()) unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void PIConsole::stop(bool clear) {
|
|
||||||
PIThread::stop(true);
|
|
||||||
if (clear) clearScreen();
|
|
||||||
moveTo(0, max_y + 4);
|
|
||||||
showCursor();
|
|
||||||
couts(fstr(Normal));
|
|
||||||
#ifdef WINDOWS
|
|
||||||
SetConsoleMode(PRIVATE->hOut, PRIVATE->smode);
|
|
||||||
SetConsoleTextAttribute(PRIVATE->hOut, PRIVATE->dattr);
|
|
||||||
#endif
|
|
||||||
fflush(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
PIString PIConsole::fstr(FormatFlags f) {
|
|
||||||
num_format = systime_format = 0;
|
|
||||||
if (f[PIConsole::Dec]) num_format = 0;
|
|
||||||
if (f[PIConsole::Hex]) num_format = 1;
|
|
||||||
if (f[PIConsole::Oct]) num_format = 2;
|
|
||||||
if (f[PIConsole::Bin]) num_format = 4;
|
|
||||||
if (f[PIConsole::Scientific]) num_format = 3;
|
|
||||||
if (f[PIConsole::SystemTimeSplit]) systime_format = 0;
|
|
||||||
if (f[PIConsole::SystemTimeSeconds]) systime_format = 1;
|
|
||||||
|
|
||||||
#ifdef WINDOWS
|
|
||||||
WORD attr = 0;
|
|
||||||
|
|
||||||
if (f[PIConsole::Inverse]) {
|
|
||||||
if (f[PIConsole::Red]) attr |= BACKGROUND_RED;
|
|
||||||
if (f[PIConsole::Green]) attr |= BACKGROUND_GREEN;
|
|
||||||
if (f[PIConsole::Blue]) attr |= BACKGROUND_BLUE;
|
|
||||||
if (f[PIConsole::Yellow]) attr |= (BACKGROUND_RED | BACKGROUND_GREEN);
|
|
||||||
if (f[PIConsole::Magenta]) attr |= (BACKGROUND_RED | BACKGROUND_BLUE);
|
|
||||||
if (f[PIConsole::Cyan]) attr |= (BACKGROUND_GREEN | BACKGROUND_BLUE);
|
|
||||||
if (f[PIConsole::White]) attr |= (BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE);
|
|
||||||
if (f[PIConsole::BackRed]) attr |= FOREGROUND_RED;
|
|
||||||
if (f[PIConsole::BackGreen]) attr |= FOREGROUND_GREEN;
|
|
||||||
if (f[PIConsole::BackBlue]) attr |= FOREGROUND_BLUE;
|
|
||||||
if (f[PIConsole::BackYellow]) attr |= (FOREGROUND_RED | FOREGROUND_GREEN);
|
|
||||||
if (f[PIConsole::BackMagenta]) attr |= (FOREGROUND_RED | FOREGROUND_BLUE);
|
|
||||||
if (f[PIConsole::BackCyan]) attr |= (FOREGROUND_GREEN | FOREGROUND_BLUE);
|
|
||||||
if (f[PIConsole::BackWhite]) attr |= (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
|
|
||||||
if ((attr & BACKGROUND_RED) + (attr & BACKGROUND_GREEN) + (attr & BACKGROUND_BLUE) == 0)
|
|
||||||
attr |= FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
|
|
||||||
} else {
|
|
||||||
if (f[PIConsole::Red]) attr |= FOREGROUND_RED;
|
|
||||||
if (f[PIConsole::Green]) attr |= FOREGROUND_GREEN;
|
|
||||||
if (f[PIConsole::Blue]) attr |= FOREGROUND_BLUE;
|
|
||||||
if (f[PIConsole::Yellow]) attr |= (FOREGROUND_RED | FOREGROUND_GREEN);
|
|
||||||
if (f[PIConsole::Magenta]) attr |= (FOREGROUND_RED | FOREGROUND_BLUE);
|
|
||||||
if (f[PIConsole::Cyan]) attr |= (FOREGROUND_GREEN | FOREGROUND_BLUE);
|
|
||||||
if (f[PIConsole::White]) attr |= (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
|
|
||||||
if (f[PIConsole::BackRed]) attr |= BACKGROUND_RED;
|
|
||||||
if (f[PIConsole::BackGreen]) attr |= BACKGROUND_GREEN;
|
|
||||||
if (f[PIConsole::BackBlue]) attr |= BACKGROUND_BLUE;
|
|
||||||
if (f[PIConsole::BackYellow]) attr |= (BACKGROUND_RED | BACKGROUND_GREEN);
|
|
||||||
if (f[PIConsole::BackMagenta]) attr |= (BACKGROUND_RED | BACKGROUND_BLUE);
|
|
||||||
if (f[PIConsole::BackCyan]) attr |= (BACKGROUND_GREEN | BACKGROUND_BLUE);
|
|
||||||
if (f[PIConsole::BackWhite]) attr |= (BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE);
|
|
||||||
if ((attr & FOREGROUND_RED) + (attr & FOREGROUND_GREEN) + (attr & FOREGROUND_BLUE) == 0)
|
|
||||||
attr |= FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
|
|
||||||
}
|
|
||||||
if (f[PIConsole::Bold]) attr |= FOREGROUND_INTENSITY;
|
|
||||||
if (f[PIConsole::Underline]) attr |= COMMON_LVB_UNDERSCORE;
|
|
||||||
|
|
||||||
SetConsoleTextAttribute(PRIVATE->hOut, attr);
|
|
||||||
return PIString();
|
|
||||||
#else
|
|
||||||
PIString ts("\e[0");
|
|
||||||
|
|
||||||
if (f[PIConsole::Bold]) ts += ";1";
|
|
||||||
if (f[PIConsole::Faint]) ts += ";2";
|
|
||||||
if (f[PIConsole::Italic]) ts += ";3";
|
|
||||||
if (f[PIConsole::Underline]) ts += ";4";
|
|
||||||
if (f[PIConsole::Blink]) ts += ";5";
|
|
||||||
if (f[PIConsole::Inverse]) ts += ";7";
|
|
||||||
|
|
||||||
if (f[PIConsole::Black]) ts += ";30";
|
|
||||||
if (f[PIConsole::Red]) ts += ";31";
|
|
||||||
if (f[PIConsole::Green]) ts += ";32";
|
|
||||||
if (f[PIConsole::Yellow]) ts += ";33";
|
|
||||||
if (f[PIConsole::Blue]) ts += ";34";
|
|
||||||
if (f[PIConsole::Magenta]) ts += ";35";
|
|
||||||
if (f[PIConsole::Cyan]) ts += ";36";
|
|
||||||
if (f[PIConsole::White]) ts += ";37";
|
|
||||||
|
|
||||||
if (f[PIConsole::BackBlack]) ts += ";40";
|
|
||||||
if (f[PIConsole::BackRed]) ts += ";41";
|
|
||||||
if (f[PIConsole::BackGreen]) ts += ";42";
|
|
||||||
if (f[PIConsole::BackYellow]) ts += ";43";
|
|
||||||
if (f[PIConsole::BackBlue]) ts += ";44";
|
|
||||||
if (f[PIConsole::BackMagenta]) ts += ";45";
|
|
||||||
if (f[PIConsole::BackCyan]) ts += ";46";
|
|
||||||
if (f[PIConsole::BackWhite]) ts += ";47";
|
|
||||||
|
|
||||||
return ts + "m";
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
inline int PIConsole::couts(const bool v) {return (v ? printf("true") : printf("false"));}
|
|
||||||
inline int PIConsole::couts(const char v) {return printf("%c", v);}
|
|
||||||
inline int PIConsole::couts(const short v) {
|
|
||||||
switch (num_format) {case (1): return printf("0x%.4hX", v); break; case (2): return printf("%o", v); break; case (4): return printf("%s", toBin(&v, 2)); break; default: return printf("%hd", v); break;}
|
|
||||||
}
|
|
||||||
inline int PIConsole::couts(const int v) {
|
|
||||||
switch (num_format) {case (1): return printf("0x%.8X", v); break; case (2): return printf("%o", v); break; case (4): return printf("%s", toBin(&v, 4)); break; default: return printf("%d", v); break;}
|
|
||||||
}
|
|
||||||
inline int PIConsole::couts(const long v) {
|
|
||||||
switch (num_format) {case (1): return printf("0x%.16lX", v); break; case (2): return printf("%lo", v); break; case (4): return printf("%s", toBin(&v, sizeof(v))); break; default: return printf("%ld", v); break;}
|
|
||||||
}
|
|
||||||
inline int PIConsole::couts(const llong v) {
|
|
||||||
switch (num_format) {case (1): return printf("0x%.16llX", v); break; case (2): return printf("%llo", v); break; case (4): return printf("%s", toBin(&v, sizeof(v))); break; default: return printf("%lld", v); break;}
|
|
||||||
}
|
|
||||||
inline int PIConsole::couts(const uchar v) {
|
|
||||||
switch (num_format) {case (1): return printf("0x%.2X", v); break; case (2): return printf("%o", v); break; case (4): return printf("%s", toBin(&v, 1)); break; default: return printf("%u", v); break;}
|
|
||||||
}
|
|
||||||
inline int PIConsole::couts(const ushort v) {
|
|
||||||
switch (num_format) {case (1): return printf("0x%.4hX", v); break; case (2): return printf("%o", v); break; case (4): return printf("%s", toBin(&v, 2)); break; default: return printf("%hu", v); break;}
|
|
||||||
}
|
|
||||||
inline int PIConsole::couts(const uint v) {
|
|
||||||
switch (num_format) {case (1): return printf("0x%.8X", v); break; case (2): return printf("%o", v); break; case (4): return printf("%s", toBin(&v, 4)); break; default: return printf("%u", v); break;}
|
|
||||||
}
|
|
||||||
inline int PIConsole::couts(const ulong v) {
|
|
||||||
switch (num_format) {case (1): return printf("0x%.16lX", v); break; case (2): return printf("%lo", v); break; case (4): return printf("%s", toBin(&v, sizeof(v))); break; default: return printf("%lu", v); break;}
|
|
||||||
}
|
|
||||||
inline int PIConsole::couts(const ullong v) {
|
|
||||||
switch (num_format) {case (1): return printf("0x%.16llX", v); break; case (2): return printf("%llo", v); break; case (4): return printf("%s", toBin(&v, sizeof(v))); break; default: return printf("%llu", v); break;}
|
|
||||||
}
|
|
||||||
inline int PIConsole::couts(const float v) {
|
|
||||||
switch (num_format) {case (3): return printf("%e", v); break; default: return printf("%.5g", v); break;}
|
|
||||||
}
|
|
||||||
inline int PIConsole::couts(const double v) {
|
|
||||||
switch (num_format) {case (3): return printf("%le", v); break; default: return printf("%.5lg", v); break;}
|
|
||||||
}
|
|
||||||
inline int PIConsole::couts(const PISystemTime & v) {
|
|
||||||
switch (systime_format) {case (1): return printf("%.6lg", v.toSeconds()); break;
|
|
||||||
default: return couts(v.seconds) + printf(" s, ") + couts(v.nanoseconds) + printf(" ns"); break;}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void PIConsole::toUpperLeft() {
|
|
||||||
#ifdef WINDOWS
|
|
||||||
SetConsoleCursorPosition(PRIVATE->hOut, PRIVATE->ulcoord);
|
|
||||||
#else
|
|
||||||
printf("\e[H");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void PIConsole::moveRight(int n) {
|
|
||||||
#ifdef WINDOWS
|
|
||||||
SetConsoleCursorPosition(PRIVATE->hOut, PRIVATE->getWinCoord(n));
|
|
||||||
#else
|
|
||||||
if (n > 0) printf("\e[%dC", n);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void PIConsole::moveLeft(int n) {
|
|
||||||
#ifdef WINDOWS
|
|
||||||
SetConsoleCursorPosition(PRIVATE->hOut, PRIVATE->getWinCoord(-n));
|
|
||||||
#else
|
|
||||||
if (n > 0) printf("\e[%dD", n);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void PIConsole::moveTo(int x, int y) {
|
|
||||||
#ifdef WINDOWS
|
|
||||||
PRIVATE->ccoord.X = x;
|
|
||||||
PRIVATE->ccoord.Y = PRIVATE->ulcoord.Y + y;
|
|
||||||
SetConsoleCursorPosition(PRIVATE->hOut, PRIVATE->ccoord);
|
|
||||||
#else
|
|
||||||
printf("\e[%d;%dH", y, x);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void PIConsole::clearScreen() {
|
|
||||||
#ifdef WINDOWS
|
|
||||||
couts(fstr(Normal));
|
|
||||||
toUpperLeft();
|
|
||||||
FillConsoleOutputAttribute(PRIVATE->hOut, PRIVATE->dattr, width * (height + 1), PRIVATE->ulcoord, &PRIVATE->written);
|
|
||||||
FillConsoleOutputCharacter(PRIVATE->hOut, ' ', width * (height + 1), PRIVATE->ulcoord, &PRIVATE->written);
|
|
||||||
#else
|
|
||||||
couts(fstr(Normal)); printf("\e[H\e[J");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void PIConsole::clearScreenLower() {
|
|
||||||
#ifdef WINDOWS
|
|
||||||
couts(fstr(Normal));
|
|
||||||
PRIVATE->getWinCurCoord();
|
|
||||||
FillConsoleOutputAttribute(PRIVATE->hOut, PRIVATE->dattr, width * height - width * PRIVATE->ccoord.Y + PRIVATE->ccoord.X, PRIVATE->ccoord, &PRIVATE->written);
|
|
||||||
FillConsoleOutputCharacter(PRIVATE->hOut, ' ', width * height - width * PRIVATE->ccoord.Y + PRIVATE->ccoord.X, PRIVATE->ccoord, &PRIVATE->written);
|
|
||||||
#else
|
|
||||||
couts(fstr(Normal)); printf("\e[J");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void PIConsole::clearLine() {
|
|
||||||
#ifdef WINDOWS
|
|
||||||
PRIVATE->getWinCurCoord();
|
|
||||||
FillConsoleOutputAttribute(PRIVATE->hOut, PRIVATE->dattr, width - PRIVATE->ccoord.X, PRIVATE->ccoord, &PRIVATE->written);
|
|
||||||
FillConsoleOutputCharacter(PRIVATE->hOut, ' ', width - PRIVATE->ccoord.X, PRIVATE->ccoord, &PRIVATE->written);
|
|
||||||
#else
|
|
||||||
printf("\e[K");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void PIConsole::newLine() {
|
|
||||||
#ifdef WINDOWS
|
|
||||||
PRIVATE->getWinCurCoord();
|
|
||||||
PRIVATE->ccoord.X = 0; PRIVATE->ccoord.Y++;
|
|
||||||
SetConsoleCursorPosition(PRIVATE->hOut, PRIVATE->ccoord);
|
|
||||||
#else
|
|
||||||
printf("\eE");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void PIConsole::hideCursor() {
|
|
||||||
#ifdef WINDOWS
|
|
||||||
PRIVATE->curinfo.bVisible = false;
|
|
||||||
SetConsoleCursorInfo(PRIVATE->hOut, &PRIVATE->curinfo);
|
|
||||||
#else
|
|
||||||
printf("\e[?25l");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void PIConsole::showCursor() {
|
|
||||||
#ifdef WINDOWS
|
|
||||||
PRIVATE->curinfo.bVisible = true; SetConsoleCursorInfo(PRIVATE->hOut, &PRIVATE->curinfo);
|
|
||||||
#else
|
|
||||||
printf("\e[?25h");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void PIConsole::begin() {
|
|
||||||
#ifdef WINDOWS
|
|
||||||
SetConsoleMode(PRIVATE->hOut, ENABLE_WRAP_AT_EOL_OUTPUT);
|
|
||||||
#endif
|
|
||||||
max_y = 0;
|
|
||||||
PICout::__mutex__().lock();
|
|
||||||
clearScreen();
|
|
||||||
hideCursor();
|
|
||||||
fillLabels();
|
|
||||||
PICout::__mutex__().unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void PIConsole::run() {
|
|
||||||
if (pause_) return;
|
|
||||||
uint cx, clen = 0;
|
|
||||||
int j;
|
|
||||||
#ifdef WINDOWS
|
|
||||||
GetConsoleScreenBufferInfo(PRIVATE->hOut, &PRIVATE->sbi);
|
|
||||||
width = PRIVATE->sbi.srWindow.Right - PRIVATE->sbi.srWindow.Left;
|
|
||||||
height = PRIVATE->sbi.srWindow.Bottom - PRIVATE->sbi.srWindow.Top;
|
|
||||||
#else
|
|
||||||
# ifdef FREERTOS
|
|
||||||
width = 80;
|
|
||||||
height = 24;
|
|
||||||
# else
|
|
||||||
winsize ws;
|
|
||||||
ioctl(0, TIOCGWINSZ, &ws);
|
|
||||||
width = ws.ws_col;
|
|
||||||
height = ws.ws_row;
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
//fflush(0); return;
|
|
||||||
PICout::__mutex__().lock();
|
|
||||||
if (pwidth != width || pheight != height) {
|
|
||||||
clearScreen();
|
|
||||||
fillLabels();
|
|
||||||
}
|
|
||||||
pwidth = width;
|
|
||||||
pheight = height;
|
|
||||||
col_cnt = columns().size();
|
|
||||||
col_wid = (col_cnt > 0) ? width / col_cnt : width;
|
|
||||||
for (uint i = 0; i < col_cnt; ++i) {
|
|
||||||
PIVector<Variable> & cvars(tabs[cur_tab].columns[i].variables);
|
|
||||||
cx = col_wid * i;
|
|
||||||
toUpperLeft();
|
|
||||||
if (max_y < cvars.size()) max_y = cvars.size();
|
|
||||||
j = 0;
|
|
||||||
piForeachC (Variable & tv_, cvars) {
|
|
||||||
if (j > height - 3) continue;
|
|
||||||
j++;
|
|
||||||
moveRight(cx);
|
|
||||||
if (tv_.type == 15) {
|
|
||||||
newLine();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
moveRight(tv_.offset);
|
|
||||||
const void * ptr = 0;
|
|
||||||
if (tv_.remote) {
|
|
||||||
if (tv_.type == 0) {
|
|
||||||
rstr.clear();
|
|
||||||
rba = tv_.rdata;
|
|
||||||
rba >> rstr;
|
|
||||||
rstr.trim();
|
|
||||||
ptr = &rstr;
|
|
||||||
} else
|
|
||||||
ptr = tv_.rdata.data();
|
|
||||||
} else
|
|
||||||
ptr = tv_.ptr;
|
|
||||||
switch (tv_.type) {
|
|
||||||
case 0: clen = printValue(ptr != 0 ? *(const PIString*)ptr : PIString(), tv_.format); break;
|
|
||||||
case 1: clen = printValue(ptr != 0 ? *(const bool*)ptr : false, tv_.format); break;
|
|
||||||
case 2: clen = printValue(ptr != 0 ? *(const int*)ptr : 0, tv_.format); break;
|
|
||||||
case 3: clen = printValue(ptr != 0 ? *(const long*)ptr : 0l, tv_.format); break;
|
|
||||||
case 4: clen = printValue(ptr != 0 ? *(const char*)ptr : char(0), tv_.format); break;
|
|
||||||
case 5: clen = printValue(ptr != 0 ? *(const float*)ptr : 0.f, tv_.format); break;
|
|
||||||
case 6: clen = printValue(ptr != 0 ? *(const double*)ptr : 0., tv_.format); break;
|
|
||||||
case 7: clen = printValue(ptr != 0 ? *(const short*)ptr : short(0), tv_.format); break;
|
|
||||||
case 8: clen = printValue(ptr != 0 ? *(const uint*)ptr : 0u, tv_.format); break;
|
|
||||||
case 9: clen = printValue(ptr != 0 ? *(const ulong*)ptr : 0ul, tv_.format); break;
|
|
||||||
case 10: clen = printValue(ptr != 0 ? *(const ushort*)ptr : ushort(0), tv_.format); break;
|
|
||||||
case 11: clen = printValue(ptr != 0 ? *(const uchar*)ptr : uchar(0), tv_.format); break;
|
|
||||||
case 12: clen = printValue(ptr != 0 ? *(const llong*)ptr : 0l, tv_.format); break;
|
|
||||||
case 13: clen = printValue(ptr != 0 ? *(const ullong*)ptr: 0ull, tv_.format); break;
|
|
||||||
case 20: clen = printValue(ptr != 0 ? *(const PISystemTime*)ptr: PISystemTime(), tv_.format); break;
|
|
||||||
case 14: clen = printValue(bitsValue(ptr, tv_.bitFrom, tv_.bitCount), tv_.format); break;
|
|
||||||
}
|
|
||||||
if (clen + tv_.offset < (uint)col_wid) {
|
|
||||||
PIString ts = PIString(
|
|
||||||
#if defined(QNX) || defined(FREE_BSD)
|
|
||||||
col_wid - clen - tv_.offset - 1, ' ');
|
|
||||||
#else
|
|
||||||
col_wid - clen - tv_.offset, ' ');
|
|
||||||
#endif
|
|
||||||
printf("%s", ts.data());
|
|
||||||
}
|
|
||||||
newLine();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#ifdef WINDOWS
|
|
||||||
moveTo(0, max_y + 1);
|
|
||||||
#else
|
|
||||||
moveTo(0, max_y + 2);
|
|
||||||
#endif
|
|
||||||
fflush(0);
|
|
||||||
PICout::__mutex__().unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void PIConsole::fillLabels() {
|
|
||||||
if (!isRunning()) return;
|
|
||||||
uint cx, cy, mx = 0, dx;
|
|
||||||
#ifdef WINDOWS
|
|
||||||
GetConsoleScreenBufferInfo(PRIVATE->hOut, &PRIVATE->sbi);
|
|
||||||
width = PRIVATE->sbi.srWindow.Right - PRIVATE->sbi.srWindow.Left;
|
|
||||||
height = PRIVATE->sbi.srWindow.Bottom - PRIVATE->sbi.srWindow.Top;
|
|
||||||
#else
|
|
||||||
# ifdef FREERTOS
|
|
||||||
width = 80;
|
|
||||||
height = 24;
|
|
||||||
# else
|
|
||||||
winsize ws;
|
|
||||||
ioctl(0, TIOCGWINSZ, &ws);
|
|
||||||
width = ws.ws_col;
|
|
||||||
height = ws.ws_row;
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
max_y = 0;
|
|
||||||
col_cnt = columns().size();
|
|
||||||
col_wid = (col_cnt > 0) ? width / col_cnt : width;
|
|
||||||
for (uint i = 0; i < col_cnt; ++i) {
|
|
||||||
Column & ccol(tabs[cur_tab].columns[i]);
|
|
||||||
PIVector<Variable> & cvars(ccol.variables);
|
|
||||||
if (ccol.alignment != Nothing) {
|
|
||||||
mx = 0;
|
|
||||||
piForeachC (Variable & j, cvars)
|
|
||||||
if (!j.isEmpty())
|
|
||||||
if (mx < j.name.size())
|
|
||||||
mx = j.name.size();
|
|
||||||
mx += 2;
|
|
||||||
}
|
|
||||||
cx = col_wid * i;
|
|
||||||
cy = 1;
|
|
||||||
toUpperLeft();
|
|
||||||
for (uint j = 0; j < cvars.size(); ++j) {
|
|
||||||
if (int(j) > height - 3) continue;
|
|
||||||
if (max_y < j) max_y = j;
|
|
||||||
moveRight(cx);
|
|
||||||
Variable & tv_(cvars[j]);
|
|
||||||
cvars[j].nx = cx;
|
|
||||||
cvars[j].ny = cy;
|
|
||||||
if (tv_.name.isEmpty()) {
|
|
||||||
cvars[j].offset = 0;
|
|
||||||
clearLine();
|
|
||||||
newLine();
|
|
||||||
cy++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
clearLine();
|
|
||||||
//piCout << tv_.name << tv_.type << tv_.ptr;
|
|
||||||
if (tv_.type == 15) {
|
|
||||||
cvars[j].offset = cvars[j].name.length();
|
|
||||||
cvars[j].nx += cvars[j].offset;
|
|
||||||
printLine(tv_.name, cx, tv_.format);
|
|
||||||
newLine();
|
|
||||||
cy++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!tv_.isEmpty()) {
|
|
||||||
switch (ccol.alignment) {
|
|
||||||
case Nothing:
|
|
||||||
cvars[j].offset = (tv_.name + ": ").length();
|
|
||||||
cvars[j].nx += cvars[j].offset;
|
|
||||||
printValue(tv_.name + ": ", tv_.format);
|
|
||||||
break;
|
|
||||||
case Left:
|
|
||||||
cvars[j].offset = mx;
|
|
||||||
cvars[j].nx += cvars[j].offset;
|
|
||||||
printValue(tv_.name + ": ", tv_.format);
|
|
||||||
break;
|
|
||||||
case Right:
|
|
||||||
cvars[j].offset = mx;
|
|
||||||
cvars[j].nx += cvars[j].offset;
|
|
||||||
dx = mx - (tv_.name + ": ").length();
|
|
||||||
moveRight(dx);
|
|
||||||
printValue(tv_.name + ": ", tv_.format);
|
|
||||||
moveLeft(dx);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
newLine();
|
|
||||||
cy++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#ifdef WINDOWS
|
|
||||||
moveTo(0, max_y + 1);
|
|
||||||
#else
|
|
||||||
moveTo(0, max_y + 2);
|
|
||||||
#endif
|
|
||||||
if (!tabs[cur_tab].status.isEmpty()) {
|
|
||||||
printValue(tabs[cur_tab].status);
|
|
||||||
newLine();
|
|
||||||
}
|
|
||||||
status();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void PIConsole::status() {
|
|
||||||
Tab * ctab;
|
|
||||||
for (uint i = 0; i < tabsCount(); ++i) {
|
|
||||||
ctab = &tabs[i];
|
|
||||||
if (ctab->key == 0) continue;
|
|
||||||
printValue(ctab->key, PIConsole::White | PIConsole::Bold);
|
|
||||||
if (i == cur_tab)
|
|
||||||
printValue(ctab->name + " ", PIConsole::BackYellow | PIConsole::Black);
|
|
||||||
else
|
|
||||||
printValue(ctab->name + " ", PIConsole::Cyan | PIConsole::Inverse);
|
|
||||||
printValue(" ");
|
|
||||||
}
|
|
||||||
newLine();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int PIConsole::bitsValue(const void * src, int offset, int count) const {
|
|
||||||
int ret = 0, stbyte = offset / 8, cbit = offset - stbyte * 8;
|
|
||||||
char cbyte = reinterpret_cast<const char * >(src)[stbyte];
|
|
||||||
for (int i = 0; i < count; i++) {
|
|
||||||
ret |= ((cbyte >> cbit & 1) << i);
|
|
||||||
cbit++;
|
|
||||||
if (cbit == 8) {
|
|
||||||
cbit = 0;
|
|
||||||
stbyte++;
|
|
||||||
cbyte = reinterpret_cast<const char * >(src)[stbyte];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const char * PIConsole::toBin(const void * d, int s) {
|
|
||||||
binstr.clear();
|
|
||||||
uchar cc, b;
|
|
||||||
for (int i = 0; i < s; ++i) {
|
|
||||||
cc = ((const uchar *)d)[i];
|
|
||||||
b = 1;
|
|
||||||
for (int j = 0; j < 8; ++j) {
|
|
||||||
binstr << (cc & b ? "1" : "0");
|
|
||||||
b <<= 1;
|
|
||||||
}
|
|
||||||
if (i < s - 1) binstr << " ";
|
|
||||||
}
|
|
||||||
binstr.reverse();
|
|
||||||
return binstr.data();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#define ADD_VAR_BODY vid++; tv.id = vid; tv.name = name; tv.bitFrom = tv.bitCount = 0; tv.format = format; tv.remote = false; checkColumn(col);
|
|
||||||
|
|
||||||
void PIConsole::addString(const PIString & name, int col, FormatFlags format) {
|
|
||||||
ADD_VAR_BODY tv.type = 15; tv.size = 0; tv.ptr = 0; column(col).push_back(tv);}
|
|
||||||
void PIConsole::addVariable(const PIString & name, const PIString * ptr, int col, FormatFlags format) {
|
|
||||||
ADD_VAR_BODY tv.type = 0; tv.size = 0; tv.ptr = ptr; column(col).push_back(tv);}
|
|
||||||
void PIConsole::addVariable(const PIString & name, const bool * ptr, int col, FormatFlags format) {
|
|
||||||
ADD_VAR_BODY tv.type = 1; tv.size = sizeof(*ptr); tv.ptr = ptr; column(col).push_back(tv);}
|
|
||||||
void PIConsole::addVariable(const PIString & name, const int * ptr, int col, FormatFlags format) {
|
|
||||||
ADD_VAR_BODY tv.type = 2; tv.size = sizeof(*ptr); tv.ptr = ptr; column(col).push_back(tv);}
|
|
||||||
void PIConsole::addVariable(const PIString & name, const long * ptr, int col, FormatFlags format) {
|
|
||||||
ADD_VAR_BODY tv.type = 3; tv.size = sizeof(*ptr); tv.ptr = ptr; column(col).push_back(tv);}
|
|
||||||
void PIConsole::addVariable(const PIString & name, const char * ptr, int col, FormatFlags format) {
|
|
||||||
ADD_VAR_BODY tv.type = 4; tv.size = sizeof(*ptr); tv.ptr = ptr; column(col).push_back(tv);}
|
|
||||||
void PIConsole::addVariable(const PIString & name, const float * ptr, int col, FormatFlags format) {
|
|
||||||
ADD_VAR_BODY tv.type = 5; tv.size = sizeof(*ptr); tv.ptr = ptr; column(col).push_back(tv);}
|
|
||||||
void PIConsole::addVariable(const PIString & name, const double * ptr, int col, FormatFlags format) {
|
|
||||||
ADD_VAR_BODY tv.type = 6; tv.size = sizeof(*ptr); tv.ptr = ptr; column(col).push_back(tv);}
|
|
||||||
void PIConsole::addVariable(const PIString & name, const short * ptr, int col, FormatFlags format) {
|
|
||||||
ADD_VAR_BODY tv.type = 7; tv.size = sizeof(*ptr); tv.ptr = ptr; column(col).push_back(tv);}
|
|
||||||
void PIConsole::addVariable(const PIString & name, const uint * ptr, int col, FormatFlags format) {
|
|
||||||
ADD_VAR_BODY tv.type = 8; tv.size = sizeof(*ptr); tv.ptr = ptr; column(col).push_back(tv);}
|
|
||||||
void PIConsole::addVariable(const PIString & name, const ulong * ptr, int col, FormatFlags format) {
|
|
||||||
ADD_VAR_BODY tv.type = 9; tv.size = sizeof(*ptr); tv.ptr = ptr; column(col).push_back(tv);}
|
|
||||||
void PIConsole::addVariable(const PIString & name, const ushort * ptr, int col, FormatFlags format) {
|
|
||||||
ADD_VAR_BODY tv.type = 10; tv.size = sizeof(*ptr); tv.ptr = ptr; column(col).push_back(tv);}
|
|
||||||
void PIConsole::addVariable(const PIString & name, const uchar * ptr, int col, FormatFlags format) {
|
|
||||||
ADD_VAR_BODY tv.type = 11; tv.size = sizeof(*ptr); tv.ptr = ptr; column(col).push_back(tv);}
|
|
||||||
void PIConsole::addVariable(const PIString & name, const llong * ptr, int col, FormatFlags format) {
|
|
||||||
ADD_VAR_BODY tv.type = 12; tv.size = sizeof(*ptr); tv.ptr = ptr; column(col).push_back(tv);}
|
|
||||||
void PIConsole::addVariable(const PIString & name, const ullong * ptr, int col, FormatFlags format) {
|
|
||||||
ADD_VAR_BODY tv.type = 13; tv.size = sizeof(*ptr); tv.ptr = ptr; column(col).push_back(tv);}
|
|
||||||
void PIConsole::addVariable(const PIString & name, const PISystemTime * ptr, int col, FormatFlags format) {
|
|
||||||
ADD_VAR_BODY tv.type = 20; tv.size = sizeof(*ptr); tv.ptr = ptr; column(col).push_back(tv);}
|
|
||||||
/** \brief Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format"
|
|
||||||
* \details This function add to column "column" next lines:
|
|
||||||
* * "<name> diagnostics"
|
|
||||||
* * "Received count": \a PIDiagnostics::receiveCount
|
|
||||||
* * "Invalid count": \a PIDiagnostics::wrongCount
|
|
||||||
* * "Sended count": \a PIDiagnostics::sendCount
|
|
||||||
* * "Immediate Frequency, Hz": \a PIDiagnostics::immediateFrequency
|
|
||||||
* * "Integral Frequency, Hz": \a PIDiagnostics::integralFrequency
|
|
||||||
* * "Receive speed": \a PIDiagnostics::receiveSpeed
|
|
||||||
* * "Send speed": \a PIDiagnostics::sendSpeed
|
|
||||||
* * "Quality": \a PIDiagnostics::quality
|
|
||||||
* */
|
|
||||||
void PIConsole::addVariable(const PIString & name, const PIDiagnostics * ptr, int col, FormatFlags format) {
|
|
||||||
addString(name + " diagnostics", col, format | PIConsole::Bold);
|
|
||||||
// addVariable("Received count", ptr->receiveCount_ptr(), col, format);
|
|
||||||
// addVariable("Invalid count", ptr->wrongCount_ptr(), col, format);
|
|
||||||
// addVariable("Sended count", ptr->sendCount_ptr(), col, format);
|
|
||||||
// addVariable("Immediate Frequency, Hz", ptr->immediateFrequency_ptr(), col, format);
|
|
||||||
// addVariable("Integral Frequency, Hz", ptr->integralFrequency_ptr(), col, format);
|
|
||||||
// addVariable("Receive speed", ptr->receiveSpeed_ptr(), col, format);
|
|
||||||
// addVariable("Send speed", ptr->sendSpeed_ptr(), col, format);
|
|
||||||
// addVariable("Quality", ptr->quality_ptr(), col, format);
|
|
||||||
}
|
|
||||||
void PIConsole::addVariable(const PIString & name, const PISystemMonitor * ptr, int col, FormatFlags format) {
|
|
||||||
addString("monitor " + name, col, format | PIConsole::Bold);
|
|
||||||
//addVariable("PID", &(ptr->statistic().ID), col, format);
|
|
||||||
//addVariable("state", &(ptr->statistic().state), col, format);
|
|
||||||
//addVariable("threads", &(ptr->statistic().threads), col, format);
|
|
||||||
//addVariable("priority", &(ptr->statistic().priority), col, format);
|
|
||||||
//addVariable("memory physical", &(ptr->statistic().physical_memsize_readable), col, format);
|
|
||||||
//addVariable("memory shared", &(ptr->statistic().share_memsize_readable), col, format);
|
|
||||||
//addVariable("cpu load kernel", &(ptr->statistic().cpu_load_system), col, format);
|
|
||||||
//addVariable("cpu load user", &(ptr->statistic().cpu_load_user), col, format);
|
|
||||||
}
|
|
||||||
void PIConsole::addBitVariable(const PIString & name, const void * ptr, int fromBit, int bitCount, int col, FormatFlags format) {
|
|
||||||
vid++; tv.id = vid; tv.size = sizeof(ullong); tv.name = name; tv.bitFrom = fromBit; tv.bitCount = bitCount; tv.type = 14; tv.ptr = ptr; tv.format = format;
|
|
||||||
checkColumn(col); column(col).push_back(tv);}
|
|
||||||
void PIConsole::addEmptyLine(int col, uint count) {
|
|
||||||
tv.id = 0; tv.size = 0; tv.name = ""; tv.type = 0; tv.ptr = 0; tv.format = Normal;
|
|
||||||
for (uint i = 0; i < count; ++i) {
|
|
||||||
checkColumn(col);
|
|
||||||
column(col).push_back(tv);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
PIString PIConsole::getString(int x, int y) {
|
|
||||||
bool run = isRunning();
|
|
||||||
if (run) PIThread::stop(true);
|
|
||||||
listener->setActive(false);
|
|
||||||
msleep(50);
|
|
||||||
#ifdef WINDOWS
|
|
||||||
moveTo(x - 1, y - 1);
|
|
||||||
#else
|
|
||||||
moveTo(x, y);
|
|
||||||
#endif
|
|
||||||
showCursor();
|
|
||||||
PIByteArray ba(4096);
|
|
||||||
#ifdef CC_VC
|
|
||||||
int ret = scanf_s(" %s", ba.data());
|
|
||||||
#else
|
|
||||||
int ret = scanf(" %s", ba.data());
|
|
||||||
#endif
|
|
||||||
listener->setActive(true);
|
|
||||||
if (run) start();
|
|
||||||
if (ret >= 1) return PIString(ba);
|
|
||||||
else return PIString();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
PIString PIConsole::getString(const PIString & name) {
|
|
||||||
piForeachC (Column & i, tabs[cur_tab].columns)
|
|
||||||
piForeachC (Variable & j, i.variables)
|
|
||||||
if (j.name == name)
|
|
||||||
return getString(j.nx + 1, j.ny);
|
|
||||||
return PIString();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#define PRINT_VAR_BODY couts(fstr(format)); int ret = couts(value); couts(fstr(PIConsole::Dec)); return ret;
|
|
||||||
|
|
||||||
inline void PIConsole::printLine(const PIString & value, int dx, FormatFlags format) {
|
|
||||||
int i = width - value.length() - dx;
|
|
||||||
#if defined(QNX) || defined(FREE_BSD)
|
|
||||||
--i;
|
|
||||||
#endif
|
|
||||||
PIString ts = fstr(format);
|
|
||||||
couts(ts);
|
|
||||||
if (i >= 0) ts = value + PIString(i, ' ');
|
|
||||||
else ts = value.left(value.size() + i);
|
|
||||||
couts(ts);
|
|
||||||
couts(fstr(Dec));
|
|
||||||
}
|
|
||||||
inline int PIConsole::printValue(const PIString & value, FormatFlags format) {
|
|
||||||
couts(fstr(format));
|
|
||||||
int ret = couts(value);
|
|
||||||
fstr(PIConsole::Dec);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
inline int PIConsole::printValue(const char * value, FormatFlags format) {PRINT_VAR_BODY}
|
|
||||||
inline int PIConsole::printValue(const bool value, FormatFlags format) {PRINT_VAR_BODY}
|
|
||||||
inline int PIConsole::printValue(const int value, FormatFlags format) {PRINT_VAR_BODY}
|
|
||||||
inline int PIConsole::printValue(const long value, FormatFlags format) {PRINT_VAR_BODY}
|
|
||||||
inline int PIConsole::printValue(const llong value, FormatFlags format) {PRINT_VAR_BODY}
|
|
||||||
inline int PIConsole::printValue(const float value, FormatFlags format) {PRINT_VAR_BODY}
|
|
||||||
inline int PIConsole::printValue(const double value, FormatFlags format) {PRINT_VAR_BODY}
|
|
||||||
inline int PIConsole::printValue(const char value, FormatFlags format) {PRINT_VAR_BODY}
|
|
||||||
inline int PIConsole::printValue(const short value, FormatFlags format) {PRINT_VAR_BODY}
|
|
||||||
inline int PIConsole::printValue(const uchar value, FormatFlags format) {PRINT_VAR_BODY}
|
|
||||||
inline int PIConsole::printValue(const ushort value, FormatFlags format) {PRINT_VAR_BODY}
|
|
||||||
inline int PIConsole::printValue(const uint value, FormatFlags format) {PRINT_VAR_BODY}
|
|
||||||
inline int PIConsole::printValue(const ulong value, FormatFlags format) {PRINT_VAR_BODY}
|
|
||||||
inline int PIConsole::printValue(const ullong value, FormatFlags format) {PRINT_VAR_BODY}
|
|
||||||
inline int PIConsole::printValue(const PISystemTime & value, FormatFlags format) {PRINT_VAR_BODY}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void PIConsole::startServer(const PIString & name) {
|
|
||||||
stopPeer();
|
|
||||||
server_mode = true;
|
|
||||||
peer = new PIPeer("_rcs_:" + name);
|
|
||||||
CONNECT2(void, const PIString & , const PIByteArray &, peer, dataReceivedEvent, this, peerReceived);
|
|
||||||
CONNECT1(void, const PIString & , peer, peerDisconnectedEvent, this, peerDisconnectedEvent);
|
|
||||||
peer_timer->start(50.);
|
|
||||||
serverSendInfo();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void PIConsole::stopPeer() {
|
|
||||||
remote_clients.clear();
|
|
||||||
peer_timer->stop();
|
|
||||||
if (peer != 0) delete peer;
|
|
||||||
peer = 0;
|
|
||||||
state = Disconnected;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
PIStringList PIConsole::clients() const {
|
|
||||||
PIStringList sl;
|
|
||||||
if (peer == 0) return sl;
|
|
||||||
piForeachC (PIPeer::PeerInfo & i, peer->allPeers()) {
|
|
||||||
if (i.name.left(6) != "_rcc_:") continue;
|
|
||||||
sl << i.name.right(i.name.length() - 6);
|
|
||||||
}
|
|
||||||
return sl;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void PIConsole::listenServers() {
|
|
||||||
stopPeer();
|
|
||||||
server_mode = false;
|
|
||||||
server_name.clear();
|
|
||||||
randomize();
|
|
||||||
peer = new PIPeer("_rcc_:" + PIDateTime::current().toString("hhmmssddMMyy_") + PIString::fromNumber(randomi()));
|
|
||||||
CONNECT2(void, const PIString & , const PIByteArray &, peer, dataReceivedEvent, this, peerReceived);
|
|
||||||
peer_timer->start(100.);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
PIStringList PIConsole::availableServers() const {
|
|
||||||
PIStringList sl;
|
|
||||||
if (peer == 0) return sl;
|
|
||||||
piForeachC (PIPeer::PeerInfo & i, peer->allPeers()) {
|
|
||||||
if (i.name.left(6) != "_rcs_:") continue;
|
|
||||||
sl << i.name.right(i.name.length() - 6);
|
|
||||||
}
|
|
||||||
return sl;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void PIConsole::connectToServer(const PIString & name) {
|
|
||||||
if (peer == 0) listenServers();
|
|
||||||
server_name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void PIConsole::disconnect() {
|
|
||||||
stopPeer();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void PIConsole::serverSendInfo() {
|
|
||||||
if (peer == 0) return;
|
|
||||||
PIByteArray ba;
|
|
||||||
ba << int(0xAA);
|
|
||||||
peer->sendToAll(ba);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void PIConsole::serverSendData() {
|
|
||||||
if (peer == 0) return;
|
|
||||||
PIByteArray ba;
|
|
||||||
PIVector<VariableContent> content;
|
|
||||||
piForeach (Tab & t, tabs)
|
|
||||||
piForeach (Column & c, t.columns)
|
|
||||||
piForeach (Variable & v, c.variables)
|
|
||||||
if (!v.isEmpty() && v.id > 0) {
|
|
||||||
VariableContent vc;
|
|
||||||
vc.id = v.id;
|
|
||||||
v.writeData(vc.rdata);
|
|
||||||
content << vc;
|
|
||||||
}
|
|
||||||
piForeach (RemoteClient & rc, remote_clients) {
|
|
||||||
ba.clear();
|
|
||||||
switch (rc.state) {
|
|
||||||
case FetchingData:
|
|
||||||
ba << int(0xCC) << tabs;
|
|
||||||
//piCout << "server send const data" << rc.name << ba.size_s();
|
|
||||||
break;
|
|
||||||
case Committing:
|
|
||||||
ba << int(0xDD);
|
|
||||||
break;
|
|
||||||
case Connected:
|
|
||||||
ba << int(0xEE) << content;
|
|
||||||
//piCout << "send data" << ba.size();
|
|
||||||
break;
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
if (!ba.isEmpty())
|
|
||||||
peer->send(rc.name, ba);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
PIConsole::RemoteClient & PIConsole::remoteClient(const PIString & fname) {
|
|
||||||
piForeach (RemoteClient & i, remote_clients)
|
|
||||||
if (i.name == fname)
|
|
||||||
return i;
|
|
||||||
remote_clients << RemoteClient(fname);
|
|
||||||
return remote_clients.back();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void PIConsole::peerReceived(const PIString & from, const PIByteArray & data) {
|
|
||||||
int type;
|
|
||||||
PIByteArray ba(data);
|
|
||||||
ba >> type;
|
|
||||||
//piCout << "rec packet from" << from << "type" << PICoutManipulators::Hex << type;
|
|
||||||
if (server_mode) {
|
|
||||||
if (from.left(5) != "_rcc_") return;
|
|
||||||
//PIString rcn = from.right(from.length() - 6);
|
|
||||||
RemoteClient & rc(remoteClient(from));
|
|
||||||
switch (type) {
|
|
||||||
case 0xBB: // fetch const data request
|
|
||||||
//piCout << "fetch data request from" << from << rc.state;
|
|
||||||
if (rc.state != Connected)
|
|
||||||
rc.state = FetchingData;
|
|
||||||
break;
|
|
||||||
case 0xCC: // const data commit
|
|
||||||
//piCout << "commit from" << from;
|
|
||||||
if (rc.state != Connected)
|
|
||||||
rc.state = Connected;
|
|
||||||
break;
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
PIVector<VariableContent> content;
|
|
||||||
PIMap<int, Variable * > vids;
|
|
||||||
if (from.left(5) != "_rcs_") return;
|
|
||||||
//PIString rcn = from.right(from.length() - 6);
|
|
||||||
switch (type) {
|
|
||||||
case 0xAA: // new server
|
|
||||||
//piCout << "new server" << rcn;
|
|
||||||
break;
|
|
||||||
case 0xCC: // const data
|
|
||||||
//piCout << "received const data";
|
|
||||||
state = Committing;
|
|
||||||
ba >> tabs;
|
|
||||||
cur_tab = tabs.isEmpty() ? -1 : 0;
|
|
||||||
piForeach (Tab & t, tabs)
|
|
||||||
piForeach (Column & c, t.columns)
|
|
||||||
piForeach (Variable & v, c.variables)
|
|
||||||
v.remote = true;
|
|
||||||
break;
|
|
||||||
case 0xDD: // const data commit
|
|
||||||
//piCout << "received commit";
|
|
||||||
state = Connected;
|
|
||||||
break;
|
|
||||||
case 0xEE: // dynamic data
|
|
||||||
//piCout << "received data" << ba.size_s();
|
|
||||||
piForeach (Tab & t, tabs)
|
|
||||||
piForeach (Column & c, t.columns)
|
|
||||||
piForeach (Variable & v, c.variables)
|
|
||||||
if (!v.isEmpty() && v.id > 0)
|
|
||||||
vids[v.id] = &v;
|
|
||||||
ba >> content;
|
|
||||||
piForeach (VariableContent & vc, content) {
|
|
||||||
if (vc.id <= 0) continue;
|
|
||||||
Variable * v = vids.at(vc.id);
|
|
||||||
if (v == 0) continue;
|
|
||||||
//piCout << "read" << v->name << vc.rdata.size_s();
|
|
||||||
v->rdata = vc.rdata;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void PIConsole::peerTimer(void * data, int delim) {
|
|
||||||
if (peer == 0) return;
|
|
||||||
//piCout << "timer" << delim;
|
|
||||||
if (server_mode) {
|
|
||||||
if (delim == 20)
|
|
||||||
serverSendInfo();
|
|
||||||
else
|
|
||||||
serverSendData();
|
|
||||||
} else {
|
|
||||||
if (delim != 1 || server_name.isEmpty()) return;
|
|
||||||
const PIPeer::PeerInfo * p = peer->getPeerByName("_rcs_:" + server_name);
|
|
||||||
if (p == 0) return;
|
|
||||||
PIByteArray ba;
|
|
||||||
switch (state) {
|
|
||||||
case Disconnected:
|
|
||||||
peer_tm.reset();
|
|
||||||
ba << int(0xBB);
|
|
||||||
//piCout << "send to" << server_name << "fetch request disc";
|
|
||||||
peer->send(p, ba);
|
|
||||||
state = FetchingData;
|
|
||||||
break;
|
|
||||||
case FetchingData:
|
|
||||||
if (peer_tm.elapsed_s() < 3.)
|
|
||||||
return;
|
|
||||||
peer_tm.reset();
|
|
||||||
ba << int(0xBB);
|
|
||||||
//piCout << "send to" << server_name << "fetch request fd";
|
|
||||||
peer->send(p, ba);
|
|
||||||
break;
|
|
||||||
case Committing:
|
|
||||||
peer_tm.reset();
|
|
||||||
ba << int(0xCC);
|
|
||||||
//piCout << "send to" << server_name << "committing";
|
|
||||||
state = Connected;
|
|
||||||
peer->send(p, ba);
|
|
||||||
break;
|
|
||||||
default: break;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void PIConsole::peerDisconnectedEvent(const PIString & name) {
|
|
||||||
for (int i = 0; i < remote_clients.size_s(); ++i)
|
|
||||||
if (remote_clients[i].name == name) {
|
|
||||||
remote_clients.remove(i);
|
|
||||||
--i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
/*
|
|
||||||
PIP - Platform Independent Primitives
|
|
||||||
|
|
||||||
Stephan Fomenko
|
|
||||||
|
|
||||||
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 PICONDITIONLOCK_H
|
|
||||||
#define PICONDITIONLOCK_H
|
|
||||||
|
|
||||||
#include "pibase.h"
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Continued
|
|
||||||
*/
|
|
||||||
class PIP_EXPORT PIConditionLock {
|
|
||||||
public:
|
|
||||||
NO_COPY_CLASS(PIConditionLock)
|
|
||||||
explicit PIConditionLock();
|
|
||||||
~PIConditionLock();
|
|
||||||
|
|
||||||
//! \brief lock
|
|
||||||
void lock();
|
|
||||||
|
|
||||||
//! \brief unlock
|
|
||||||
void unlock();
|
|
||||||
|
|
||||||
//! \brief tryLock
|
|
||||||
bool tryLock();
|
|
||||||
|
|
||||||
void * handle();
|
|
||||||
|
|
||||||
private:
|
|
||||||
PRIVATE_DECLARATION
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif // PICONDITIONLOCK_H
|
|
||||||
@@ -1,461 +0,0 @@
|
|||||||
/*! \file piconsole.h
|
|
||||||
* \brief Console output class
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
PIP - Platform Independent Primitives
|
|
||||||
Console output/input
|
|
||||||
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 PICONSOLE_H
|
|
||||||
#define PICONSOLE_H
|
|
||||||
|
|
||||||
#include "pikbdlistener.h"
|
|
||||||
|
|
||||||
class PIProtocol;
|
|
||||||
class PIDiagnostics;
|
|
||||||
class PISystemMonitor;
|
|
||||||
class PIPeer;
|
|
||||||
class PITimer;
|
|
||||||
|
|
||||||
class PIP_EXPORT PIConsole: public PIThread
|
|
||||||
{
|
|
||||||
PIOBJECT_SUBCLASS(PIConsole, PIThread)
|
|
||||||
public:
|
|
||||||
|
|
||||||
//! Constructs %PIConsole with key handler "slot" and if "startNow" start it
|
|
||||||
explicit PIConsole(bool startNow = true, PIKbdListener::KBFunc slot = 0);
|
|
||||||
|
|
||||||
~PIConsole();
|
|
||||||
|
|
||||||
|
|
||||||
//! Variables output format
|
|
||||||
enum Format {
|
|
||||||
Normal /** Default console format */ = 0x01,
|
|
||||||
Bold /** Bold text */ = 0x02,
|
|
||||||
Faint = 0x04,
|
|
||||||
Italic = 0x08,
|
|
||||||
Underline /** Underlined text */ = 0x10,
|
|
||||||
Blink /** Blinked text */ = 0x20,
|
|
||||||
Inverse /** Swap text and background colors */ = 0x40,
|
|
||||||
Black /** Black text */ = 0x100,
|
|
||||||
Red /** Red text */ = 0x200,
|
|
||||||
Green /** Green text */ = 0x400,
|
|
||||||
Yellow /** Yellow text */ = 0x800,
|
|
||||||
Blue /** Blue text */ = 0x1000,
|
|
||||||
Magenta /** Magenta text */ = 0x2000,
|
|
||||||
Cyan /** Cyan text */ = 0x4000,
|
|
||||||
White /** White text */ = 0x8000,
|
|
||||||
BackBlack /** Black background */ = 0x10000,
|
|
||||||
BackRed /** Red background */ = 0x20000,
|
|
||||||
BackGreen /** Green background */ = 0x40000,
|
|
||||||
BackYellow /** Yellow background */ = 0x80000,
|
|
||||||
BackBlue /** Blue background */ = 0x100000,
|
|
||||||
BackMagenta /** Magenta background */ = 0x200000,
|
|
||||||
BackCyan /** Cyan background */ = 0x400000,
|
|
||||||
BackWhite /** White background */ = 0x800000,
|
|
||||||
Dec /** Decimal base for integers */ = 0x1000000,
|
|
||||||
Hex /** Hexadecimal base for integers */ = 0x2000000,
|
|
||||||
Oct /** Octal base for integers */ = 0x4000000,
|
|
||||||
Bin /** Binary base for integers */ = 0x8000000,
|
|
||||||
Scientific /** Scientific representation of floats */ = 0x10000000,
|
|
||||||
SystemTimeSplit /** PISystemTime split representation (* s, * ns) */ = 0x20000000,
|
|
||||||
SystemTimeSeconds /** PISystemTime seconds representation (*.* s) */ = 0x40000000
|
|
||||||
};
|
|
||||||
|
|
||||||
//! Column labels alignment
|
|
||||||
enum Alignment {
|
|
||||||
Nothing /** No alignment */ ,
|
|
||||||
Left /** Labels align left and variables align left */ ,
|
|
||||||
Right /** Labels align right and variables align left */
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef PIFlags<PIConsole::Format> FormatFlags;
|
|
||||||
|
|
||||||
//! Add to current tab to column "column" string "name" with format "format"
|
|
||||||
void addString(const PIString & name, int column = 1, FormatFlags format = PIConsole::Normal);
|
|
||||||
|
|
||||||
//! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format"
|
|
||||||
void addVariable(const PIString & name, const PIString * ptr, int column = 1, FormatFlags format = PIConsole::Normal);
|
|
||||||
|
|
||||||
//! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format"
|
|
||||||
void addVariable(const PIString & name, const char * ptr, int column = 1, FormatFlags format = PIConsole::Normal);
|
|
||||||
|
|
||||||
//! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format"
|
|
||||||
void addVariable(const PIString & name, const bool * ptr, int column = 1, FormatFlags format = PIConsole::Normal);
|
|
||||||
|
|
||||||
//! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format"
|
|
||||||
void addVariable(const PIString & name, const short * ptr, int column = 1, FormatFlags format = PIConsole::Normal);
|
|
||||||
|
|
||||||
//! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format"
|
|
||||||
void addVariable(const PIString & name, const int * ptr, int column = 1, FormatFlags format = PIConsole::Normal);
|
|
||||||
|
|
||||||
//! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format"
|
|
||||||
void addVariable(const PIString & name, const long * ptr, int column = 1, FormatFlags format = PIConsole::Normal);
|
|
||||||
|
|
||||||
//! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format"
|
|
||||||
void addVariable(const PIString & name, const llong * ptr, int column = 1, FormatFlags format = PIConsole::Normal);
|
|
||||||
|
|
||||||
//! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format"
|
|
||||||
void addVariable(const PIString & name, const uchar * ptr, int column = 1, FormatFlags format = PIConsole::Normal);
|
|
||||||
|
|
||||||
//! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format"
|
|
||||||
void addVariable(const PIString & name, const ushort * ptr, int column = 1, FormatFlags format = PIConsole::Normal);
|
|
||||||
|
|
||||||
//! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format"
|
|
||||||
void addVariable(const PIString & name, const uint * ptr, int column = 1, FormatFlags format = PIConsole::Normal);
|
|
||||||
|
|
||||||
//! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format"
|
|
||||||
void addVariable(const PIString & name, const ulong * ptr, int column = 1, FormatFlags format = PIConsole::Normal);
|
|
||||||
|
|
||||||
//! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format"
|
|
||||||
void addVariable(const PIString & name, const ullong * ptr, int column = 1, FormatFlags format = PIConsole::Normal);
|
|
||||||
|
|
||||||
//! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format"
|
|
||||||
void addVariable(const PIString & name, const float * ptr, int column = 1, FormatFlags format = PIConsole::Normal);
|
|
||||||
|
|
||||||
//! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format"
|
|
||||||
void addVariable(const PIString & name, const double * ptr, int column = 1, FormatFlags format = PIConsole::Normal);
|
|
||||||
|
|
||||||
//! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format"
|
|
||||||
void addVariable(const PIString & name, const PISystemTime * ptr, int column = 1, FormatFlags format = PIConsole::Normal);
|
|
||||||
|
|
||||||
void addVariable(const PIString & name, const PIDiagnostics * ptr, int column = 1, FormatFlags format = PIConsole::Normal);
|
|
||||||
void addVariable(const PIString & name, const PISystemMonitor * ptr, int column = 1, FormatFlags format = PIConsole::Normal);
|
|
||||||
|
|
||||||
//! Add to current tab to column "column" bits field with label "name", pointer "ptr" and format "format"
|
|
||||||
void addBitVariable(const PIString & name, const void * ptr, int fromBit, int bitsCount, int column = 1, FormatFlags format = PIConsole::Normal);
|
|
||||||
|
|
||||||
//! Add to current tab to column "column" "count" empty lines
|
|
||||||
void addEmptyLine(int column = 1, uint count = 1);
|
|
||||||
|
|
||||||
PIString getString(int x, int y);
|
|
||||||
short getShort(int x, int y) {return getString(x, y).toShort();}
|
|
||||||
int getInt(int x, int y) {return getString(x, y).toInt();}
|
|
||||||
float getFloat(int x, int y) {return getString(x, y).toFloat();}
|
|
||||||
double getDouble(int x, int y) {return getString(x, y).toDouble();}
|
|
||||||
PIString getString(const PIString & name);
|
|
||||||
short getShort(const PIString & name) {return getString(name).toShort();}
|
|
||||||
int getInt(const PIString & name) {return getString(name).toInt();}
|
|
||||||
float getFloat(const PIString & name) {return getString(name).toFloat();}
|
|
||||||
double getDouble(const PIString & name) {return getString(name).toDouble();}
|
|
||||||
|
|
||||||
|
|
||||||
//! Returns tabs count
|
|
||||||
uint tabsCount() const {return tabs.size();}
|
|
||||||
|
|
||||||
//! Returns current tab name
|
|
||||||
PIString currentTab() const {return tabs[cur_tab].name;}
|
|
||||||
|
|
||||||
//! Returns current tab index
|
|
||||||
int currentTabIndex() const {return cur_tab;}
|
|
||||||
|
|
||||||
//! Add new tab with name "name", bind key "bind_key" and returns this tab index
|
|
||||||
int addTab(const PIString & name, char bind_key = 0);
|
|
||||||
|
|
||||||
//! Remove tab with index "index"
|
|
||||||
void removeTab(uint index);
|
|
||||||
|
|
||||||
//! Remove tab with name "name"
|
|
||||||
void removeTab(const PIString & name);
|
|
||||||
|
|
||||||
//! Clear content of tab with index "index"
|
|
||||||
void clearTab(uint index);
|
|
||||||
|
|
||||||
//! Clear content of tab with name "name"
|
|
||||||
void clearTab(const PIString & name);
|
|
||||||
|
|
||||||
//! Set current tab to tab with index "index", returns if tab exists
|
|
||||||
bool setTab(uint index);
|
|
||||||
|
|
||||||
//! Set current tab to tab with name "name", returns if tab exists
|
|
||||||
bool setTab(const PIString & name);
|
|
||||||
|
|
||||||
//! Set tab with index "index" bind key to "bind_key", returns if tab exists
|
|
||||||
bool setTabBindKey(uint index, char bind_key);
|
|
||||||
|
|
||||||
//! Set tab with name "name" bind key to "bind_key", returns if tab exists
|
|
||||||
bool setTabBindKey(const PIString & name, char bind_key);
|
|
||||||
|
|
||||||
//! Remove all tabs and if "clearScreen" clear the screen
|
|
||||||
void clearTabs(bool clearScreen = true) {if (clearScreen && isRunning()) {toUpperLeft(); clearScreenLower();} tabs.clear();}
|
|
||||||
|
|
||||||
|
|
||||||
//! Set custom status text of current tab to "str"
|
|
||||||
void addCustomStatus(const PIString & str) {tabs[cur_tab].status = str;}
|
|
||||||
|
|
||||||
//! Clear custom status text of current tab
|
|
||||||
void clearCustomStatus() {tabs[cur_tab].status.clear();}
|
|
||||||
|
|
||||||
//! Returns default alignment
|
|
||||||
Alignment defaultAlignment() const {return def_align;}
|
|
||||||
|
|
||||||
//! Set default alignment to "align"
|
|
||||||
void setDefaultAlignment(Alignment align) {def_align = align;}
|
|
||||||
|
|
||||||
//! Set column "col" alignment to "align"
|
|
||||||
void setColumnAlignment(int col, Alignment align) {if (col < 0 || col >= columns().size_s()) return; column(col).alignment = align;}
|
|
||||||
|
|
||||||
//! Set all columns of all tabs alignment to "align"
|
|
||||||
void setColumnAlignmentToAll(Alignment align) {piForeach (Tab & i, tabs) piForeach (Column & j, i.columns) j.alignment = align; fillLabels();}
|
|
||||||
|
|
||||||
|
|
||||||
//! Directly call function from \a PIKbdListener
|
|
||||||
void enableExitCapture(char key = 'Q') {listener->enableExitCapture(key);}
|
|
||||||
|
|
||||||
//! Directly call function from \a PIKbdListener
|
|
||||||
void disableExitCapture() {listener->disableExitCapture();}
|
|
||||||
|
|
||||||
//! Directly call function from \a PIKbdListener
|
|
||||||
bool exitCaptured() const {return listener->exitCaptured();}
|
|
||||||
|
|
||||||
//! Directly call function from \a PIKbdListener
|
|
||||||
char exitKey() const {return listener->exitKey();}
|
|
||||||
|
|
||||||
|
|
||||||
int windowWidth() const {return width;}
|
|
||||||
int windowHeight() const {return height;}
|
|
||||||
|
|
||||||
PIString fstr(FormatFlags f);
|
|
||||||
void update();
|
|
||||||
void pause(bool yes) {pause_ = yes;}
|
|
||||||
|
|
||||||
// Server functions
|
|
||||||
void startServer(const PIString & name);
|
|
||||||
void stopPeer();
|
|
||||||
bool isServerStarted() const {return peer != 0;}
|
|
||||||
PIStringList clients() const;
|
|
||||||
|
|
||||||
// Client functions
|
|
||||||
void listenServers();
|
|
||||||
PIStringList availableServers() const;
|
|
||||||
PIString selectedServer() const {return server_name;}
|
|
||||||
void connectToServer(const PIString & name);
|
|
||||||
void disconnect();
|
|
||||||
bool isConnected() const {return state == Connected;}
|
|
||||||
|
|
||||||
void toUpperLeft();
|
|
||||||
void moveRight(int n = 1);
|
|
||||||
void moveLeft(int n = 1);
|
|
||||||
void moveTo(int x = 0, int y = 0);
|
|
||||||
void clearScreen();
|
|
||||||
void clearScreenLower();
|
|
||||||
void clearLine();
|
|
||||||
void newLine();
|
|
||||||
void hideCursor();
|
|
||||||
void showCursor();
|
|
||||||
|
|
||||||
EVENT_HANDLER0(void, clearVariables) {clearVariables(true);}
|
|
||||||
EVENT_HANDLER1(void, clearVariables, bool, clearScreen);
|
|
||||||
|
|
||||||
EVENT_HANDLER0(void, waitForFinish) {WAIT_FOR_EXIT}
|
|
||||||
EVENT_HANDLER0(void, start) {start(false);}
|
|
||||||
EVENT_HANDLER1(void, start, bool, wait) {PIThread::start(40); if (wait) waitForFinish();}
|
|
||||||
EVENT_HANDLER0(void, stop) {stop(false);}
|
|
||||||
EVENT_HANDLER1(void, stop, bool, clear);
|
|
||||||
|
|
||||||
EVENT2(keyPressed, PIKbdListener::KeyEvent, key, void * , data)
|
|
||||||
|
|
||||||
//! \handlers
|
|
||||||
//! \{
|
|
||||||
|
|
||||||
//! \fn void waitForFinish()
|
|
||||||
//! \brief block until finished (exit key will be pressed)
|
|
||||||
|
|
||||||
//! \fn void clearVariables(bool clearScreen = true)
|
|
||||||
//! \brief Remove all columns at current tab and if "clearScreen" clear the screen
|
|
||||||
|
|
||||||
//! \fn void start(bool wait = false)
|
|
||||||
//! \brief Start console output and if "wait" block until finished (exit key will be pressed)
|
|
||||||
|
|
||||||
//! \fn void stop(bool clear = false)
|
|
||||||
//! \brief Stop console output and if "clear" clear the screen
|
|
||||||
|
|
||||||
//! \}
|
|
||||||
//! \events
|
|
||||||
//! \{
|
|
||||||
|
|
||||||
//! \fn void keyPressed(PIKbdListener::KeyEvent key, void * data)
|
|
||||||
//! \brief Raise on key "key" pressed, "data" is pointer to %PIConsole object
|
|
||||||
|
|
||||||
//! \}
|
|
||||||
|
|
||||||
private:
|
|
||||||
void begin();
|
|
||||||
void run();
|
|
||||||
void fillLabels();
|
|
||||||
void status();
|
|
||||||
void checkColumn(uint col) {while (columns().size() < col) columns().push_back(Column(def_align));}
|
|
||||||
int bitsValue(const void * src, int offset, int count) const;
|
|
||||||
const char * toBin(const void * d, int s);
|
|
||||||
inline void printLine(const PIString & str, int dx = 0, FormatFlags format = PIConsole::Normal);
|
|
||||||
inline int printValue(const PIString & str, FormatFlags format = PIConsole::Normal);
|
|
||||||
inline int printValue(const char * str, FormatFlags format = PIConsole::Normal);
|
|
||||||
inline int printValue(const bool value, FormatFlags format = PIConsole::Normal);
|
|
||||||
inline int printValue(const int value, FormatFlags format = PIConsole::Normal);
|
|
||||||
inline int printValue(const long value, FormatFlags format = PIConsole::Normal);
|
|
||||||
inline int printValue(const llong value, FormatFlags format = PIConsole::Normal);
|
|
||||||
inline int printValue(const float value, FormatFlags format = PIConsole::Normal);
|
|
||||||
inline int printValue(const double value, FormatFlags format = PIConsole::Normal);
|
|
||||||
inline int printValue(const char value, FormatFlags format = PIConsole::Normal);
|
|
||||||
inline int printValue(const short value, FormatFlags format = PIConsole::Normal);
|
|
||||||
inline int printValue(const uchar value, FormatFlags format = PIConsole::Normal);
|
|
||||||
inline int printValue(const ushort value, FormatFlags format = PIConsole::Normal);
|
|
||||||
inline int printValue(const uint value, FormatFlags format = PIConsole::Normal);
|
|
||||||
inline int printValue(const ulong value, FormatFlags format = PIConsole::Normal);
|
|
||||||
inline int printValue(const ullong value, FormatFlags format = PIConsole::Normal);
|
|
||||||
inline int printValue(const PISystemTime & value, FormatFlags format = PIConsole::Normal);
|
|
||||||
static void key_event(PIKbdListener::KeyEvent key, void * t);
|
|
||||||
|
|
||||||
struct Variable {
|
|
||||||
Variable() {nx = ny = type = offset = bitFrom = bitCount = size = 0; format = Normal; remote = false; ptr = 0; id = 1;}
|
|
||||||
Variable(const Variable & src) {remote = src.remote; name = src.name; format = src.format; type = src.type; offset = src.offset; size = src.size;
|
|
||||||
bitFrom = src.bitFrom; bitCount = src.bitCount; ptr = src.ptr; nx = src.nx; ny = src.ny; rdata = src.rdata; id = src.id;}
|
|
||||||
bool isEmpty() const {return (remote ? false : ptr == 0);}
|
|
||||||
const void * data() {return (remote ? rdata.data() : ptr);}
|
|
||||||
void writeData(PIByteArray & ba) {
|
|
||||||
if (remote) ba << rdata;
|
|
||||||
else {
|
|
||||||
if (type == 0) ba << (*(PIString * )ptr);
|
|
||||||
else ba << PIByteArray::RawData(ptr, size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
PIString name;
|
|
||||||
FormatFlags format;
|
|
||||||
int nx;
|
|
||||||
int ny;
|
|
||||||
int type;
|
|
||||||
int offset;
|
|
||||||
int bitFrom;
|
|
||||||
int bitCount;
|
|
||||||
int size;
|
|
||||||
int id;
|
|
||||||
bool remote;
|
|
||||||
const void * ptr;
|
|
||||||
PIByteArray rdata;
|
|
||||||
void operator =(const Variable & src) {remote = src.remote; name = src.name; format = src.format; type = src.type; offset = src.offset; size = src.size;
|
|
||||||
bitFrom = src.bitFrom; bitCount = src.bitCount; ptr = src.ptr; nx = src.nx; ny = src.ny; rdata = src.rdata; id = src.id;}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct VariableContent {
|
|
||||||
int id;
|
|
||||||
PIByteArray rdata;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Column {
|
|
||||||
Column(Alignment align = PIConsole::Right) {variables.reserve(32); alignment = align;}
|
|
||||||
PIVector<Variable> variables;
|
|
||||||
Alignment alignment;
|
|
||||||
uint size() const {return variables.size();}
|
|
||||||
Variable & operator [](int index) {return variables[index];}
|
|
||||||
const Variable & operator [](int index) const {return variables[index];}
|
|
||||||
void push_back(const Variable & v) {variables.push_back(v);}
|
|
||||||
void operator =(const Column & src) {variables = src.variables; alignment = src.alignment;}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Tab {
|
|
||||||
Tab(PIString n = "", char k = 0) {columns.reserve(8); name = n; key = k;}
|
|
||||||
PIVector<Column> columns;
|
|
||||||
PIString name;
|
|
||||||
PIString status;
|
|
||||||
char key;
|
|
||||||
};
|
|
||||||
|
|
||||||
enum ConnectedState {Disconnected, FetchingData, Committing, Connected};
|
|
||||||
|
|
||||||
friend PIByteArray & operator <<(PIByteArray & ba, const PIConsole::VariableContent & v);
|
|
||||||
friend PIByteArray & operator >>(PIByteArray & ba, PIConsole::VariableContent & v);
|
|
||||||
|
|
||||||
friend PIByteArray & operator <<(PIByteArray & ba, const PIConsole::Variable & v);
|
|
||||||
friend PIByteArray & operator >>(PIByteArray & ba, PIConsole::Variable & v);
|
|
||||||
|
|
||||||
friend PIByteArray & operator <<(PIByteArray & ba, const PIConsole::Column & v);
|
|
||||||
friend PIByteArray & operator >>(PIByteArray & ba, PIConsole::Column & v);
|
|
||||||
|
|
||||||
friend PIByteArray & operator <<(PIByteArray & ba, const PIConsole::Tab & v);
|
|
||||||
friend PIByteArray & operator >>(PIByteArray & ba, PIConsole::Tab & v);
|
|
||||||
|
|
||||||
PIVector<Column> & columns() {return tabs[cur_tab].columns;}
|
|
||||||
Column & column(int index) {return tabs[cur_tab].columns[index - 1];}
|
|
||||||
int couts(const PIString & v);
|
|
||||||
int couts(const char * v);
|
|
||||||
int couts(const bool v);
|
|
||||||
int couts(const char v);
|
|
||||||
int couts(const short v);
|
|
||||||
int couts(const int v);
|
|
||||||
int couts(const long v);
|
|
||||||
int couts(const llong v);
|
|
||||||
int couts(const uchar v);
|
|
||||||
int couts(const ushort v);
|
|
||||||
int couts(const uint v);
|
|
||||||
int couts(const ulong v);
|
|
||||||
int couts(const ullong v);
|
|
||||||
int couts(const float v);
|
|
||||||
int couts(const double v);
|
|
||||||
int couts(const PISystemTime & v);
|
|
||||||
|
|
||||||
struct RemoteClient;
|
|
||||||
|
|
||||||
void serverSendInfo();
|
|
||||||
void serverSendData();
|
|
||||||
RemoteClient & remoteClient(const PIString & fname);
|
|
||||||
EVENT_HANDLER2(void, peerReceived, const PIString &, from, const PIByteArray &, data);
|
|
||||||
EVENT_HANDLER2(void, peerTimer, void * , data, int, delim);
|
|
||||||
EVENT_HANDLER1(void, peerDisconnectedEvent, const PIString &, name);
|
|
||||||
|
|
||||||
PRIVATE_DECLARATION
|
|
||||||
PIVector<Tab> tabs;
|
|
||||||
PIString binstr, rstr;
|
|
||||||
PIByteArray rba;
|
|
||||||
Variable tv;
|
|
||||||
PIKbdListener * listener;
|
|
||||||
Alignment def_align;
|
|
||||||
PIKbdListener::KBFunc ret_func;
|
|
||||||
int width, height, pwidth, pheight, col_wid, num_format, systime_format;
|
|
||||||
uint max_y;
|
|
||||||
int vid;
|
|
||||||
uint cur_tab, col_cnt;
|
|
||||||
|
|
||||||
PIPeer * peer;
|
|
||||||
PITimer * peer_timer;
|
|
||||||
PITimeMeasurer peer_tm;
|
|
||||||
PIString server_name;
|
|
||||||
bool server_mode, pause_;
|
|
||||||
ConnectedState state;
|
|
||||||
|
|
||||||
struct RemoteClient {
|
|
||||||
RemoteClient(const PIString & n = "") {name = n; state = Disconnected;}
|
|
||||||
PIString name;
|
|
||||||
ConnectedState state;
|
|
||||||
};
|
|
||||||
|
|
||||||
PIVector<RemoteClient> remote_clients;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
inline PIByteArray & operator <<(PIByteArray & ba, const PIConsole::VariableContent & v) {ba << v.id << v.rdata; return ba;}
|
|
||||||
inline PIByteArray & operator >>(PIByteArray & ba, PIConsole::VariableContent & v) {ba >> v.id; ba >> v.rdata; return ba;}
|
|
||||||
|
|
||||||
inline PIByteArray & operator <<(PIByteArray & ba, const PIConsole::Variable & v) {ba << v.name << v.id << (int)v.format << v.type << v.size << v.bitFrom << v.bitCount; return ba;}
|
|
||||||
inline PIByteArray & operator >>(PIByteArray & ba, PIConsole::Variable & v) {ba >> v.name >> v.id >> (int & )v.format >> v.type >> v.size >> v.bitFrom >> v.bitCount; return ba;}
|
|
||||||
|
|
||||||
inline PIByteArray & operator <<(PIByteArray & ba, const PIConsole::Column & v) {ba << (int)v.alignment << v.variables; return ba;}
|
|
||||||
inline PIByteArray & operator >>(PIByteArray & ba, PIConsole::Column & v) {int a; ba >> a >> v.variables; v.alignment = (PIConsole::Alignment)a; return ba;}
|
|
||||||
|
|
||||||
inline PIByteArray & operator <<(PIByteArray & ba, const PIConsole::Tab & v) {ba << v.name << v.status << (uchar)v.key << v.columns; return ba;}
|
|
||||||
inline PIByteArray & operator >>(PIByteArray & ba, PIConsole::Tab & v) {ba >> v.name >> v.status >> (uchar&)v.key >> v.columns; return ba;}
|
|
||||||
|
|
||||||
#endif // PICONSOLE_H
|
|
||||||
@@ -21,7 +21,6 @@
|
|||||||
#define PICONSOLEMODULE_H
|
#define PICONSOLEMODULE_H
|
||||||
|
|
||||||
#include "pikbdlistener.h"
|
#include "pikbdlistener.h"
|
||||||
#include "piconsole.h"
|
|
||||||
#include "piscreen.h"
|
#include "piscreen.h"
|
||||||
#include "piscreentiles.h"
|
#include "piscreentiles.h"
|
||||||
|
|
||||||
|
|||||||
@@ -49,6 +49,9 @@ public:
|
|||||||
PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T))
|
PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T))
|
||||||
resize(pid_size, f);
|
resize(pid_size, f);
|
||||||
}
|
}
|
||||||
|
inline PIDeque(PIDeque<T> && other): pid_data(0), pid_size(0), pid_rsize(0), pid_start(0) {
|
||||||
|
swap(other);
|
||||||
|
}
|
||||||
inline virtual ~PIDeque() {
|
inline virtual ~PIDeque() {
|
||||||
//piCout << "~PIDeque";
|
//piCout << "~PIDeque";
|
||||||
PIINTROSPECTION_CONTAINER_DELETE(T)
|
PIINTROSPECTION_CONTAINER_DELETE(T)
|
||||||
@@ -66,6 +69,12 @@ public:
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline PIDeque<T> & operator =(PIDeque<T> && other) {
|
||||||
|
if (this == &other) return *this;
|
||||||
|
swap(other);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
typedef T value_type;
|
typedef T value_type;
|
||||||
|
|
||||||
class iterator {
|
class iterator {
|
||||||
@@ -256,6 +265,23 @@ public:
|
|||||||
elementNew(pid_data + pid_start + index, v);
|
elementNew(pid_data + pid_start + index, v);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
inline PIDeque<T> & insert(size_t index, T && v) {
|
||||||
|
bool dir = pid_rsize <= 2 ? true : (index >= pid_rsize / 2 ? true : false);
|
||||||
|
if (dir) {
|
||||||
|
alloc(pid_size + 1, true);
|
||||||
|
if (index < pid_size - 1) {
|
||||||
|
size_t os = pid_size - index - 1;
|
||||||
|
memmove((void*)(&(pid_data[index + pid_start + 1])), (const void*)(&(pid_data[index + pid_start])), os * sizeof(T));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
alloc(pid_size + 1, false, -1);
|
||||||
|
if (index > 0)
|
||||||
|
memmove((void*)(&(pid_data[pid_start])), (const void*)(&(pid_data[pid_start + 1])), index * sizeof(T));
|
||||||
|
}
|
||||||
|
PIINTROSPECTION_CONTAINER_USED(T, 1)
|
||||||
|
elementNew(pid_data + pid_start + index, v);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
inline PIDeque<T> & insert(size_t index, const PIDeque<T> & other) {
|
inline PIDeque<T> & insert(size_t index, const PIDeque<T> & other) {
|
||||||
if (other.isEmpty()) return *this;
|
if (other.isEmpty()) return *this;
|
||||||
assert(&other != this);
|
assert(&other != this);
|
||||||
@@ -336,7 +362,14 @@ public:
|
|||||||
elementNew(pid_data + pid_start + pid_size - 1, v);
|
elementNew(pid_data + pid_start + pid_size - 1, v);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
inline PIDeque<T> & push_back(T && v) {
|
||||||
|
alloc(pid_size + 1, true);
|
||||||
|
PIINTROSPECTION_CONTAINER_USED(T, 1);
|
||||||
|
elementNew(pid_data + pid_start + pid_size - 1, v);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
inline PIDeque<T> & append(const T & v) {return push_back(v);}
|
inline PIDeque<T> & append(const T & v) {return push_back(v);}
|
||||||
|
inline PIDeque<T> & append(T && v) {return push_back(v);}
|
||||||
inline PIDeque<T> & append(const PIDeque<T> & t) {
|
inline PIDeque<T> & append(const PIDeque<T> & t) {
|
||||||
assert(&t != this);
|
assert(&t != this);
|
||||||
size_t ps = pid_size;
|
size_t ps = pid_size;
|
||||||
@@ -345,6 +378,7 @@ public:
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
inline PIDeque<T> & operator <<(const T & v) {return push_back(v);}
|
inline PIDeque<T> & operator <<(const T & v) {return push_back(v);}
|
||||||
|
inline PIDeque<T> & operator <<(T && v) {return push_back(v);}
|
||||||
inline PIDeque<T> & operator <<(const PIDeque<T> & t) {return append(t);}
|
inline PIDeque<T> & operator <<(const PIDeque<T> & t) {return append(t);}
|
||||||
|
|
||||||
inline PIDeque<T> & push_front(const T & v) {insert(0, v); return *this;}
|
inline PIDeque<T> & push_front(const T & v) {insert(0, v); return *this;}
|
||||||
@@ -412,6 +446,7 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
inline void elementNew(T * to, const T & from) {new(to)T(from);}
|
inline void elementNew(T * to, const T & from) {new(to)T(from);}
|
||||||
|
inline void elementNew(T * to, T && from) {piSwap(*to, from);}
|
||||||
inline void elementDelete(T & from) {from.~T();}
|
inline void elementDelete(T & from) {from.~T();}
|
||||||
inline void dealloc() {
|
inline void dealloc() {
|
||||||
if ((uchar*)pid_data != 0) free((uchar*)pid_data);
|
if ((uchar*)pid_data != 0) free((uchar*)pid_data);
|
||||||
@@ -485,6 +520,7 @@ private:
|
|||||||
template<> inline void PIDeque<T>::newT(T * dst, const T * src, size_t s) {PIINTROSPECTION_CONTAINER_USED(T, s); memcpy((void*)(dst), (const void*)(src), s * sizeof(T));} \
|
template<> inline void PIDeque<T>::newT(T * dst, const T * src, size_t s) {PIINTROSPECTION_CONTAINER_USED(T, s); memcpy((void*)(dst), (const void*)(src), s * sizeof(T));} \
|
||||||
template<> inline void PIDeque<T>::deleteT(T *, size_t sz) {PIINTROSPECTION_CONTAINER_UNUSED(T, sz);} \
|
template<> inline void PIDeque<T>::deleteT(T *, size_t sz) {PIINTROSPECTION_CONTAINER_UNUSED(T, sz);} \
|
||||||
template<> inline void PIDeque<T>::elementNew(T * to, const T & from) {(*to) = from;} \
|
template<> inline void PIDeque<T>::elementNew(T * to, const T & from) {(*to) = from;} \
|
||||||
|
template<> inline void PIDeque<T>::elementNew(T * to, T && from) {(*to) = from;} \
|
||||||
template<> inline void PIDeque<T>::elementDelete(T &) {;} \
|
template<> inline void PIDeque<T>::elementDelete(T &) {;} \
|
||||||
template<> inline PIDeque<T> & PIDeque<T>::_resizeRaw(size_t new_size) { \
|
template<> inline PIDeque<T> & PIDeque<T>::_resizeRaw(size_t new_size) { \
|
||||||
if (new_size > pid_size) { \
|
if (new_size > pid_size) { \
|
||||||
|
|||||||
@@ -74,6 +74,7 @@ class PIMap {
|
|||||||
public:
|
public:
|
||||||
PIMap() {;}
|
PIMap() {;}
|
||||||
PIMap(const PIMap<Key, T> & other) {*this = other;}
|
PIMap(const PIMap<Key, T> & other) {*this = other;}
|
||||||
|
PIMap(PIMap<Key, T> && other) {swap(other);}
|
||||||
virtual ~PIMap() {;}
|
virtual ~PIMap() {;}
|
||||||
|
|
||||||
PIMap<Key, T> & operator =(const PIMap<Key, T> & other) {
|
PIMap<Key, T> & operator =(const PIMap<Key, T> & other) {
|
||||||
@@ -84,6 +85,12 @@ public:
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PIMap<Key, T> & operator =(PIMap<Key, T> && other) {
|
||||||
|
if (this == &other) return *this;
|
||||||
|
swap(other);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
typedef T mapped_type;
|
typedef T mapped_type;
|
||||||
typedef Key key_type;
|
typedef Key key_type;
|
||||||
typedef PIPair<Key, T> value_type;
|
typedef PIPair<Key, T> value_type;
|
||||||
|
|||||||
@@ -48,6 +48,9 @@ public:
|
|||||||
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(0), piv_size(0), piv_rsize(0) {
|
||||||
|
swap(other);
|
||||||
|
}
|
||||||
inline virtual ~PIVector() {
|
inline virtual ~PIVector() {
|
||||||
PIINTROSPECTION_CONTAINER_DELETE(T)
|
PIINTROSPECTION_CONTAINER_DELETE(T)
|
||||||
PIINTROSPECTION_CONTAINER_FREE(T, (piv_rsize))
|
PIINTROSPECTION_CONTAINER_FREE(T, (piv_rsize))
|
||||||
@@ -65,6 +68,12 @@ public:
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline PIVector<T> & operator =(PIVector<T> && other) {
|
||||||
|
if (this == &other) return *this;
|
||||||
|
swap(other);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
typedef T value_type;
|
typedef T value_type;
|
||||||
|
|
||||||
class iterator {
|
class iterator {
|
||||||
@@ -253,6 +262,16 @@ public:
|
|||||||
elementNew(piv_data + index, v);
|
elementNew(piv_data + index, v);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
inline PIVector<T> & insert(size_t index, T && v) {
|
||||||
|
alloc(piv_size + 1);
|
||||||
|
if (index < piv_size - 1) {
|
||||||
|
size_t os = piv_size - index - 1;
|
||||||
|
memmove((void*)(&(piv_data[index + 1])), (const void*)(&(piv_data[index])), os * sizeof(T));
|
||||||
|
}
|
||||||
|
PIINTROSPECTION_CONTAINER_USED(T, 1)
|
||||||
|
elementNew(piv_data + index, v);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
inline PIVector<T> & insert(size_t index, const PIVector<T> & other) {
|
inline PIVector<T> & insert(size_t index, const PIVector<T> & other) {
|
||||||
if (other.isEmpty()) return *this;
|
if (other.isEmpty()) return *this;
|
||||||
assert(&other != this);
|
assert(&other != this);
|
||||||
@@ -320,7 +339,14 @@ public:
|
|||||||
elementNew(piv_data + piv_size - 1, v);
|
elementNew(piv_data + piv_size - 1, v);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
inline PIVector<T> & push_back(T && v) {
|
||||||
|
alloc(piv_size + 1);
|
||||||
|
PIINTROSPECTION_CONTAINER_USED(T, 1);
|
||||||
|
elementNew(piv_data + piv_size - 1, v);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
inline PIVector<T> & append(const T & v) {return push_back(v);}
|
inline PIVector<T> & append(const T & v) {return push_back(v);}
|
||||||
|
inline PIVector<T> & append(T && v) {return push_back(v);}
|
||||||
inline PIVector<T> & append(const PIVector<T> & other) {
|
inline PIVector<T> & append(const PIVector<T> & other) {
|
||||||
assert(&other != this);
|
assert(&other != this);
|
||||||
size_t ps = piv_size;
|
size_t ps = piv_size;
|
||||||
@@ -329,6 +355,7 @@ public:
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
inline PIVector<T> & operator <<(const T & v) {return push_back(v);}
|
inline PIVector<T> & operator <<(const T & v) {return push_back(v);}
|
||||||
|
inline PIVector<T> & operator <<(T && v) {return push_back(v);}
|
||||||
inline PIVector<T> & operator <<(const PIVector<T> & other) {return append(other);}
|
inline PIVector<T> & operator <<(const PIVector<T> & other) {return append(other);}
|
||||||
|
|
||||||
inline PIVector<T> & push_front(const T & v) {insert(0, v); return *this;}
|
inline PIVector<T> & push_front(const T & v) {insert(0, v); return *this;}
|
||||||
@@ -405,6 +432,7 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
inline void elementNew(T * to, const T & from) {new(to)T(from);}
|
inline void elementNew(T * to, const T & from) {new(to)T(from);}
|
||||||
|
inline void elementNew(T * to, T && from) {piSwap(*to, from);}
|
||||||
inline void elementDelete(T & from) {from.~T();}
|
inline void elementDelete(T & from) {from.~T();}
|
||||||
inline void dealloc() {
|
inline void dealloc() {
|
||||||
if ((uchar*)piv_data != 0) free((uchar*)piv_data);
|
if ((uchar*)piv_data != 0) free((uchar*)piv_data);
|
||||||
@@ -434,6 +462,7 @@ private:
|
|||||||
template<> inline void PIVector<T>::newT(T * dst, const T * src, size_t s) {PIINTROSPECTION_CONTAINER_USED(T, s); memcpy((void*)(dst), (const void*)(src), s * sizeof(T));} \
|
template<> inline void PIVector<T>::newT(T * dst, const T * src, size_t s) {PIINTROSPECTION_CONTAINER_USED(T, s); memcpy((void*)(dst), (const void*)(src), s * sizeof(T));} \
|
||||||
template<> inline void PIVector<T>::deleteT(T *, size_t sz) {PIINTROSPECTION_CONTAINER_UNUSED(T, sz);} \
|
template<> inline void PIVector<T>::deleteT(T *, size_t sz) {PIINTROSPECTION_CONTAINER_UNUSED(T, sz);} \
|
||||||
template<> inline void PIVector<T>::elementNew(T * to, const T & from) {(*to) = from;} \
|
template<> inline void PIVector<T>::elementNew(T * to, const T & from) {(*to) = from;} \
|
||||||
|
template<> inline void PIVector<T>::elementNew(T * to, T && from) {(*to) = from;} \
|
||||||
template<> inline void PIVector<T>::elementDelete(T &) {;} \
|
template<> inline void PIVector<T>::elementDelete(T &) {;} \
|
||||||
template<> inline PIVector<T> & PIVector<T>::_resizeRaw(size_t new_size) { \
|
template<> inline PIVector<T> & PIVector<T>::_resizeRaw(size_t new_size) { \
|
||||||
if (new_size > piv_size) { \
|
if (new_size > piv_size) { \
|
||||||
|
|||||||
@@ -18,9 +18,9 @@
|
|||||||
*/
|
*/
|
||||||
#include "piincludes_p.h"
|
#include "piincludes_p.h"
|
||||||
#include "picout.h"
|
#include "picout.h"
|
||||||
#include "piconsole.h"
|
|
||||||
#include "pibytearray.h"
|
#include "pibytearray.h"
|
||||||
#include "pistack.h"
|
#include "pistack.h"
|
||||||
|
#include "piobject.h"
|
||||||
#include "pistring_std.h"
|
#include "pistring_std.h"
|
||||||
#ifdef WINDOWS
|
#ifdef WINDOWS
|
||||||
# include <windows.h>
|
# include <windows.h>
|
||||||
|
|||||||
@@ -19,7 +19,6 @@
|
|||||||
|
|
||||||
#include "piincludes.h"
|
#include "piincludes.h"
|
||||||
#include "piincludes_p.h"
|
#include "piincludes_p.h"
|
||||||
#include "piconsole.h"
|
|
||||||
#include "pitime.h"
|
#include "pitime.h"
|
||||||
#ifndef QNX
|
#ifndef QNX
|
||||||
# include <clocale>
|
# include <clocale>
|
||||||
|
|||||||
@@ -27,10 +27,9 @@
|
|||||||
# include <iostream>
|
# include <iostream>
|
||||||
#endif
|
#endif
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <mutex>
|
|
||||||
|
|
||||||
typedef std::mutex PIMutex;
|
class PIMutex;
|
||||||
//typedef std::lock_guard<std::mutex> PIMutexLocker;
|
class PIMutexLocker;
|
||||||
class PIObject;
|
class PIObject;
|
||||||
class PIString;
|
class PIString;
|
||||||
class PIByteArray;
|
class PIByteArray;
|
||||||
|
|||||||
@@ -51,6 +51,8 @@ public:
|
|||||||
|
|
||||||
PIString(const PIString & o): PIDeque<PIChar>() {*this += o;}
|
PIString(const PIString & o): PIDeque<PIChar>() {*this += o;}
|
||||||
|
|
||||||
|
PIString(PIString && o): PIDeque<PIChar>() {swap(o);}
|
||||||
|
|
||||||
|
|
||||||
//! Contructs string with single symbol "c"
|
//! Contructs string with single symbol "c"
|
||||||
PIString(const PIChar & c): PIDeque<PIChar>() {*this += c;}
|
PIString(const PIChar & c): PIDeque<PIChar>() {*this += c;}
|
||||||
@@ -89,6 +91,8 @@ public:
|
|||||||
|
|
||||||
PIString & operator =(const PIString & o) {if (this == &o) return *this; clear(); *this += o; return *this;}
|
PIString & operator =(const PIString & o) {if (this == &o) return *this; clear(); *this += o; return *this;}
|
||||||
|
|
||||||
|
PIString & operator =(PIString && o) {if (this == &o) return *this; swap(o); return *this;}
|
||||||
|
|
||||||
/*! \brief Return c-string representation of string
|
/*! \brief Return c-string representation of string
|
||||||
* \details Converts content of string to c-string and return
|
* \details Converts content of string to c-string and return
|
||||||
* pointer to first char. This buffer is valid until new convertion
|
* pointer to first char. This buffer is valid until new convertion
|
||||||
|
|||||||
@@ -83,6 +83,7 @@ public:
|
|||||||
PIStringList & operator =(const PIStringList & o) {PIDeque<PIString>::operator=(o); return *this;}
|
PIStringList & operator =(const PIStringList & o) {PIDeque<PIString>::operator=(o); return *this;}
|
||||||
|
|
||||||
PIStringList & operator <<(const PIString & str) {append(str); return *this;}
|
PIStringList & operator <<(const PIString & str) {append(str); return *this;}
|
||||||
|
PIStringList & operator <<(PIString && str) {append(str); return *this;}
|
||||||
PIStringList & operator <<(const PIStringList & sl) {append(sl); return *this;}
|
PIStringList & operator <<(const PIStringList & sl) {append(sl); return *this;}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,45 +0,0 @@
|
|||||||
/*
|
|
||||||
PIP - Platform Independent Primitives
|
|
||||||
Text codings coder, based on "iconv"
|
|
||||||
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 PIP_FREERTOS
|
|
||||||
|
|
||||||
#include "picodec.h"
|
|
||||||
|
|
||||||
|
|
||||||
PIStringList PICodec::availableCodecs() {
|
|
||||||
exec("/usr/bin/iconv", "-l");
|
|
||||||
waitForFinish();
|
|
||||||
PIString str(readOutput());
|
|
||||||
str.cutLeft(str.find("\n "));
|
|
||||||
str.replaceAll("\n", "");
|
|
||||||
return str.split("//");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
PIByteArray PICodec::exec_iconv(const PIString & from, const PIString & to, const PIByteArray & str) {
|
|
||||||
tf.openTemporary(PIIODevice::ReadWrite);
|
|
||||||
tf.clear();
|
|
||||||
tf << str;
|
|
||||||
tf.close();
|
|
||||||
exec("/usr/bin/iconv", PIStringList() << ("-f=" + from) << ("-t=" + to) << tf.path());
|
|
||||||
waitForFinish();
|
|
||||||
return readOutput();
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // PIP_FREERTOS
|
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
/*
|
|
||||||
PIP - Platform Independent Primitives
|
|
||||||
Text codings coder, based on "iconv"
|
|
||||||
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 PICODEC_H
|
|
||||||
#define PICODEC_H
|
|
||||||
|
|
||||||
#ifndef PIP_FREERTOS
|
|
||||||
|
|
||||||
#include "piprocess.h"
|
|
||||||
|
|
||||||
class PIP_EXPORT PICodec: protected PIProcess
|
|
||||||
{
|
|
||||||
PIOBJECT(PICodec)
|
|
||||||
public:
|
|
||||||
PICodec(): PIProcess() {setGrabOutput(true);}
|
|
||||||
PICodec(const PIString & from, const PIString & to): PIProcess() {setCodings(from, to);}
|
|
||||||
~PICodec() {tf.remove();}
|
|
||||||
|
|
||||||
void setFromCoding(const PIString & from) {c_from = from;}
|
|
||||||
void setToCoding(const PIString & to) {c_to = to;}
|
|
||||||
void setCodings(const PIString & from, const PIString & to) {c_from = from; c_to = to;}
|
|
||||||
|
|
||||||
PIStringList availableCodecs();
|
|
||||||
PIString encode(PIString & str) {return PIString(exec_iconv(c_from, c_to, str.toByteArray()));}
|
|
||||||
PIString encode(const PIByteArray & str) {return PIString(exec_iconv(c_from, c_to, str));}
|
|
||||||
PIString decode(PIString & str) {return PIString(exec_iconv(c_to, c_from, str.toByteArray()));}
|
|
||||||
PIString decode(const PIByteArray & str) {return PIString(exec_iconv(c_to, c_from, str));}
|
|
||||||
|
|
||||||
private:
|
|
||||||
PIByteArray exec_iconv(const PIString & from, const PIString & to, const PIByteArray & str);
|
|
||||||
|
|
||||||
PIString c_from, c_to;
|
|
||||||
PIFile tf;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // PIP_FREERTOS
|
|
||||||
#endif // PICODEC_H
|
|
||||||
@@ -20,7 +20,6 @@
|
|||||||
#ifndef PISYSTEMMODULE_H
|
#ifndef PISYSTEMMODULE_H
|
||||||
#define PISYSTEMMODULE_H
|
#define PISYSTEMMODULE_H
|
||||||
|
|
||||||
#include "picodec.h"
|
|
||||||
#include "pisignals.h"
|
#include "pisignals.h"
|
||||||
#include "pilibrary.h"
|
#include "pilibrary.h"
|
||||||
#include "pisysteminfo.h"
|
#include "pisysteminfo.h"
|
||||||
|
|||||||
@@ -17,8 +17,8 @@
|
|||||||
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_TESTS_PIBLOCKINGDEQUEUE_H
|
#ifndef PIBLOCKINGDEQUEUE_H
|
||||||
#define PIP_TESTS_PIBLOCKINGDEQUEUE_H
|
#define PIBLOCKINGDEQUEUE_H
|
||||||
|
|
||||||
#include "pideque.h"
|
#include "pideque.h"
|
||||||
#include "piconditionvar.h"
|
#include "piconditionvar.h"
|
||||||
@@ -140,14 +140,14 @@ public:
|
|||||||
* return value is retrieved value
|
* return value is retrieved value
|
||||||
* @return the head of this queue, or defaultVal if the specified waiting time elapses before an element is available
|
* @return the head of this queue, or defaultVal if the specified waiting time elapses before an element is available
|
||||||
*/
|
*/
|
||||||
T poll(int timeoutMs, const T & defaultVal = T(), bool* isOk = nullptr) {
|
T poll(int timeoutMs, const T & defaultVal = T(), bool * isOk = nullptr) {
|
||||||
T t;
|
T t;
|
||||||
mutex.lock();
|
mutex.lock();
|
||||||
bool isNotEmpty = cond_var_add->waitFor(mutex, timeoutMs, [&]() { return !PIDeque<T>::isEmpty(); });
|
bool isNotEmpty = cond_var_add->waitFor(mutex, timeoutMs, [&]() { return !PIDeque<T>::isEmpty(); });
|
||||||
t = isNotEmpty ? T(PIDeque<T>::take_front()) : defaultVal;
|
t = isNotEmpty ? T(PIDeque<T>::take_front()) : defaultVal;
|
||||||
mutex.unlock();
|
mutex.unlock();
|
||||||
if (isNotEmpty) cond_var_rem->notifyOne();
|
if (isNotEmpty) cond_var_rem->notifyOne();
|
||||||
if (isOk != nullptr) *isOk = isNotEmpty;
|
if (isOk) *isOk = isNotEmpty;
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -160,14 +160,14 @@ public:
|
|||||||
* return value is retrieved value
|
* return value is retrieved value
|
||||||
* @return the head of this queue, or defaultVal if the specified waiting time elapses before an element is available
|
* @return the head of this queue, or defaultVal if the specified waiting time elapses before an element is available
|
||||||
*/
|
*/
|
||||||
T poll(const T & defaultVal = T(), bool* isOk = nullptr) {
|
T poll(const T & defaultVal = T(), bool * isOk = nullptr) {
|
||||||
T t;
|
T t;
|
||||||
mutex.lock();
|
mutex.lock();
|
||||||
bool isNotEmpty = !PIDeque<T>::isEmpty();
|
bool isNotEmpty = !PIDeque<T>::isEmpty();
|
||||||
t = isNotEmpty ? T(PIDeque<T>::take_front()) : defaultVal;
|
t = isNotEmpty ? T(PIDeque<T>::take_front()) : defaultVal;
|
||||||
mutex.unlock();
|
mutex.unlock();
|
||||||
if (isNotEmpty) cond_var_rem->notifyOne();
|
if (isNotEmpty) cond_var_rem->notifyOne();
|
||||||
if (isOk != nullptr) *isOk = isNotEmpty;
|
if (isOk) *isOk = isNotEmpty;
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -213,7 +213,7 @@ public:
|
|||||||
*/
|
*/
|
||||||
size_t drainTo(PIDeque<T>& other, size_t maxCount = SIZE_MAX) {
|
size_t drainTo(PIDeque<T>& other, size_t maxCount = SIZE_MAX) {
|
||||||
mutex.lock();
|
mutex.lock();
|
||||||
size_t count = maxCount > PIDeque<T>::size() ? PIDeque<T>::size() : maxCount;
|
size_t count = ((maxCount > PIDeque<T>::size()) ? PIDeque<T>::size() : maxCount);
|
||||||
for (size_t i = 0; i < count; ++i) other.push_back(PIDeque<T>::take_front());
|
for (size_t i = 0; i < count; ++i) other.push_back(PIDeque<T>::take_front());
|
||||||
mutex.unlock();
|
mutex.unlock();
|
||||||
return count;
|
return count;
|
||||||
@@ -235,11 +235,11 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PIConditionLock mutex;
|
PIMutex mutex;
|
||||||
PIConditionVariable* cond_var_add;
|
PIConditionVariable * cond_var_add, * cond_var_rem;
|
||||||
PIConditionVariable* cond_var_rem;
|
|
||||||
size_t max_size;
|
size_t max_size;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif //PIP_TESTS_PIBLOCKINGDEQUEUE_H
|
#endif // PIBLOCKINGDEQUEUE_H
|
||||||
@@ -35,7 +35,7 @@ PRIVATE_DEFINITION_START(PIConditionVariable)
|
|||||||
CONDITION_VARIABLE nativeHandle;
|
CONDITION_VARIABLE nativeHandle;
|
||||||
#else
|
#else
|
||||||
pthread_cond_t nativeHandle;
|
pthread_cond_t nativeHandle;
|
||||||
PIConditionLock* currentLock;
|
PIMutex * currentLock;
|
||||||
#endif
|
#endif
|
||||||
bool isDestroying;
|
bool isDestroying;
|
||||||
PRIVATE_DEFINITION_END(PIConditionVariable)
|
PRIVATE_DEFINITION_END(PIConditionVariable)
|
||||||
@@ -61,7 +61,7 @@ PIConditionVariable::~PIConditionVariable() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void PIConditionVariable::wait(PIConditionLock& lk) {
|
void PIConditionVariable::wait(PIMutex& lk) {
|
||||||
#ifdef WINDOWS
|
#ifdef WINDOWS
|
||||||
SleepConditionVariableCS(&PRIVATE->nativeHandle, (PCRITICAL_SECTION)lk.handle(), INFINITE);
|
SleepConditionVariableCS(&PRIVATE->nativeHandle, (PCRITICAL_SECTION)lk.handle(), INFINITE);
|
||||||
#else
|
#else
|
||||||
@@ -70,7 +70,7 @@ void PIConditionVariable::wait(PIConditionLock& lk) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void PIConditionVariable::wait(PIConditionLock& lk, const std::function<bool()>& condition) {
|
void PIConditionVariable::wait(PIMutex& lk, const std::function<bool()>& condition) {
|
||||||
bool isCondition;
|
bool isCondition;
|
||||||
while (true) {
|
while (true) {
|
||||||
isCondition = condition();
|
isCondition = condition();
|
||||||
@@ -85,7 +85,7 @@ void PIConditionVariable::wait(PIConditionLock& lk, const std::function<bool()>&
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool PIConditionVariable::waitFor(PIConditionLock &lk, int timeoutMs) {
|
bool PIConditionVariable::waitFor(PIMutex &lk, int timeoutMs) {
|
||||||
bool isNotTimeout;
|
bool isNotTimeout;
|
||||||
#ifdef WINDOWS
|
#ifdef WINDOWS
|
||||||
isNotTimeout = SleepConditionVariableCS(&PRIVATE->nativeHandle, (PCRITICAL_SECTION)lk.handle(), timeoutMs) != 0;
|
isNotTimeout = SleepConditionVariableCS(&PRIVATE->nativeHandle, (PCRITICAL_SECTION)lk.handle(), timeoutMs) != 0;
|
||||||
@@ -98,7 +98,7 @@ bool PIConditionVariable::waitFor(PIConditionLock &lk, int timeoutMs) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool PIConditionVariable::waitFor(PIConditionLock& lk, int timeoutMs, const std::function<bool()> &condition) {
|
bool PIConditionVariable::waitFor(PIMutex& lk, int timeoutMs, const std::function<bool()> &condition) {
|
||||||
bool isCondition;
|
bool isCondition;
|
||||||
PITimeMeasurer measurer;
|
PITimeMeasurer measurer;
|
||||||
while (true) {
|
while (true) {
|
||||||
@@ -20,14 +20,13 @@
|
|||||||
#ifndef PICONDITIONVAR_H
|
#ifndef PICONDITIONVAR_H
|
||||||
#define PICONDITIONVAR_H
|
#define PICONDITIONVAR_H
|
||||||
|
|
||||||
#include "piconditionlock.h"
|
|
||||||
#include "pithread.h"
|
#include "pithread.h"
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief A condition variable is an object able to block the calling thread until notified to resume.
|
* @brief A condition variable is an object able to block the calling thread until notified to resume.
|
||||||
*
|
*
|
||||||
* It uses a PIConditionLock to lock the thread when one of its wait functions is called. The thread remains
|
* It uses a PIMutex to lock the thread when one of its wait functions is called. The thread remains
|
||||||
* blocked until woken up by another thread that calls a notification function on the same PIConditionVariable object.
|
* blocked until woken up by another thread that calls a notification function on the same PIConditionVariable object.
|
||||||
*/
|
*/
|
||||||
class PIP_EXPORT PIConditionVariable {
|
class PIP_EXPORT PIConditionVariable {
|
||||||
@@ -49,20 +48,20 @@ public:
|
|||||||
void notifyAll();
|
void notifyAll();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief see wait(PIConditionLock&, const std::function<bool()>&)
|
* @brief see wait(PIMutex &, const std::function<bool()>&)
|
||||||
*/
|
*/
|
||||||
virtual void wait(PIConditionLock& lk);
|
virtual void wait(PIMutex & lk);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Wait until notified
|
* @brief Wait until notified
|
||||||
*
|
*
|
||||||
* The execution of the current thread (which shall have locked with lk method PIConditionLock::lock()) is blocked
|
* The execution of the current thread (which shall have locked with lk method PIMutex::lock()) is blocked
|
||||||
* until notified.
|
* until notified.
|
||||||
*
|
*
|
||||||
* At the moment of blocking the thread, the function automatically calls lk.unlock() (PIConditionLock::unlock()),
|
* At the moment of blocking the thread, the function automatically calls lk.unlock() (PIMutex::unlock()),
|
||||||
* allowing other locked threads to continue.
|
* allowing other locked threads to continue.
|
||||||
*
|
*
|
||||||
* Once notified (explicitly, by some other thread), the function unblocks and calls lk.lock() (PIConditionLock::lock()),
|
* Once notified (explicitly, by some other thread), the function unblocks and calls lk.lock() (PIMutex::lock()),
|
||||||
* leaving lk in the same state as when the function was called. Then the function returns (notice that this last mutex
|
* leaving lk in the same state as when the function was called. Then the function returns (notice that this last mutex
|
||||||
* locking may block again the thread before returning).
|
* locking may block again the thread before returning).
|
||||||
*
|
*
|
||||||
@@ -77,23 +76,23 @@ public:
|
|||||||
* @param condition A callable object or function that takes no arguments and returns a value that can be evaluated
|
* @param condition A callable object or function that takes no arguments and returns a value that can be evaluated
|
||||||
* as a bool. This is called repeatedly until it evaluates to true.
|
* as a bool. This is called repeatedly until it evaluates to true.
|
||||||
*/
|
*/
|
||||||
virtual void wait(PIConditionLock& lk, const std::function<bool()>& condition);
|
virtual void wait(PIMutex& lk, const std::function<bool()>& condition);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief see waitFor(PIConditionLock&, int, const std::function<bool()>&)
|
* @brief see waitFor(PIMutex &, int, const std::function<bool()>&)
|
||||||
*/
|
*/
|
||||||
virtual bool waitFor(PIConditionLock& lk, int timeoutMs);
|
virtual bool waitFor(PIMutex & lk, int timeoutMs);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Wait for timeout or until notified
|
* @brief Wait for timeout or until notified
|
||||||
*
|
*
|
||||||
* The execution of the current thread (which shall have locked with lk method PIConditionLock::lock()) is blocked
|
* The execution of the current thread (which shall have locked with lk method PIMutex::lock()) is blocked
|
||||||
* during timeoutMs, or until notified (if the latter happens first).
|
* during timeoutMs, or until notified (if the latter happens first).
|
||||||
*
|
*
|
||||||
* At the moment of blocking the thread, the function automatically calls lk.lock() (PIConditionLock::lock()), allowing
|
* At the moment of blocking the thread, the function automatically calls lk.lock() (PIMutex::lock()), allowing
|
||||||
* other locked threads to continue.
|
* other locked threads to continue.
|
||||||
*
|
*
|
||||||
* Once notified or once timeoutMs has passed, the function unblocks and calls lk.unlock() (PIConditionLock::unlock()),
|
* Once notified or once timeoutMs has passed, the function unblocks and calls lk.unlock() (PIMutex::unlock()),
|
||||||
* leaving lk in the same state as when the function was called. Then the function returns (notice that this last
|
* leaving lk in the same state as when the function was called. Then the function returns (notice that this last
|
||||||
* mutex locking may block again the thread before returning).
|
* mutex locking may block again the thread before returning).
|
||||||
*
|
*
|
||||||
@@ -109,7 +108,7 @@ public:
|
|||||||
* as a bool. This is called repeatedly until it evaluates to true.
|
* as a bool. This is called repeatedly until it evaluates to true.
|
||||||
* @return false if timeout reached or true if wakeup condition is true
|
* @return false if timeout reached or true if wakeup condition is true
|
||||||
*/
|
*/
|
||||||
virtual bool waitFor(PIConditionLock& lk, int timeoutMs, const std::function<bool()>& condition);
|
virtual bool waitFor(PIMutex& lk, int timeoutMs, const std::function<bool()>& condition);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PRIVATE_DECLARATION
|
PRIVATE_DECLARATION
|
||||||
122
lib/main/thread/pimutex.cpp
Normal file
122
lib/main/thread/pimutex.cpp
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
/*
|
||||||
|
PIP - Platform Independent Primitives
|
||||||
|
Mutex
|
||||||
|
Ivan Pelipenko peri4ko@yandex.ru, Stephan Fomenko, 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** \class PIMutex
|
||||||
|
* \brief Mutex
|
||||||
|
* \details
|
||||||
|
* \section PIMutex_sec0 Synopsis
|
||||||
|
* %PIMutex provides synchronization blocks between several threads.
|
||||||
|
* Using mutex guarantees execution of some code only one of threads.
|
||||||
|
* Mutex contains logic state and functions to change it: \a lock(),
|
||||||
|
* \a unlock() and \a tryLock().
|
||||||
|
*
|
||||||
|
* \section PIMutex_sec1 Usage
|
||||||
|
* Block of code that should to be executed only one thread simultaniously
|
||||||
|
* should to be started with \a lock() and ended with \a unlock().
|
||||||
|
* \snippet pimutex.cpp main
|
||||||
|
* "mutex" in this example is one for all threads.
|
||||||
|
*
|
||||||
|
* */
|
||||||
|
|
||||||
|
#include "pimutex.h"
|
||||||
|
#include "piincludes_p.h"
|
||||||
|
#ifdef WINDOWS
|
||||||
|
# include <synchapi.h>
|
||||||
|
#else
|
||||||
|
# include <pthread.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
PRIVATE_DEFINITION_START(PIMutex)
|
||||||
|
#ifdef WINDOWS
|
||||||
|
CRITICAL_SECTION
|
||||||
|
#else
|
||||||
|
pthread_mutex_t
|
||||||
|
#endif
|
||||||
|
mutex;
|
||||||
|
PRIVATE_DEFINITION_END(PIMutex)
|
||||||
|
|
||||||
|
|
||||||
|
PIMutex::PIMutex() {
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PIMutex::~PIMutex() {
|
||||||
|
destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PIMutex::lock() {
|
||||||
|
#ifdef WINDOWS
|
||||||
|
EnterCriticalSection(&(PRIVATE->mutex));
|
||||||
|
#else
|
||||||
|
pthread_mutex_lock(&(PRIVATE->mutex));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PIMutex::unlock() {
|
||||||
|
#ifdef WINDOWS
|
||||||
|
LeaveCriticalSection(&(PRIVATE->mutex));
|
||||||
|
#else
|
||||||
|
pthread_mutex_unlock(&(PRIVATE->mutex));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool PIMutex::tryLock() {
|
||||||
|
bool ret =
|
||||||
|
#ifdef WINDOWS
|
||||||
|
(TryEnterCriticalSection(&(PRIVATE->mutex)) != 0);
|
||||||
|
#else
|
||||||
|
(pthread_mutex_trylock(&(PRIVATE->mutex)) == 0);
|
||||||
|
#endif
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void * PIMutex::handle() {
|
||||||
|
return (void*)&(PRIVATE->mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PIMutex::init() {
|
||||||
|
#ifdef WINDOWS
|
||||||
|
InitializeCriticalSection(&(PRIVATE->mutex));
|
||||||
|
#else
|
||||||
|
pthread_mutexattr_t attr;
|
||||||
|
memset(&attr, 0, sizeof(attr));
|
||||||
|
pthread_mutexattr_init(&attr);
|
||||||
|
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL);
|
||||||
|
memset(&(PRIVATE->mutex), 0, sizeof(PRIVATE->mutex));
|
||||||
|
pthread_mutex_init(&(PRIVATE->mutex), &attr);
|
||||||
|
pthread_mutexattr_destroy(&attr);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PIMutex::destroy() {
|
||||||
|
#ifdef WINDOWS
|
||||||
|
DeleteCriticalSection(&(PRIVATE->mutex));
|
||||||
|
#else
|
||||||
|
pthread_mutex_destroy(&(PRIVATE->mutex));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
/*
|
/*
|
||||||
PIP - Platform Independent Primitives
|
PIP - Platform Independent Primitives
|
||||||
PIMutexLocker
|
PIMutexLocker
|
||||||
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
|
Ivan Pelipenko peri4ko@yandex.ru, Stephan Fomenko, 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
|
||||||
@@ -24,6 +24,45 @@
|
|||||||
#define PIMUTEX_H
|
#define PIMUTEX_H
|
||||||
|
|
||||||
#include "piinit.h"
|
#include "piinit.h"
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
|
|
||||||
|
class PIP_EXPORT PIMutex
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NO_COPY_CLASS(PIMutex)
|
||||||
|
|
||||||
|
//! Constructs unlocked mutex
|
||||||
|
explicit PIMutex();
|
||||||
|
|
||||||
|
//! Destroy mutex
|
||||||
|
~PIMutex();
|
||||||
|
|
||||||
|
|
||||||
|
//! \brief Lock mutex
|
||||||
|
//! \details If mutex is unlocked it set to locked state and returns immediate.
|
||||||
|
//! If mutex is already locked function blocks until mutex will be unlocked
|
||||||
|
void lock();
|
||||||
|
|
||||||
|
//! \brief Unlock mutex
|
||||||
|
//! \details In any case this function returns immediate
|
||||||
|
void unlock() ;
|
||||||
|
|
||||||
|
//! \brief Try to lock mutex
|
||||||
|
//! \details If mutex is unlocked it set to locked state and returns "true" immediate.
|
||||||
|
//! If mutex is already locked function returns immediate an returns "false"
|
||||||
|
bool tryLock();
|
||||||
|
|
||||||
|
void * handle();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void init();
|
||||||
|
void destroy();
|
||||||
|
|
||||||
|
PRIVATE_DECLARATION
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
//! \brief PIMutexLocker
|
//! \brief PIMutexLocker
|
||||||
//! \details Same as std::lock_guard<std::mutex>.
|
//! \details Same as std::lock_guard<std::mutex>.
|
||||||
@@ -40,7 +79,7 @@ public:
|
|||||||
~PIMutexLocker() {if (cond) mutex.unlock();}
|
~PIMutexLocker() {if (cond) mutex.unlock();}
|
||||||
private:
|
private:
|
||||||
PIMutex & mutex;
|
PIMutex & mutex;
|
||||||
std::atomic_bool cond;
|
bool cond;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // PIMUTEX_H
|
#endif // PIMUTEX_H
|
||||||
|
|||||||
@@ -25,5 +25,7 @@
|
|||||||
#include "pitimer.h"
|
#include "pitimer.h"
|
||||||
#include "pipipelinethread.h"
|
#include "pipipelinethread.h"
|
||||||
#include "pigrabberbase.h"
|
#include "pigrabberbase.h"
|
||||||
|
#include "pithreadpoolexecutor.h"
|
||||||
|
#include "piconditionvar.h"
|
||||||
|
|
||||||
#endif // PITHREADMODULE_H
|
#endif // PITHREADMODULE_H
|
||||||
|
|||||||
@@ -17,10 +17,24 @@
|
|||||||
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 "executor.h"
|
#include "pithreadpoolexecutor.h"
|
||||||
|
#include "pisysteminfo.h"
|
||||||
|
|
||||||
|
/*! \class PIThreadPoolExecutor
|
||||||
|
* @brief Thread pools address two different problems: they usually provide improved performance when executing large
|
||||||
|
* numbers of asynchronous tasks, due to reduced per-task invocation overhead, and they provide a means of bounding and
|
||||||
|
* managing the resources, including threads, consumed when executing a collection of tasks.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
PIThreadPoolExecutor::PIThreadPoolExecutor(size_t corePoolSize, PIBlockingDequeue<std::function<void()>> *taskQueue_) : isShutdown_(false), taskQueue(taskQueue_) {
|
PIThreadPoolExecutor::PIThreadPoolExecutor(size_t corePoolSize, PIBlockingDequeue<std::function<void()> > * taskQueue_) : isShutdown_(false) {
|
||||||
|
queue_own = false;
|
||||||
|
if (corePoolSize <= 0)
|
||||||
|
corePoolSize = PISystemInfo::instance()->processorsCount;
|
||||||
|
if (!taskQueue_) {
|
||||||
|
taskQueue = new PIBlockingDequeue<std::function<void()> >();
|
||||||
|
queue_own = true;
|
||||||
|
}
|
||||||
for (size_t i = 0; i < corePoolSize; ++i) {
|
for (size_t i = 0; i < corePoolSize; ++i) {
|
||||||
PIThread * thread = new PIThread([&, i](){
|
PIThread * thread = new PIThread([&, i](){
|
||||||
auto runnable = taskQueue->poll(100, std::function<void()>());
|
auto runnable = taskQueue->poll(100, std::function<void()>());
|
||||||
@@ -55,11 +69,12 @@ void PIThreadPoolExecutor::shutdownNow() {
|
|||||||
PIThreadPoolExecutor::~PIThreadPoolExecutor() {
|
PIThreadPoolExecutor::~PIThreadPoolExecutor() {
|
||||||
shutdownNow();
|
shutdownNow();
|
||||||
while (threadPool.size() > 0) delete threadPool.take_back();
|
while (threadPool.size() > 0) delete threadPool.take_back();
|
||||||
delete taskQueue;
|
if (queue_own)
|
||||||
|
delete taskQueue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void PIThreadPoolExecutor::execute(const std::function<void()> &runnable) {
|
void PIThreadPoolExecutor::execute(const std::function<void()> & runnable) {
|
||||||
if (!isShutdown_) taskQueue->offer(runnable);
|
if (!isShutdown_) taskQueue->offer(runnable);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -17,20 +17,16 @@
|
|||||||
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_TESTS_EXECUTOR_H
|
#ifndef PITHREADPOOLEXECUTOR_H
|
||||||
#define PIP_TESTS_EXECUTOR_H
|
#define PITHREADPOOLEXECUTOR_H
|
||||||
|
|
||||||
#include "piblockingdequeue.h"
|
#include "piblockingdequeue.h"
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Thread pools address two different problems: they usually provide improved performance when executing large
|
|
||||||
* numbers of asynchronous tasks, due to reduced per-task invocation overhead, and they provide a means of bounding and
|
|
||||||
* managing the resources, including threads, consumed when executing a collection of tasks.
|
|
||||||
*/
|
|
||||||
class PIThreadPoolExecutor {
|
class PIThreadPoolExecutor {
|
||||||
public:
|
public:
|
||||||
explicit PIThreadPoolExecutor(size_t corePoolSize = 1, PIBlockingDequeue<std::function<void()> >* taskQueue_ = new PIBlockingDequeue<std::function<void()> >());
|
explicit PIThreadPoolExecutor(size_t corePoolSize = -1, PIBlockingDequeue<std::function<void()> > * taskQueue_ = 0);
|
||||||
|
|
||||||
virtual ~PIThreadPoolExecutor();
|
virtual ~PIThreadPoolExecutor();
|
||||||
|
|
||||||
@@ -41,7 +37,7 @@ public:
|
|||||||
*
|
*
|
||||||
* @param runnable not empty function for thread pool execution
|
* @param runnable not empty function for thread pool execution
|
||||||
*/
|
*/
|
||||||
void execute(const std::function<void()>& runnable);
|
void execute(const std::function<void()> & runnable);
|
||||||
|
|
||||||
void shutdownNow();
|
void shutdownNow();
|
||||||
|
|
||||||
@@ -55,10 +51,13 @@ public:
|
|||||||
bool isShutdown() const;
|
bool isShutdown() const;
|
||||||
|
|
||||||
bool awaitTermination(int timeoutMs);
|
bool awaitTermination(int timeoutMs);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::atomic_bool isShutdown_;
|
std::atomic_bool isShutdown_;
|
||||||
PIBlockingDequeue<std::function<void()> >* taskQueue;
|
PIBlockingDequeue<std::function<void()> > * taskQueue;
|
||||||
PIVector<PIThread*> threadPool;
|
PIVector<PIThread*> threadPool;
|
||||||
|
bool queue_own;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //PIP_TESTS_EXECUTOR_H
|
#endif // PITHREADPOOLEXECUTOR_H
|
||||||
28
main.cpp
28
main.cpp
@@ -1,5 +1,5 @@
|
|||||||
#include "pip.h"
|
#include "pip.h"
|
||||||
#ifdef PIP_LUA
|
/*#ifdef PIP_LUA
|
||||||
#include "piluaprogram.h"
|
#include "piluaprogram.h"
|
||||||
|
|
||||||
static const char * script
|
static const char * script
|
||||||
@@ -30,3 +30,29 @@ int main() {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "picodeparser.h"
|
||||||
|
int main() {
|
||||||
|
piDebug = false;
|
||||||
|
double min = -1, max = -1, mean = 0;
|
||||||
|
for (int i = 0; i < 50; ++i) {
|
||||||
|
PITimeMeasurer tm;
|
||||||
|
/*PICodeParser cp;
|
||||||
|
cp.parseFile("SH_plugin_base.h");*/
|
||||||
|
PIStringList sl;
|
||||||
|
for (int i = 0; i < 5000; ++i) {
|
||||||
|
//PIString s("1234567890-=");
|
||||||
|
//sl << s;
|
||||||
|
sl << PIString("1234567890-=");
|
||||||
|
}
|
||||||
|
double ms = tm.elapsed_m();
|
||||||
|
if (min < 0) min = ms;
|
||||||
|
if (max < 0) max = ms;
|
||||||
|
min = piMin(min, ms);
|
||||||
|
max = piMax(max, ms);
|
||||||
|
mean += ms;
|
||||||
|
}
|
||||||
|
piDebug = true;
|
||||||
|
piCout << min << (mean / 50) << max;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user